1. 程式人生 > 其它 >drf序列化群增、群改、群刪

drf序列化群增、群改、群刪

1 自定義user表,簽發token,認證類

表模型

class MyUser(models.Model):
    username = models.CharField(max_length=32)
    password = models.CharField(max_length=32)
    phone = models.CharField(max_length=32)
    email = models.EmailField()

路由

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

檢視

jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
from rest_framework_jwt.views import obtain_jwt_token


class MyLoginView(APIView):
    def post(self, request, *args, **kwargs):
        username = request.data.get('username')
        password = request.data.get('password')
        # 如果是手機號
        if re.match('^1[3-9]\d{9}$', username):
            # 以手機號登入
            user = MyUser.objects.filter(phone=username).first()
        elif re.match('^.+@.+$', username):
            # 以郵箱登入
            user = MyUser.objects.filter(email=username).first()
        else:
            # 以使用者名稱登入
            user = MyUser.objects.filter(username=username).first()
        # 如果user有值並且密碼正確
        if user and user.password == password:
            # 登入成功,生成token
            # drf-jwt中有通過user物件生成token的方法
            payload = jwt_payload_handler(user)
            token = jwt_encode_handler(payload)
            return APIResponse(token=token, username=user.username)
        else:
            return APIResponse(code=101, msg='使用者名稱或密碼錯誤')

2 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)

3 book表單增群增

class BookView(APIView):
    def post(self, request, *args, **kwargs):
        if isinstance(request.data, dict):
            # 增一條
            ser = serializer.BookSerializer(data=request.data)
            ser.is_valid(raise_exception=True)
            ser.save()
            return APIResponse(data=ser.data)
        elif isinstance(request.data, list):
            # 增多條
            ser = serializer.BookSerializer(data=request.data, many=True)
            # 內部如何實現的?
            # many=True,ser不是BookSerializer物件,而是ListSerializer物件,套了一個個的BookSerializer
            print(type(ser))
            ser.is_valid(raise_exception=True)
            #
            from rest_framework.serializers import ListSerializer
            ser.save()  # ListSerializer的save
            return APIResponse(msg='增加%s條成功' % len(request.data))

4 book表單查群查

class BookView(APIView):
    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 = serializer.BookSerializer(instance=book)

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

5 book表單改群改

class BookView(APIView):
    def put(self, request, *args, **kwargs):
        pk = kwargs.get('pk', None)
        if pk:
            # 單條修改
            book = models.Book.objects.get(id=pk, is_delete=False)
            ser = serializer.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 = serializer.BookSerializer(instance=book_list, data=request.data, many=True)
            print(type(ser))
            ser.is_valid(raise_exception=True)
            ser.save()
            return APIResponse(msg='修改%s條成功')

            # 你們能想到的方法
            # 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))

6 book表的單刪群刪

class BookView(APIView):

    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

        res = models.Book.objects.filter(id__in=pks).update(is_delete=True)
        if res >= 1:
            return APIResponse(msg='刪除%s條成功' % res)
        else:
            # raise Exception('沒有要刪除的資料')
            return APIResponse(code=999, msg='沒有要刪除的資料')

7 序列化類

from app01 import models


class ListBookSerializer(serializers.ListSerializer):
    # def create(self, validated_data):
    #     print('=======',validated_data)
    #     return '1'
    def update(self, instance, validated_data):
        print(instance) # book_list:是一堆圖書物件
        print(validated_data) # 列表套字典,是要修改的資料

        return [self.child.update(book, validated_data[i]) for i, book in enumerate(instance)]


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},

        }

    # def create(self, validated_data):
    #     print(validated_data)

路由

path('books/', views.BookView.as_view()),
re_path('books/(?P<pk>\d+)', views.BookView.as_view()),
1 自定義token的簽發和認證:https://www.cnblogs.com/liuqingzheng/articles/9766397.html