多方式登录  book,publish,author表关系及抽象表的建立  book表的群(增删改查)

一:多方式登录

serializer.py文件中


from rest_framework import serializers
from app01.models import UserInfo,MyUser

import re
from rest_framework.exceptions import ValidationError
from rest_framework_jwt.views import obtain_jwt_token
from rest_framework_jwt.utils import jwt_encode_handler,jwt_payload_handler


#继承了Absract表的多方式登录
class LoginSerializer(serializers.ModelSerializer):
    username = serializers.CharField()

    class Meta:
        model = UserInfo
        fields = ['username','password']

    def validate(self, attrs):
        username = attrs.get('username')
        password = attrs.get('password')
        #如果是手机号(^1(?:3\d|4[4-9]|5[0-35-9]|6[67]|7[013-8]|8\d|9\d)\d{8}$)中国合法是手机号码正则表达式
        if re.match('^1(?:3\d|4[4-9]|5[0-35-9]|6[67]|7[013-8]|8\d|9\d)\d{8}$',username):
            user = UserInfo.objects.filter(phone=username).first()
        #如果是邮箱(^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$)
        elif re.match('^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$',username):
            user = UserInfo.objects.filter(email=username).first()

        else:
            user = UserInfo.objects.filter(username=username).first()

        if user and user.check_password(password):
            #登录成功,生成token
            #drf-jwt中有通过uer对象生成token的方法
            payload = jwt_payload_handler(user)
            token = jwt_encode_handler(payload)
            #token是要在视图类中使用,现在我们在序列化类在中
            #self.context.get('request')
            #视图类和序列化类之间通过context这个字典来传递数据
            self.context['token'] = token
            self.context['username'] = user.username
            return attrs
        else:
            raise ValidationError('用户名或者密码错误')


#没有继承的多方式登录
class LoginMyuser(serializers.ModelSerializer):

    class Meta:
        model = MyUser
        fields = ['username', 'password']

    def validate(self, attrs):
        username = attrs.get('username')
        password = attrs.get('password')
        # 如果是手机号(^1(?:3\d|4[4-9]|5[0-35-9]|6[67]|7[013-8]|8\d|9\d)\d{8}$)中国合法是手机号码正则表达式
        if re.match('^1(?:3\d|4[4-9]|5[0-35-9]|6[67]|7[013-8]|8\d|9\d)\d{8}$', username):
            user = MyUser.objects.filter(phone=username).first()
            print(user)
        # 如果是邮箱(^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$)
        elif re.match('^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$', username):
            user = MyUser.objects.filter(email=username).first()
            print(user)

        else:
            user = MyUser.objects.filter(username=username).first()

        if user and password == user.password:
            # 登录成功,生成token
            # drf-jwt中有通过uer对象生成token的方法
            payload = jwt_payload_handler(user)
            token = jwt_encode_handler(payload)
            print(token)
            # token是要在视图类中使用,现在我们在序列化类在中
            # self.context.get('request')
            # 视图类和序列化类之间通过context这个字典来传递数据
            self.context['token'] = token
            self.context['username'] = user.username
            return attrs
        else:
            raise ValidationError('用户名或者密码错误')
View Code

View.py

from  rest_framework.viewsets import ViewSet
from app01.serizlizer import LoginSerializer,LoginMyuser
from app01.utils import APIResponse
from rest_framework.views import APIView

class LoginViewSet(ViewSet):
    def create(self,request,*args,**kwargs):
        #实例化得到一个序列化的对象
        #ser=LoginSerializer(data=request.data,context={'request':request})
        ser = LoginSerializer(data=request.data)
        #序列化类的对象的校验方法
        ser.is_valid(raise_exception=True) #字段自己的校验 局部校验,全局校验
        #如果通过,表示登录成功,返回手动签发的token
        token = ser.context.get('token')
        username = ser.context.get('username')
        return APIResponse(token=token,username=username)
        #如果失败则不用管,因为设置了全局异常




class LoginMyuserViewset(ViewSet):
    def create(self,request,*args,**kwargs):
        ser = LoginMyuser(data=request.data)
        ser.is_valid(raise_exception=True)
        token = ser.context.get('token')
        username = ser.context.get('username')
        return APIResponse(token=token,username=username)
View Code

路由

path('login2/', views.MyLoginView.as_view()),

二、book、publish、author表关系以及抽象表的建立

# 注意:以后所有的数据删除,尽量用软删除,使用一个字段标志是否删除,而不是真正的从数据库中删除
    -好处:1 这样删除数据不会影响索引,不会导致索引失效
          2 之前存的用户数据还在,以备以后使用
# 表模型如下
# 抽象出一个基表(不再数据库生成,abstract=True),只用来继承

class BaseModel(models.Model):
    is_delete = models.BooleanField(default=False)
    create_time = models.DateTimeField(auto_now_add=True)

    class Meta:
        # 基表必须设置abstract,基表就是给普通Model类继承使用的,设置了abstract就不会完成数据库迁移完成建表
        abstract = True


class Book(BaseModel):
    name = models.CharField(max_length=16)
    price = models.DecimalField(max_digits=5, decimal_places=2)
    publish = models.ForeignKey(to='Publish', db_constraint=False, on_delete=models.DO_NOTHING)
    # 重点:多对多外键实际在关系表中,ORM默认关系表中两个外键都是级联
    # ManyToManyField字段不提供设置on_delete,如果想设置关系表级联,只能手动定义关系表
    authors = models.ManyToManyField(to='Author', related_name='books', db_constraint=False)

    @property
    def publish_name(self):
        return self.publish.name
    @property
    def author_list(self):
        # ll=[]
        # for author in self.authors.all():
        #     ll.append({'name':author.name,'sex':author.get_sex_display()})
        return [{'name': author.name, 'sex': author.get_sex_display()} for author in self.authors.all()]


class Publish(BaseModel):
    name = models.CharField(max_length=16)
    address = models.CharField(max_length=64)


class Author(BaseModel):
    name = models.CharField(max_length=16)
    sex = models.IntegerField(choices=[(0, ''), (1, '')], default=0)


class AuthorDetail(BaseModel):
    mobile = models.CharField(max_length=11)
    # 有作者可以没有详情,删除作者,详情一定会被级联删除
    # 外键字段为正向查询字段,related_name是反向查询字段
    author = models.OneToOneField(to='Author', related_name='detail', db_constraint=False, on_delete=models.CASCADE)
View Code

三、book表单增群增

from app01 import serizlizer
from app01 import models


class BookView(APIView):
    def post(self,request,*args,**kwargs):
        if isinstance(request.data,dict):  #看request.data是不是字典
            #增一条
            ser = serizlizer.BookSerializer(data=request.data)
            ser.is_valid(raise_exception=True)
            ser.save() #对象直接保存
            return APIResponse(data=ser.data)
        elif isinstance(request.data,list):
            #增多条
            ser = serizlizer.BookSerializer(data=request.data,many=True)
            #内部如何实现的?
            #many=True,ser不是BookSerizlizer对象,而是listSerializer对象,套了一个个的BookSerializer对象
            print(type(ser))
            ser.is_valid(raise_exception=True)
            #
            ser.save()
            return APIResponse(msg='增加%s条成功'%len(request.data))

    def get(self,request,*args,**kwargs):
        pk = kwargs.get('pk',None)
        if pk:
            #单查
            #方式一:
            # book=models.Book.objects.filter(id=pk).filter(is_delete=False).first()
            #if not book:
                # raise Exception('要查询的不存在')
            book= models.Book.objects.get(id=pk,is_delete=False)
            ser = serizlizer.BookSerializer(instance=book)

        else:
            #查所有
            book_list = models.Book.objects.all().filter(is_delete=False)
            ser = serizlizer.BookSerializer(instance=book_list,many=True)
        return APIResponse(data=ser.data)

book表的单删群删

 def delete(self,request,*args,**kwargs):
        pk = kwargs.get('pk',None)
        pks = []
        if pk:
            #单条删除
            # res=models.Book.objects.filter(id=pk).update(is_delete=True)
            # print(res)
            # return APIResponse(msg='删除成功')
            pks.append(pk)
        else:
            pks = request.data
            print(request.data)
            # for i in request.data:
            #     book=models.Book.objects.filter(title=request.data.get('title'),price=request.data.get('price')).first()
            #     pks.append(book.pk)

        res = models.Book.objects.filter(id__in=pks).update(is_delete=True)
        # res = models.Book.objects.filter(id__in=pks).update(is_delete=True)
        print(res,type(res))
        if res >=1:
            return APIResponse(msg='删除%s条成功'%res)
        else:
            #raise Exception('没有要删除的数据')
            return APIResponse(code=99,msg='没有要删除的数据')

book表的单增群增

 def put(self,request,*args,**kwargs):
        pk = kwargs.get('pk',None)
        if pk:
            #单条修改
            book = models.Book.objects.get(id=pk,is_delete=False)
            ser = serizlizer.BookSerializer(instance=book,data=request.data)
            ser.is_valid(raise_exception=True)
            ser.save()
            return APIResponse(msg='修改成功')
        else:
            #分析:ListSerializer的update方法没有写,需要我们自己去写
            from rest_framework.serializers import ListSerializer
            #pks=[item['id'] for item in request.data]
            #如果我们不重写ListSerializer的update方法,这是存不进去的
            pks = []
            for item in request.data:
                pks.append(item['id'])
                item.pop('id')

            print(request.data)
            book_list = models.Book.objects.filter(id__in=pks,is_delete=False)
            ser = serizlizer.BookSerializer(instance=book_list,data=request.data,many=True)
            print(type(ser))
            ser.is_valid(raise_exception=True)
            ser.save()
            print(ser,222222222222222222222)
            return APIResponse(msg='修改成功%s条成功'%len(pks))

        # 你们能想到的方法
        # pks = []
        # for item in request.data:
        #     pks.append(item['id'])
        #     item.pop('id')
        # book_list = models.Book.objects.filter(id__in=pks, is_delete=False)
        #
        # for i,book in enumerate(book_list):
        #     ser = serializer.BookSerializer(instance=book, data=request.data[i])
        #     ser.is_valid(raise_exception=True)
        #     ser.save()
        # return APIResponse(msg='修改%s条成功'%len(book_list))
View Code

serizlizer.py

图书表序列化
from app01 import models


class ListBookSerializer(serializers.ListSerializer):
    def update(self, instance, validated_data):
        print(instance)  #book_list:是一堆图书对象
        print(validated_data,9999999999) #列表套字典,是要修改的数据
        print(self.child,1212121)
        return [self.child.update(book,validated_data[i]) for i,book in enumerate(instance) ]
        # child是所有图书的对象打印出来是这样的
        '''
        BookSerializer(data=[{'name': '金梅5up', 'price': '22.22', 'publish': 1, 'authors': [1]}, {'name': '金梅6up', 'price': '22.22', 'publish': 1, 'authors': [1]}], instance=<QuerySet [<Book: Book object (5)>, <Book: Book object (6)>]>):
    name = CharField(max_length=16)
    price = DecimalField(decimal_places=2, max_digits=5)
    publish = PrimaryKeyRelatedField(queryset=Publish.objects.all(), write_only=True)
    authors = PrimaryKeyRelatedField(allow_empty=False, many=True, queryset=Author.objects.all(), write_only=True)
    publish_name = ReadOnlyField(read_only=True)
    author_list = ReadOnlyField(read_only=True) 1212121
        '''
       #视图view中的ser打印出来也是这样的,两者
    """
    BookSerializer(data=[{'name': '金梅5up', 'price': '22.22', 'publish': 1, 'authors': [1]}, {'name': '金梅6up', 'price': '22.22', 'publish': 1, 'authors': [1]}], instance=<QuerySet [<Book: Book object (5)>, <Book: Book object (6)>]>, many=True):
    name = CharField(max_length=16)
    price = DecimalField(decimal_places=2, max_digits=5)
    publish = PrimaryKeyRelatedField(queryset=Publish.objects.all(), write_only=True)
    authors = PrimaryKeyRelatedField(allow_empty=False, many=True, queryset=Author.objects.all(), write_only=True)
    publish_name = ReadOnlyField(read_only=True)
    author_list = ReadOnlyField(read_only=True) 222222222222222222222
    """







class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Book
        list_serializer_class = ListBookSerializer #指定many=True的时候,生成的ListBookSerializer的对象
        fields = ['name','price','publish','authors','publish_name','author_list']
        extra_kwargs = {
            'publish':{'write_only':True},
            'authors':{'write_only':True},
            'publish_name':{'read_only':True},
            'author_list':{'read_only':True},
        }
View Code

 

book表的单查群查

 def get(self,request,*args,**kwargs):
        pk = kwargs.get('pk',None)
        if pk:
            #单查
            #方式一:
            # book=models.Book.objects.filter(id=pk).filter(is_delete=False).first()
            #if not book:
                # raise Exception('要查询的不存在')
            book= models.Book.objects.get(id=pk,is_delete=False)
            ser = serizlizer.BookSerializer(instance=book)

        else:
            #查所有
            book_list = models.Book.objects.all().filter(is_delete=False)
            ser = serizlizer.BookSerializer(instance=book_list,many=True)
        return APIResponse(data=ser.data)
View Code

 

 

 

posted on 2020-11-16 23:40  輪滑少年  阅读(156)  评论(0编辑  收藏  举报