day79:luffy:注冊之對手機號的驗證&實現基本的注冊功能邏輯&點擊獲取驗證碼&redis


目錄

1.前端和后端對於手機號的驗證

2.實現基本的注冊功能-不包括驗證碼

3.點擊獲取驗證碼

4.解決登錄不上Xadmin的bug

5.redis

register.vue頁面

<template>
    <div class="login box">
        <img src="../../static/img/Loginbg.3377d0c.jpg" alt="">
        <div class="login">
            <div class="login-title">
                <img src="../../static/img/Logotitle.1ba5466.png" alt="">
                <p>幫助有志向的年輕人通過努力學習獲得體面的工作和生活!</p>
            </div>
            <div class="login_box">
                <div class="title">
                    <span @click="login_type=0">密碼登錄</span>
                    <span @click="login_type=1">短信登錄</span>
                </div>
                <div class="inp" v-if="login_type==0">
                    <input v-model = "username" type="text" placeholder="用戶名 / 手機號碼" class="user">
                    <input v-model = "password" type="password" name="" class="pwd" placeholder="密碼">
                    <div id="geetest1"></div>
                    <div class="rember">
                        <p>
                            <input type="checkbox" class="no" name="a" v-model="remember"/>
                            <span>記住密碼</span>
                        </p>
                        <p>忘記密碼</p>
                    </div>
                    <button class="login_btn" @click="loginHandle">登錄</button>
          <p class="go_login" >沒有賬號 <router-link to="/user/register">立即注冊</router-link></p>
                </div>
                <div class="inp" v-show="login_type==1">
                    <input v-model = "username" type="text" placeholder="手機號碼" class="user">
                    <input v-model = "password"  type="text" class="pwd" placeholder="短信驗證碼">
          <button id="get_code">獲取驗證碼</button>
                    <button class="login_btn">登錄</button>
                    <p class="go_login" >沒有賬號 <span>立即注冊</span></p>
                </div>
            </div>
        </div>
    </div>
</template>

<script>
export default {
  name: 'Login',
  data(){
    return {
        login_type: 0,
        username:"",
        password:"",
        remember:false,
    }
  },

 methods:{
    loginHandle(){
      var captcha1 = new TencentCaptcha('2095582704', (res) =>{
        if (res.ret === 0){

          this.$axios.post(`${this.$settings.Host}/users/login/`,{
            username:this.username,
            password:this.password,
            ticket:res.ticket,
            randstr:res.randstr,

          }).then((res)=>{
            console.log(res);
            // console.log(this.remember);
            if (this.remember){
              localStorage.token = res.data.token;
              localStorage.username = res.data.username;
              localStorage.id = res.data.id;
              sessionStorage.removeItem('token');
              sessionStorage.removeItem('username');
              sessionStorage.removeItem('id');

            }else {
              sessionStorage.token = res.data.token;
              sessionStorage.username = res.data.username;
              sessionStorage.id = res.data.id;
              localStorage.removeItem('token');
              localStorage.removeItem('username');
              localStorage.removeItem('id');
            }

            this.$confirm('下一步想去哪消費!', '提示', {
                confirmButtonText: '去首頁',
                cancelButtonText: '去個人中心',
                type: 'success'
              }).then(() => {
                this.$router.push('/');
              }).catch(() => {
                this.$router.push('/person');
              });


          }).catch((error)=>{
            this.$alert('用戶名或者密碼錯誤', '登錄失敗', {
              confirmButtonText: '確定',

            });
          })
        }
      });
      captcha1.show(); // 顯示驗證碼



    }

  },

};
</script>

<style scoped>
.box{
    width: 100%;
  height: 100%;
    position: relative;
  overflow: hidden;
}
.box img{
    width: 100%;
  min-height: 100%;
}
.box .login {
    position: absolute;
    width: 500px;
    height: 400px;
    top: 0;
    left: 0;
  margin: auto;
  right: 0;
  bottom: 0;
  top: -338px;
}
.login .login-title{
     width: 100%;
    text-align: center;
}
.login-title img{
    width: 190px;
    height: auto;
}
.login-title p{
    font-family: PingFangSC-Regular;
    font-size: 18px;
    color: #fff;
    letter-spacing: .29px;
    padding-top: 10px;
    padding-bottom: 50px;
}
.login_box{
    width: 400px;
    height: auto;
    background: #fff;
    box-shadow: 0 2px 4px 0 rgba(0,0,0,.5);
    border-radius: 4px;
    margin: 0 auto;
    padding-bottom: 40px;
}
.login_box .title{
    font-size: 20px;
    color: #9b9b9b;
    letter-spacing: .32px;
    border-bottom: 1px solid #e6e6e6;
     display: flex;
        justify-content: space-around;
        padding: 50px 60px 0 60px;
        margin-bottom: 20px;
        cursor: pointer;
}
.login_box .title span:nth-of-type(1){
    color: #4a4a4a;
        border-bottom: 2px solid #84cc39;
}

.inp{
    width: 350px;
    margin: 0 auto;
}
.inp input{
    border: 0;
    outline: 0;
    width: 100%;
    height: 45px;
    border-radius: 4px;
    border: 1px solid #d9d9d9;
    text-indent: 20px;
    font-size: 14px;
    background: #fff !important;
}
.inp input.user{
    margin-bottom: 16px;
}
.inp .rember{
     display: flex;
    justify-content: space-between;
    align-items: center;
    position: relative;
    margin-top: 10px;
}
.inp .rember p:first-of-type{
    font-size: 12px;
    color: #4a4a4a;
    letter-spacing: .19px;
    margin-left: 22px;
    display: -ms-flexbox;
    display: flex;
    -ms-flex-align: center;
    align-items: center;
    /*position: relative;*/
}
.inp .rember p:nth-of-type(2){
    font-size: 14px;
    color: #9b9b9b;
    letter-spacing: .19px;
    cursor: pointer;
}

.inp .rember input{
    outline: 0;
    width: 30px;
    height: 45px;
    border-radius: 4px;
    border: 1px solid #d9d9d9;
    text-indent: 20px;
    font-size: 14px;
    background: #fff !important;
}

.inp .rember p span{
    display: inline-block;
  font-size: 12px;
  width: 100px;
  /*position: absolute;*/
/*left: 20px;*/

}
#geetest{
    margin-top: 20px;
}
.login_btn{
     width: 100%;
    height: 45px;
    background: #84cc39;
    border-radius: 5px;
    font-size: 16px;
    color: #fff;
    letter-spacing: .26px;
    margin-top: 30px;
}
.inp .go_login{
    text-align: center;
    font-size: 14px;
    color: #9b9b9b;
    letter-spacing: .26px;
    padding-top: 20px;
}
.inp .go_login span{
    color: #84cc39;
    cursor: pointer;
}
</style>

1.前端和后端對於手機號的驗證

1.將注冊的幾個輸入框和js中的數據設置好數據驅動視圖 :v-model

// 修改input框中的相關的值
    <input v-model = "mobile" type="text" placeholder="手機號碼" class="user" @blur="checkPhone">
                    <input v-model = "password" type="password" placeholder="密碼" class="user">
                    <input v-model = "r_password" type="password" placeholder="確認密碼" class="user">
                        
// 修改js中data的相關值
  data(){
    return {
        sms:"",
        mobile:"",
        password:"",
        r_password:"",
        validateResult:false,
    }                  

2.前端對輸入的手機號長度做校驗

給手機號的輸入框綁定一個鼠標離開的事件,當用戶輸入手機號之后離開輸入框,會對手機號格式進行校驗

<!-- html -->
    <input v-model = "mobile" type="text" placeholder="手機號碼" class="user" @blur="checkPhone">
// js
methods:{
    checkPhone(){

      let phoneNumber = this.mobile;
      // 前端
      let reg = /^1[3-9][0-9]{9}$/;
      if (!reg.test(phoneNumber)){ // 前端檢測手機號長度是否符合要求
        this.$message.error('手機號 格式 error');
        return false;
      }
       // 如果前端驗證手機號長度沒問題,就向后端發起請求
       this.$axios.get(`${this.$settings.Host}/users/check_phone/?phone=${phoneNumber}`)  // request.GET.get(phone)
      .then((res)=>{
        console.log(res);
      }).catch((error)=>{
        this.$message.error(error.response.data.error_msg);
      })

    },

關於手機號的校驗:現在我們想達到的效果是:在前端進行對手機號的格式校驗,只要用戶輸入的手機號格式有問題,會立刻出現彈窗:手機號格式錯誤。(且前端只能對手機號的格式進行校驗)

比如:你想驗證手機號是不是已經存在 這種邏輯就沒有辦法放到前端去做,因為手機號都存儲在數據庫中,所以如果想驗證手機號是否存在,肯定是后端要做相關邏輯。

也就是:

前端驗證手機號格式

后端驗證手機號格式加手機號是否已經存在

3.后端設置接口:驗證手機號格式和手機號唯一性

users/urls.py

# urls.py
from rest_framework_jwt.views import obtain_jwt_token,verify_jwt_token
from django.urls import path
from . import views

urlpatterns = [
    ......
    path(r'/check_phone/',views.CheckPhoneNumber.as_view())
]

users/views.py

# views.py

import re
from rest_framework.views import APIView
from rest_framework.response import Response
from .utils import get_user_obj

......
        
class CheckPhoneNumber(APIView):

    def get(self,request):
        phone_number = request.GET.get('phone')
        
        # 驗證手機號格式
        if not re.match('^1[3-9][0-9]{9}$', phone_number):  # 格式不對
            return Response({'error_msg':'手機號格式有誤,請重新輸入!'}, status=status.HTTP_400_BAD_REQUEST)
        
        # 驗證手機號唯一性
        ret = get_user_obj(phone_number)
        if ret:
            return Response({'error_msg': '手機號已被注冊,請換手機號'}, status=status.HTTP_400_BAD_REQUEST)

        return Response({'msg': 'ok'})

現在前端和后端的校驗都已經編寫完畢,讓我們看一下效果

2.實現基本的注冊功能-不包括驗證碼

1.注冊功能的流程

2.注冊-前端

點擊注冊按鈕,將輸入框中的數據發送到后端

<!-- html -->
<button class="register_btn" @click="registerHandler">注冊</button>
// js
 methods:{
  
    ......
    registerHandler(){

      this.$axios.post(`${this.$settings.Host}/`,{
        // 將輸入框的四項一並提交到后台
        sms:this.sms,
        mobile:this.mobile,
        password:this.password,
        r_password:this.r_password,
      }).then((res)=>{

      }).catch((error)=>{

      })


    },

3.注冊-后端接口

users/urls.py

# urls.py
from rest_framework_jwt.views import obtain_jwt_token,verify_jwt_token
from django.urls import path
from . import views

urlpatterns = [
    ......
    path(r'register/', views.RegisterView.as_view()),
]

users/views.py

# views.py
class RegisterView(CreateAPIView):
    queryset = models.User.objects.all()
    serializer_class = RegisterModelSerializer

user/serializers.py

反序列化需要的字段:phone password r_password sms

序列化需要的字段:id token phone

反序列化之后需要存到數據庫的字段:phone password

# serializers.py
class RegisterModelSerializer(serializers.ModelSerializer):
    '''
    sms,r_password這兩個字段只需要write_only=True
    意思是:反序列化校驗的時候,這兩個字段必須要傳遞給我
    但是序列化返回數據的時候,這兩個字段是不序列化出來的
    
    id,token這兩個字段只需要read_only=True
    意思是:反序列化校驗的時候,這些字段是無需校驗的
    但是序列化返回數據的時候,必須要返回這兩個數據
    '''
    id = serializers.IntegerField(read_only=True) 
    
    # sms和r_password這兩個字段數據庫並沒有,但是反序列化的時候還需要校驗這兩個字段,所以需要在這寫這兩個字段
    # 將兩個字段設置為write_only=True的原因是因為:驗證碼和確認密碼這兩個字段只做反序列化校驗功能,不需要序列化返回到前端 
    sms = serializers.CharField(max_length=6, min_length=4, write_only=True)  # '3333'
    r_password = serializers.CharField(write_only=True)
    
    token = serializers.CharField(read_only=True)  # 后端需要給前端傳遞token

    class Meta:
        model = models.User
        fields = ['id', 'phone', 'password', 'r_password', 'sms', 'token']
        extra_kwargs = {
            'password': {'write_only': True},
        }


    # 校驗密碼和確認密碼
    def validate(self, attrs):
        # 校驗手機號
        phone_number = attrs.get('phone')
        
        # 后端校驗手機號格式是否正確
        if not re.match('^1[3-9][0-9]{9}$', phone_number):
            raise serializers.ValidationError('手機號格式不對')
       
        # 驗證手機號是否已經存在
        ret = get_user_obj(phone_number)
        if ret:
            raise serializers.ValidationError('手機號已經存在!!')
        p1 = attrs.get('password')
        p2 = attrs.get('r_password')
        
        # 驗證密碼和確認密碼是否一致
        if p1 != p2:
            raise serializers.ValidationError('兩次密碼不一致,請核對')

    # todo  校驗驗證碼[待做]

        return attrs

    '''
    重寫create方法:因為序列化器中有的字段是不需要反序列化存到數據庫中
    
    
    '''
    def create(self, validated_data):

        # 確認密碼和驗證碼不需要存到數據庫中,所以要剔除它們
        validated_data.pop('r_password')
        validated_data.pop('sms')
        
        # 密碼加密
        hash_password = make_password(validated_data['password'])
        validated_data['password'] = hash_password
        
        # 以上處理好的數據存到數據庫中
        user = models.User.objects.create(
            **validated_data
        )
        user.token = '123' # 硬加上一個token

        return user # 返回user對象時,就會有token這個屬性了

3.點擊獲取驗證碼

1.點擊獲取驗證碼的原理

2.點擊獲取驗證碼-配置

1.安裝django-redis

pip install django-redis

2.dev.py文件做相關配置

# dev.py

# 設置redis緩存
CACHES = {
    # 默認緩存
    "default": {
        "BACKEND": "django_redis.cache.RedisCache",
        # 項目上線時,需要調整這里的路徑
        "LOCATION": "redis://127.0.0.1:6379/0",

        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
        }
    },
    # 提供給xadmin或者admin的session存儲
    "session": {
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": "redis://127.0.0.1:6379/1",
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
        }
    },
    # 提供存儲短信驗證碼
    "sms_code":{
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": "redis://127.0.0.1:6379/2",
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
        },
    }
}

# 設置xadmin用戶登錄時,登錄信息session保存到redis
SESSION_ENGINE = "django.contrib.sessions.backends.cache"
SESSION_CACHE_ALIAS = "session"

3.點擊獲取驗證碼-前端

<!-- html -->
<button style="width: 34%;height: 41px;" @click="getSmsCode">點擊獲取驗證碼</button>
// js
 getSmsCode(){
      this.$axios.get(`${this.$settings.Host}/`)
    }

4.點擊獲取驗證碼-后端接口

users/urls.py

# urls.py
from rest_framework_jwt.views import obtain_jwt_token, verify_jwt_token
from . import views
from django.urls import path

urlpatterns = [
    ......
    path(r'sms_code/(?P<phone>^1[3-9][0-9]{9}$)/', views.GetSMSCodeView.as_view()),

]

users/views.py

# views.py
from django_redis import get_redis_connection
class GetSMSCodeView(APIView):

    def get(self,request,phone):
        
        # 驗證是否已經發送過短信了
        conn = get_redis_connection('sms_code')
        ret = conn.get('mobile_interval_%s'%phone)
        if ret:
            return Response({'msg':'60秒內已經發送過了,別瞎搞'}, status=status.HTTP_400_BAD_REQUEST)

        # 生成驗證碼
        sms_code = "%06d" % random.randint(0,999999)

        # 保存驗證碼
        '''
        驗證碼是存到redis里的,因為驗證碼有時限,所以用setex將驗證碼存入
        存入方式是以鍵值對存入的:
        key:手機號 value:驗證碼
        '''
        conn.setex('mobile_%s'%phone, sms_code, contains.SMS_CODE_EXPIRE_TIME)  # 設置有效期

        #
        conn.setex('mobile_interval_%s'%phone, sms_code, contains.SMS_CODE_INTERVAL_TIME)  # 設置發送短信的時間間隔


        # todo 發送驗證碼

        return Response({'msg':'ok'})

兩個常量放到constant.py中

settings/constant.py

# settings/constant.py
SMS_CODE_EXPIRE_TIME = 60*10 # 有效時間
SMS_CODE_INTERVAL_TIME = 60 # 間隔時間

4.解決登錄不上Xadmin的bug

登錄不上Xadmin的原因是:

之前我們設置了Xadmin使用咱們自己創建的用戶表,而不是使用Xadmin原先自帶的表:傳送門:Xadmin使用自己創建的用戶表

而在昨天我們又重寫了jwt代碼,讓其除了驗證用戶名和密碼還要驗證ticket票據:傳送門:重寫jwt代碼來實現對滑動成功的認證

這樣的話就會導致我們在登錄Xadmin的時候,也會驗證ticket票據,所以會登錄失敗。

所以我們做一個if判斷:

當ticket有值的時候才走滑動成功的認證:驗證用戶名 密碼 ticket randstr

當ticket沒有值的時候,就做常規認證,只驗證用戶名和密碼即可

users/utils.py

# users/utils.py
class CustomeModelBackend(ModelBackend):

    def authenticate(self, request, username=None, password=None, **kwargs):
        try:
            user_obj = get_user_obj(username)
            
            '''
            看是否有票據信息,如果沒有,直接走下面的代碼(Xadmin用戶名密碼登錄)
            如果有票據信息,走if里面的代碼 對票據進行驗證
            這樣的話xadmin就不會因為走票據信息這套邏輯導致登錄失敗了
            '''
            if kwargs.get('ticket'):

                ticket = kwargs.get('ticket')

                userip = request.META['REMOTE_ADDR']
                randstr = kwargs.get('randstr')
                print('userip:', userip)

                params = {
                    "aid": settings.FSQ.get('appid'),
                    "AppSecretKey": settings.FSQ.get('app_serect_key'),
                    "Ticket": ticket,
                    "Randstr": randstr,
                    "UserIP": userip
                }
                params = urlencode(params).encode()

                url = settings.FSQ.get('URL')

                f = urlopen(url, params)

                content = f.read()
                res = json.loads(content)
                print(res)  # {'response': '1', 'evil_level': '0', 'err_msg': 'OK'}
                if res.get('response') != '1':
                    return None

            if user_obj:
                if user_obj.check_password(password):
                    return user_obj

            else:
                return None
        except Exception:
            logger.error('驗證過程代碼有誤,請聯系管理員')
            return None

5.redis

1.redis簡要介紹

mysql的表類型[表引擎,存儲引擎],memory 表結構和表數據分開存儲的,表結構保存在硬盤中,表數據保存在內存中.

memcache 一款軟件,可以使用鍵值對的格式,保存數據到內存中.

redis是意大利的工程師開發的開源\免費的高速內存緩存數據庫.需要注意的是,作者本身是只開發了linux版本的redis數據庫.

 

window系統的redis是微軟團隊根據官方的linux版本高仿的

官方原版: https://redis.io/

中文官網:http://www.redis.cn

參考命令:http://doc.redisfans.com/

2.redis的下載和安裝

下載地址: https://github.com/MicrosoftArchive/redis/releases

使用以下命令啟動redis服務端[配置文件路徑根據自己的擺放位置改動]

redis-server C:/tool/redis/redis.windows.conf

redis作為windows服務啟動方式

redis-server --service-install redis.windows.conf

啟動服務:redis-server --service-start

停止服務:redis-server --service-stop

3.redis的使用

如何使用redis?傳送門:如何使用redis?

Redis 是一個高性能的key-value數據格式的內存緩存,NoSQL數據庫。

NOSQL:not only sql,泛指非關系型數據庫。

關系型數據庫: (mysql, oracle, sql server, sqlite, db2)

1. 數據存放在表中,表之間有關系。
2. 通用的SQL操作語言。
3. 大部分支持事務。

非關系型數據庫:[ redis,hadoop,mangoDB]:

1. 沒有數據表的概念,不同的nosql數據庫存放數據位置不同。
2. nosql數據庫沒有通用的操作語言。
3. 基本不支持事務。   redis支持簡單事務

redis:內存型(數據存放在內存中)的非關系型(nosql)key-value(鍵值存儲)數據庫,支持數據的持久化(注: 數據持久化時將數據存放到文件中,每次啟動redis之后會先將文件中數據加載到內存),經常用來做緩存(用來緩存一些經常用到的數據,提高讀寫速度)。

redis是一款基於CS架構的數據庫,所以redis有客戶端,也有服務端。

其中,客戶端可以使用python等編程語言,也可以終端命令行工具

 

redis客戶端連接服務器:

redis-cli -h `redis服務器ip` -p `redis服務器port`  #6379

4.redis數據類型

# 1. string類型:
    字符串類型是 Redis 中最為基礎的數據存儲類型,它在 Redis 中是二進制安全的,也就是byte類型
    最大容量是512M。
        key: string
# 2. hash類型: hash用於存儲對象,對象的結構為屬性、值,值的類型為string。 key:{ 域:值[這里的值只能是字符串], 域:值, 域:值, 域:值, ... }
# 3. list類型: 列表的元素類型為string。 key:[ 值1,值2,值3..... ]
# 4. set類型: 無序集合,元素為string類型,元素唯一不重復,沒有修改操作。 key: {值1,值4,值3,值5,....}
# 5. zset類型[sortset]: 有序集合,元素為string類型,元素唯一不重復,有修改操作。 key:{ 值: 權重值, 值: 權重值, }

5.String

如果設置的鍵不存在則為添加,如果設置的鍵已經存在則修改

  • 設置鍵值

    set key value

  • 例1:設置鍵為name值為xiaoming的數據

    set name xiaoming

  • 設置鍵值及過期時間,以秒為單位

    setex key seconds value

  • 例2:設置鍵為aa值為aa過期時間為3秒的數據

    setex name 20 xiaoming

 

關於設置保存數據的有效期

# setex 添加保存數據到redis,同時設置有效期
格式:
    setex key time value
# expire 給已有的數據重新設置有效期
格式:
    expire key time
  • 設置多個鍵值

    mset key1 value1 key2 value2 ...

  • 例3:設置鍵為a1值為python、鍵為a2值為java、鍵為a3值為c

    mset a1 python a2 java a3 c

  • 追加值

    append key value

  • 例4:向鍵為a1中追加值haha,a1='xx'

    append a1 haha

    a1= 'xxhaha'

 

  • 獲取:根據鍵獲取值,如果不存在此鍵則返回nil

    get key

  • 例5:獲取鍵name的值

    get name

 

  • 根據多個鍵獲取多個值

    mget key1 key2 ...

  • 例6:獲取鍵a1、a2、a3的值

    mget a1 a2 a3

6.鍵操作

  • 查找鍵,參數⽀持正則表達式

    keys pattern

  • 例1:查看所有鍵

    keys *

  • 例2:查看名稱中包含a的鍵

    keys a*

 

  • 判斷鍵是否存在,如果存在返回1,不存在返回0

    exists key1

  • 例3:判斷鍵a1是否存在

    exists a1

 

  • 查看鍵對應的value的類型

    type key

  • 例4:查看鍵a1的值類型,為redis⽀持的五種類型中的⼀種

    type a1

  • 刪除鍵及對應的值

    del key1 key2 ...

  • 例5:刪除鍵a2、a3

    del a2 a3

  • 查看有效時間,以秒為單位

    ttl key

  • 例7:查看鍵bb的有效時間

    ttl bb

7.hash

# 結構:


鍵key:{
    域field:值value
}
 
  • 設置單個屬性

    hset key field value

  • 例1:設置鍵 user的屬性namexiaohong

    hset user name xiaohong

  • 設置多個屬性

    hmset key field1 value1 field2 value2 ...

  • 例2:設置鍵u2的屬性namexiaohong、屬性age11

    hmset u2 name xiaohong age 11

  • 獲取指定鍵所有的屬性

    hkeys key

  • 例3:獲取鍵u2的所有屬性

    hkeys u2

  • 獲取⼀個屬性的值

    hget key field

  • 例4:獲取鍵u2屬性name的值

    hget u2 name

  • 獲取多個屬性的值

    hmget key field1 field2 ...

  • 例5:獲取鍵u2屬性nameage的值

    hmget u2 name age

  • 獲取所有屬性的值

    hvals key

  • 例6:獲取鍵u2所有屬性的值

    hvals u2

  • 刪除屬性,屬性對應的值會被⼀起刪除

    hdel key field1 field2 ...

  • 例7:刪除鍵u2的屬性age

    hdel u2 age

8.set

可刪除不可修改

  • 添加元素

    sadd key member1 member2 ...

  • 例1:向鍵a3的集合中添加元素zhangsanlisiwangwu

    sadd a3 zhangsan sili wangwu

 

  • 返回所有的元素

    smembers key

  • 例2:獲取鍵a3的集合中所有元素

    smembers a3

 

  • 刪除指定元素

    srem key value

  • 例3:刪除鍵a3的集合中元素wangwu

    srem a3 wangwu

9.list

列表的元素類型為string

按照插⼊順序排序

  • 在左側插⼊數據

    lpush key value1 value2 ...

  • 例1:從鍵為a1的列表左側加⼊數據a 、 b 、c

    lpush a1 a b c

  • 在右側插⼊數據

    rpush key value1 value2 ...

  • 例2:從鍵為a1的列表右側加⼊數據0、1

    rpush a1 0 1

  • 在指定元素的前或后插⼊新元素

    linsert key before或after 現有元素 新元素

  • 例3:在鍵為a1的列表中元素b前加⼊3

    linsert a1 before b 3

 

設置指定索引位置的元素值

  • 索引從左側開始,第⼀個元素為0

  • 索引可以是負數,表示尾部開始計數,如-1表示最后⼀個元素

    lset key index value

  • 例5:修改鍵為a1的列表中下標為1的元素值為z

    lset a 1 z

 

  • 刪除指定元素

    • 將列表中前count次出現的值為value的元素移除

    • count > 0: 從頭往尾移除

    • count < 0: 從尾往頭移除

    • count = 0: 移除所有

     lrem key count value

  • 例6.2:從a2列表右側開始刪除2個b

    lrem a2 -2 b

  • 例6.3:查看列表a2的所有元素

    lrange a2 0 -1


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM