zoukankan      html  css  js  c++  java
  • 八、drf单、群增删查改

    drf单、群增删查改

    一、单群增

    ① models.py

    from django.db import models
    
    
    class BaseModel(models.Model):
        is_delete = models.BooleanField(default=False)
    
        # auto_now_add = True 只要记录创建,不需要手动插入时间,自动版当前时间插入
        create_time = models.DateTimeField(auto_now_add=True)
        # auto_now = True 只要更新,就会把当前时间插入
        last_update_time = models.DateTimeField(auto_now=True)
        # 此处的Datetime.datetime.now不需要加括号,加括号和不加括号有很大的区别
        # create_time = models.DateTimeField(default=Datetime.datetime.now)
    
        class Meta:
            # 单个字段,有索引,有唯一
            # 多个字段,又联合索引,联合唯一
            abstract = True # 抽象表,不在数据库中创建实际表
    
    
    class Book(BaseModel):
        id = models.AutoField(primary_key=True)
        name = models.CharField(max_length=32,verbose_name="书名")
        price = models.DecimalField(max_digits=5,decimal_places=2,verbose_name="价格")
    
        # 一对多关系一旦确立,关联字段写在多的一边
        # to_field 默认不写,关联到Publish主键
        # db_constraint = False 逻辑上的关联,实质上没有外键联系,增删不会受外键影响,但是orm查询不影响
        publish = models.ForeignKey(to="Publish",on_delete=models.DO_NOTHING,db_constraint=False)
    
        # 多对多关系,跟作者  关联字段写在查询次数多的一方
    
        # 什么时候使用自动,什么时候使用手动? 第三张表只有关联字段,用自动;  第三张表有扩展字段,需要手动写
        # 不能写on_delete 因为使用自动的话,这是orm帮我们建的关系表,不会真正作用到数据库中
        authors = models.ManyToManyField(to="Author",db_constraint=False)
    
        class Meta:
            verbose_name_plural = "书表" # admin中表名的显示
    
        def __str__(self):
            return self.name
    
        @property
        def publish_name(self):
            return self.publish.name
    
        def author_list(self):
            # 拿到所有作者
            author_list = self.authors.all()
            ll = []
            for author in author_list:
                ll.append({'name':author.name,'sex':author.get_sex_display()})
            return ll
            # 列表推导式,太长了就别用了
            # return [{'name':author.name,'sex':author.get_sex_display()} for author in author_list]
    
    
    class Publish(BaseModel):
        name = models.CharField(max_length=32,verbose_name="出版社")
        addr = models.CharField(max_length=32,verbose_name="地址")
    
        class Meta:
            verbose_name_plural = "出版社"
    
        def __str__(self):
            return self.name
    
    class Author(BaseModel):
        name = models.CharField(max_length=32,verbose_name="作者")
        sex = models.IntegerField(choices=((1,"男"),(2,'女'),),verbose_name="性别")
    
        # 一对一关系,关联字段写在查询频率高的那一方
        # OneToOneField本质就是ForeignKey + unique,自己手动写也可以
        author_Detail = models.OneToOneField(to="AuthorDetail",db_constraint=False,on_delete=models.CASCADE)
    
        class Meta:
            verbose_name_plural = "作者表"
    
        def __str__(self):
            return self.name
    
    
    class AuthorDetail(BaseModel):
        mobile = models.CharField(max_length=11,verbose_name="手机号")
    
        class Meta:
            verbose_name_plural = "作者详情表"
    
        def __str__(self):
            return self.mobile
    
    
    # 表断关联
    # 1.表之间没有外键关联,但是有外键逻辑关联(有充当外键的字段)
    # 2.断关系后不会影响数据查询效率,但是会极大提高数据库增删改效率(不影响增删改查操作)
    # 3.断关系一定要通过逻辑保证表支架数据安全
    # 4.断关联
    # 5.级联关系
        # <1> 作者没了,详情也没了:on_delete = models.CASCADE
        # <2> 出版社没了,书还是那个出版社出版:on_delete = models.DO_NOTHING
        # <3> 部门没了,员工没有部门(空不能):null = True ,on_delete = models.SET_NULL
        # <4> 部门没了,员工进入默认部门(默认值):default = 0,on_delete = models.SET_DEFAULT
    

    ② ser.py

    from api import models
    from rest_framework import serializers
    
    
    # 写一个类,继承ListSerializer,重写修改数据时需要执行的update方法
    class BookListSerializer(serializers.ListSerializer):
        # def create(self, validated_data):
        # 这是重写新增数据时需要执行的方法
        # print(validated_data)
        # return super().create(validated_data)
        def update(self, instance, validated_data):
            # 这是重写修改数据时需要执行的方法
            # instance = book_list,数据格式是:[book1,book2,book3]
            # validated_data = modify_data,数据格式是:[{name:jason,price:12},{name:jason,price:12}]
    
            # 此处的self.child是BookSerializer对象,但是需要在BookSerializer中的Meta中配置一句话
            # list_serializer_class = BookListSerializer
            print("----》",instance)
            print("---->",validated_data)
    
            # ll = []
            # for i,si_data in enumerate(validated_data):
            #     result = self.child.update(instance[i],si_data)
            #     ll.append(result)
            # return ll
            """上面的方法和下面的方法一致"""
            return [
                self.child.update(instance[i], attrs) for i, attrs in enumerate(validated_data)
    
                # self.child.update(instance[i], attrs) for i, attrs in enumerate(validated_data)
                # def update(self, instance = instance[i], validated_data = attrs):
                #   pass
            ]
    
    
    # 如何序列化的是数据库的表,尽量用ModelSerializer
    class BookSerializer(serializers.ModelSerializer):
        # depth:控制的是在前端展示的外键数据
        # 因为数据库中的有些数据不需要在前端展示,所以需要在后端处理展示的信息
    
        # 方式一:只序列化可以,反序列化会出现问题
        # publish = serializers.CharField(source="publish.name")
    
        # 方式二:在models中写方法
        # ...
    
        class Meta:
            list_serializer_class = BookListSerializer
            model = models.Book
            # fields = "__all__"
            # 控制前端展示的数据信息,用得少
            # depth = 0
    
            fields = ('id','name', 'price', 'authors', 'publish', 'publish_name', 'author_list')
            extra_kwargs = {
                'publish': {'write_only': True},
                'publish_name': {"read_only": True},
                'authors': {'write_only': True},
                'author_list': {"read_only": True},
            }
    

    ③ urls.py

    # 使用了路由分发
    from django.conf.urls import url
    from api import views
    
    urlpatterns = [
        # 此处一定要记得,特殊的路由放在上面,避免匹配到 
        url(r'books/(?P<pk>d+)', views.BookAPIView.as_view()),
        url(r'books/', views.BookAPIView.as_view()),
    ]
    

    ④ views.py

    """单查群查、单增群增、单改群改、单删群删"""
    class BookAPIView(APIView):
        # 增加一条和多条数据
        def post(self, request, *args, **kwargs):
            # 具备增单条和增多条的功能
            if isinstance(request.data, dict):  # 如果request.data 是一个套字段信息的字典,就是增一条数据 {}
                book_ser = ser.BookSerializer(data=request.data)
                book_ser.is_valid(raise_exception=True)
                book_ser.save()
                return Response(data=book_ser.data)
            elif isinstance(request.data, list):  # 如果request.data 是一个套字段信息的多个字典的列表,就是增多条数据 [{},{},{}]
                # 此时的book_ser是ListSerializer对象
                book_ser = ser.BookSerializer(data=request.data, many=True)
                print(type(book_ser))
                book_ser.is_valid(raise_exception=True)
                book_ser.save()
                # 此时的book_ser.save()是谁的方法?
                '''
                此时的book_ser是ListSerializer对象,所以save()方法是ListSerializer的save()的方法
                批量新增-----》ListSerializer------》create()方法
                
                # 源码中的方法
                def create(self,validated_data):
                    # self.create是bookSerializer对象
                    return [
                        self.child.create(attr) for attr in validated_data
                    ]
                '''
                return Response(data=book_ser.data)
    

    二、单群删

    ① models.py

    from django.db import models
    
    
    class BaseModel(models.Model):
        is_delete = models.BooleanField(default=False)
    
        # auto_now_add = True 只要记录创建,不需要手动插入时间,自动版当前时间插入
        create_time = models.DateTimeField(auto_now_add=True)
        # auto_now = True 只要更新,就会把当前时间插入
        last_update_time = models.DateTimeField(auto_now=True)
        # 此处的Datetime.datetime.now不需要加括号,加括号和不加括号有很大的区别
        # create_time = models.DateTimeField(default=Datetime.datetime.now)
    
        class Meta:
            # 单个字段,有索引,有唯一
            # 多个字段,又联合索引,联合唯一
            abstract = True # 抽象表,不在数据库中创建实际表
    
    
    class Book(BaseModel):
        id = models.AutoField(primary_key=True)
        name = models.CharField(max_length=32,verbose_name="书名")
        price = models.DecimalField(max_digits=5,decimal_places=2,verbose_name="价格")
    
        # 一对多关系一旦确立,关联字段写在多的一边
        # to_field 默认不写,关联到Publish主键
        # db_constraint = False 逻辑上的关联,实质上没有外键联系,增删不会受外键影响,但是orm查询不影响
        publish = models.ForeignKey(to="Publish",on_delete=models.DO_NOTHING,db_constraint=False)
    
        # 多对多关系,跟作者  关联字段写在查询次数多的一方
    
        # 什么时候使用自动,什么时候使用手动? 第三张表只有关联字段,用自动;  第三张表有扩展字段,需要手动写
        # 不能写on_delete 因为使用自动的话,这是orm帮我们建的关系表,不会真正作用到数据库中
        authors = models.ManyToManyField(to="Author",db_constraint=False)
    
        class Meta:
            verbose_name_plural = "书表" # admin中表名的显示
    
        def __str__(self):
            return self.name
    
        @property
        def publish_name(self):
            return self.publish.name
    
        def author_list(self):
            # 拿到所有作者
            author_list = self.authors.all()
            ll = []
            for author in author_list:
                ll.append({'name':author.name,'sex':author.get_sex_display()})
            return ll
            # 列表推导式,太长了就别用了
            # return [{'name':author.name,'sex':author.get_sex_display()} for author in author_list]
    
    
    class Publish(BaseModel):
        name = models.CharField(max_length=32,verbose_name="出版社")
        addr = models.CharField(max_length=32,verbose_name="地址")
    
        class Meta:
            verbose_name_plural = "出版社"
    
        def __str__(self):
            return self.name
    
    class Author(BaseModel):
        name = models.CharField(max_length=32,verbose_name="作者")
        sex = models.IntegerField(choices=((1,"男"),(2,'女'),),verbose_name="性别")
    
        # 一对一关系,关联字段写在查询频率高的那一方
        # OneToOneField本质就是ForeignKey + unique,自己手动写也可以
        author_Detail = models.OneToOneField(to="AuthorDetail",db_constraint=False,on_delete=models.CASCADE)
    
        class Meta:
            verbose_name_plural = "作者表"
    
        def __str__(self):
            return self.name
    
    
    class AuthorDetail(BaseModel):
        mobile = models.CharField(max_length=11,verbose_name="手机号")
    
        class Meta:
            verbose_name_plural = "作者详情表"
    
        def __str__(self):
            return self.mobile
    
    
    # 表断关联
    # 1.表之间没有外键关联,但是有外键逻辑关联(有充当外键的字段)
    # 2.断关系后不会影响数据查询效率,但是会极大提高数据库增删改效率(不影响增删改查操作)
    # 3.断关系一定要通过逻辑保证表支架数据安全
    # 4.断关联
    # 5.级联关系
        # <1> 作者没了,详情也没了:on_delete = models.CASCADE
        # <2> 出版社没了,书还是那个出版社出版:on_delete = models.DO_NOTHING
        # <3> 部门没了,员工没有部门(空不能):null = True ,on_delete = models.SET_NULL
        # <4> 部门没了,员工进入默认部门(默认值):default = 0,on_delete = models.SET_DEFAULT
    

    ② ser.py

    from api import models
    from rest_framework import serializers
    
    
    # 写一个类,继承ListSerializer,重写修改数据时需要执行的update方法
    class BookListSerializer(serializers.ListSerializer):
        # def create(self, validated_data):
        # 这是重写新增数据时需要执行的方法
        # print(validated_data)
        # return super().create(validated_data)
        def update(self, instance, validated_data):
            # 这是重写修改数据时需要执行的方法
            # instance = book_list,数据格式是:[book1,book2,book3]
            # validated_data = modify_data,数据格式是:[{name:jason,price:12},{name:jason,price:12}]
    
            # 此处的self.child是BookSerializer对象,但是需要在BookSerializer中的Meta中配置一句话
            # list_serializer_class = BookListSerializer
            print("----》",instance)
            print("---->",validated_data)
    
            # ll = []
            # for i,si_data in enumerate(validated_data):
            #     result = self.child.update(instance[i],si_data)
            #     ll.append(result)
            # return ll
            """上面的方法和下面的方法一致"""
            return [
                self.child.update(instance[i], attrs) for i, attrs in enumerate(validated_data)
    
                # self.child.update(instance[i], attrs) for i, attrs in enumerate(validated_data)
                # def update(self, instance = instance[i], validated_data = attrs):
                #   pass
            ]
    
    
    # 如何序列化的是数据库的表,尽量用ModelSerializer
    class BookSerializer(serializers.ModelSerializer):
        # depth:控制的是在前端展示的外键数据
        # 因为数据库中的有些数据不需要在前端展示,所以需要在后端处理展示的信息
    
        # 方式一:只序列化可以,反序列化会出现问题
        # publish = serializers.CharField(source="publish.name")
    
        # 方式二:在models中写方法
        # ...
    
        class Meta:
            list_serializer_class = BookListSerializer
            model = models.Book
            # fields = "__all__"
            # 控制前端展示的数据信息,用得少
            # depth = 0
    
            fields = ('id','name', 'price', 'authors', 'publish', 'publish_name', 'author_list')
            extra_kwargs = {
                'publish': {'write_only': True},
                'publish_name': {"read_only": True},
                'authors': {'write_only': True},
                'author_list': {"read_only": True},
            }
    

    ③ urls.py

    # 使用了路由分发
    from django.conf.urls import url
    from api import views
    
    urlpatterns = [
        # 此处一定要记得,特殊的路由放在上面,避免匹配到 
        url(r'books/(?P<pk>d+)', views.BookAPIView.as_view()),
        url(r'books/', views.BookAPIView.as_view()),
    ]
    

    ④ views.py

    """单查群查、单增群增、单改群改、单删群删"""
    class BookAPIView(APIView):
        # 删除一条和多条数据
        def delete(self,request,*args,**kwargs):
            # 多条单条一起删除
            pk = kwargs.get('pk')
            pks = []
            if pk:
                """删除一条数据"""
                # 此处的pk是前端在url路径后面拼接的数据pk
                # append进pks是为了后面一起删除数据
                print(pk)
                pks.append(pk)
            else:
                """删除多条数据"""
                # 此处的pks是前端在body中传入的需要删除的数据的pk
                # 前端传回来的数据格式是{'pks':[1,2,3]}
                # 直接赋值给pks是为了后面一起删除数据
    
                pks = request.data.get('pks')
            # 数据并不是真正的删除,只是将is_delete字段改成False而已
            # result 是返回受影响的字段数,是一个int类型
            result = models.Book.objects.filter(pk__in=pks,is_delete=False).update(is_delete=True)
            if result > 0:
                return Response(data='删除成功')
            else:
                return Response(data="删除失败")
    
    
    

    三、单群查

    ① models.py

    from django.db import models
    
    
    class BaseModel(models.Model):
        is_delete = models.BooleanField(default=False)
    
        # auto_now_add = True 只要记录创建,不需要手动插入时间,自动版当前时间插入
        create_time = models.DateTimeField(auto_now_add=True)
        # auto_now = True 只要更新,就会把当前时间插入
        last_update_time = models.DateTimeField(auto_now=True)
        # 此处的Datetime.datetime.now不需要加括号,加括号和不加括号有很大的区别
        # create_time = models.DateTimeField(default=Datetime.datetime.now)
    
        class Meta:
            # 单个字段,有索引,有唯一
            # 多个字段,又联合索引,联合唯一
            abstract = True # 抽象表,不在数据库中创建实际表
    
    
    class Book(BaseModel):
        id = models.AutoField(primary_key=True)
        name = models.CharField(max_length=32,verbose_name="书名")
        price = models.DecimalField(max_digits=5,decimal_places=2,verbose_name="价格")
    
        # 一对多关系一旦确立,关联字段写在多的一边
        # to_field 默认不写,关联到Publish主键
        # db_constraint = False 逻辑上的关联,实质上没有外键联系,增删不会受外键影响,但是orm查询不影响
        publish = models.ForeignKey(to="Publish",on_delete=models.DO_NOTHING,db_constraint=False)
    
        # 多对多关系,跟作者  关联字段写在查询次数多的一方
    
        # 什么时候使用自动,什么时候使用手动? 第三张表只有关联字段,用自动;  第三张表有扩展字段,需要手动写
        # 不能写on_delete 因为使用自动的话,这是orm帮我们建的关系表,不会真正作用到数据库中
        authors = models.ManyToManyField(to="Author",db_constraint=False)
    
        class Meta:
            verbose_name_plural = "书表" # admin中表名的显示
    
        def __str__(self):
            return self.name
    
        @property
        def publish_name(self):
            return self.publish.name
    
        def author_list(self):
            # 拿到所有作者
            author_list = self.authors.all()
            ll = []
            for author in author_list:
                ll.append({'name':author.name,'sex':author.get_sex_display()})
            return ll
            # 列表推导式,太长了就别用了
            # return [{'name':author.name,'sex':author.get_sex_display()} for author in author_list]
    
    
    class Publish(BaseModel):
        name = models.CharField(max_length=32,verbose_name="出版社")
        addr = models.CharField(max_length=32,verbose_name="地址")
    
        class Meta:
            verbose_name_plural = "出版社"
    
        def __str__(self):
            return self.name
    
    class Author(BaseModel):
        name = models.CharField(max_length=32,verbose_name="作者")
        sex = models.IntegerField(choices=((1,"男"),(2,'女'),),verbose_name="性别")
    
        # 一对一关系,关联字段写在查询频率高的那一方
        # OneToOneField本质就是ForeignKey + unique,自己手动写也可以
        author_Detail = models.OneToOneField(to="AuthorDetail",db_constraint=False,on_delete=models.CASCADE)
    
        class Meta:
            verbose_name_plural = "作者表"
    
        def __str__(self):
            return self.name
    
    
    class AuthorDetail(BaseModel):
        mobile = models.CharField(max_length=11,verbose_name="手机号")
    
        class Meta:
            verbose_name_plural = "作者详情表"
    
        def __str__(self):
            return self.mobile
    
    
    # 表断关联
    # 1.表之间没有外键关联,但是有外键逻辑关联(有充当外键的字段)
    # 2.断关系后不会影响数据查询效率,但是会极大提高数据库增删改效率(不影响增删改查操作)
    # 3.断关系一定要通过逻辑保证表支架数据安全
    # 4.断关联
    # 5.级联关系
        # <1> 作者没了,详情也没了:on_delete = models.CASCADE
        # <2> 出版社没了,书还是那个出版社出版:on_delete = models.DO_NOTHING
        # <3> 部门没了,员工没有部门(空不能):null = True ,on_delete = models.SET_NULL
        # <4> 部门没了,员工进入默认部门(默认值):default = 0,on_delete = models.SET_DEFAULT
    

    ② ser.py

    from api import models
    from rest_framework import serializers
    
    
    # 写一个类,继承ListSerializer,重写修改数据时需要执行的update方法
    class BookListSerializer(serializers.ListSerializer):
        # def create(self, validated_data):
        # 这是重写新增数据时需要执行的方法
        # print(validated_data)
        # return super().create(validated_data)
        def update(self, instance, validated_data):
            # 这是重写修改数据时需要执行的方法
            # instance = book_list,数据格式是:[book1,book2,book3]
            # validated_data = modify_data,数据格式是:[{name:jason,price:12},{name:jason,price:12}]
    
            # 此处的self.child是BookSerializer对象,但是需要在BookSerializer中的Meta中配置一句话
            # list_serializer_class = BookListSerializer
            print("----》",instance)
            print("---->",validated_data)
    
            # ll = []
            # for i,si_data in enumerate(validated_data):
            #     result = self.child.update(instance[i],si_data)
            #     ll.append(result)
            # return ll
            """上面的方法和下面的方法一致"""
            return [
                self.child.update(instance[i], attrs) for i, attrs in enumerate(validated_data)
    
                # self.child.update(instance[i], attrs) for i, attrs in enumerate(validated_data)
                # def update(self, instance = instance[i], validated_data = attrs):
                #   pass
            ]
    
    
    # 如何序列化的是数据库的表,尽量用ModelSerializer
    class BookSerializer(serializers.ModelSerializer):
        # depth:控制的是在前端展示的外键数据
        # 因为数据库中的有些数据不需要在前端展示,所以需要在后端处理展示的信息
    
        # 方式一:只序列化可以,反序列化会出现问题
        # publish = serializers.CharField(source="publish.name")
    
        # 方式二:在models中写方法
        # ...
    
        class Meta:
            list_serializer_class = BookListSerializer
            model = models.Book
            # fields = "__all__"
            # 控制前端展示的数据信息,用得少
            # depth = 0
    
            fields = ('id','name', 'price', 'authors', 'publish', 'publish_name', 'author_list')
            extra_kwargs = {
                'publish': {'write_only': True},
                'publish_name': {"read_only": True},
                'authors': {'write_only': True},
                'author_list': {"read_only": True},
            }
    

    ③ urls.py

    # 使用了路由分发
    from django.conf.urls import url
    from api import views
    
    urlpatterns = [
        # 此处一定要记得,特殊的路由放在上面,避免匹配到 
        url(r'books/(?P<pk>d+)', views.BookAPIView.as_view()),
        url(r'books/', views.BookAPIView.as_view()),
    ]
    

    ④ views.py

    """单查群查、单增群增、单改群改、单删群删"""
    class BookAPIView(APIView):
        # 查询一条和多条数据
        def get(self, request, *args, **kwargs):
            # 查询单个和查询所有,合到一起
            if kwargs.get('pk', None): # 查询一条数据
                book_obj = models.Book.objects.filter(pk=kwargs.get('pk'), is_delete=False).first()
                book_ser = ser.BookSerializer(instance=book_obj)
                return Response(data=book_ser.data)
            else: # 此处是查询所有
                book_list_obj = models.Book.objects.all().filter(is_delete=False)
                book_list_ser = ser.BookSerializer(instance=book_list_obj, many=True)
                return Response(data=book_list_ser.data)
    

    四、单群改

    ① models.py

    from django.db import models
    
    
    class BaseModel(models.Model):
        is_delete = models.BooleanField(default=False)
    
        # auto_now_add = True 只要记录创建,不需要手动插入时间,自动版当前时间插入
        create_time = models.DateTimeField(auto_now_add=True)
        # auto_now = True 只要更新,就会把当前时间插入
        last_update_time = models.DateTimeField(auto_now=True)
        # 此处的Datetime.datetime.now不需要加括号,加括号和不加括号有很大的区别
        # create_time = models.DateTimeField(default=Datetime.datetime.now)
    
        class Meta:
            # 单个字段,有索引,有唯一
            # 多个字段,又联合索引,联合唯一
            abstract = True # 抽象表,不在数据库中创建实际表
    
    
    class Book(BaseModel):
        id = models.AutoField(primary_key=True)
        name = models.CharField(max_length=32,verbose_name="书名")
        price = models.DecimalField(max_digits=5,decimal_places=2,verbose_name="价格")
    
        # 一对多关系一旦确立,关联字段写在多的一边
        # to_field 默认不写,关联到Publish主键
        # db_constraint = False 逻辑上的关联,实质上没有外键联系,增删不会受外键影响,但是orm查询不影响
        publish = models.ForeignKey(to="Publish",on_delete=models.DO_NOTHING,db_constraint=False)
    
        # 多对多关系,跟作者  关联字段写在查询次数多的一方
    
        # 什么时候使用自动,什么时候使用手动? 第三张表只有关联字段,用自动;  第三张表有扩展字段,需要手动写
        # 不能写on_delete 因为使用自动的话,这是orm帮我们建的关系表,不会真正作用到数据库中
        authors = models.ManyToManyField(to="Author",db_constraint=False)
    
        class Meta:
            verbose_name_plural = "书表" # admin中表名的显示
    
        def __str__(self):
            return self.name
    
        @property
        def publish_name(self):
            return self.publish.name
    
        def author_list(self):
            # 拿到所有作者
            author_list = self.authors.all()
            ll = []
            for author in author_list:
                ll.append({'name':author.name,'sex':author.get_sex_display()})
            return ll
            # 列表推导式,太长了就别用了
            # return [{'name':author.name,'sex':author.get_sex_display()} for author in author_list]
    
    
    class Publish(BaseModel):
        name = models.CharField(max_length=32,verbose_name="出版社")
        addr = models.CharField(max_length=32,verbose_name="地址")
    
        class Meta:
            verbose_name_plural = "出版社"
    
        def __str__(self):
            return self.name
    
    class Author(BaseModel):
        name = models.CharField(max_length=32,verbose_name="作者")
        sex = models.IntegerField(choices=((1,"男"),(2,'女'),),verbose_name="性别")
    
        # 一对一关系,关联字段写在查询频率高的那一方
        # OneToOneField本质就是ForeignKey + unique,自己手动写也可以
        author_Detail = models.OneToOneField(to="AuthorDetail",db_constraint=False,on_delete=models.CASCADE)
    
        class Meta:
            verbose_name_plural = "作者表"
    
        def __str__(self):
            return self.name
    
    
    class AuthorDetail(BaseModel):
        mobile = models.CharField(max_length=11,verbose_name="手机号")
    
        class Meta:
            verbose_name_plural = "作者详情表"
    
        def __str__(self):
            return self.mobile
    
    
    # 表断关联
    # 1.表之间没有外键关联,但是有外键逻辑关联(有充当外键的字段)
    # 2.断关系后不会影响数据查询效率,但是会极大提高数据库增删改效率(不影响增删改查操作)
    # 3.断关系一定要通过逻辑保证表支架数据安全
    # 4.断关联
    # 5.级联关系
        # <1> 作者没了,详情也没了:on_delete = models.CASCADE
        # <2> 出版社没了,书还是那个出版社出版:on_delete = models.DO_NOTHING
        # <3> 部门没了,员工没有部门(空不能):null = True ,on_delete = models.SET_NULL
        # <4> 部门没了,员工进入默认部门(默认值):default = 0,on_delete = models.SET_DEFAULT
    

    ② ser.py

    from api import models
    from rest_framework import serializers
    
    
    # 写一个类,继承ListSerializer,重写修改数据时需要执行的update方法
    class BookListSerializer(serializers.ListSerializer):
        # def create(self, validated_data):
        # 这是重写新增数据时需要执行的方法
        # print(validated_data)
        # return super().create(validated_data)
        def update(self, instance, validated_data):
            # 这是重写修改数据时需要执行的方法
            # instance = book_list,数据格式是:[book1,book2,book3]
            # validated_data = modify_data,数据格式是:[{name:jason,price:12},{name:jason,price:12}]
    
            # 此处的self.child是BookSerializer对象,但是需要在BookSerializer中的Meta中配置一句话
            # list_serializer_class = BookListSerializer
            print("----》",instance)
            print("---->",validated_data)
    
            # ll = []
            # for i,si_data in enumerate(validated_data):
            #     result = self.child.update(instance[i],si_data)
            #     ll.append(result)
            # return ll
            """上面的方法和下面的方法一致"""
            return [
                self.child.update(instance[i], attrs) for i, attrs in enumerate(validated_data)
    
                # self.child.update(instance[i], attrs) for i, attrs in enumerate(validated_data)
                # def update(self, instance = instance[i], validated_data = attrs):
                #   pass
            ]
    
    
    # 如何序列化的是数据库的表,尽量用ModelSerializer
    class BookSerializer(serializers.ModelSerializer):
        # depth:控制的是在前端展示的外键数据
        # 因为数据库中的有些数据不需要在前端展示,所以需要在后端处理展示的信息
    
        # 方式一:只序列化可以,反序列化会出现问题
        # publish = serializers.CharField(source="publish.name")
    
        # 方式二:在models中写方法
        # ...
    
        class Meta:
            list_serializer_class = BookListSerializer
            model = models.Book
            # fields = "__all__"
            # 控制前端展示的数据信息,用得少
            # depth = 0
    
            fields = ('id','name', 'price', 'authors', 'publish', 'publish_name', 'author_list')
            extra_kwargs = {
                'publish': {'write_only': True},
                'publish_name': {"read_only": True},
                'authors': {'write_only': True},
                'author_list': {"read_only": True},
            }
    

    ③ urls.py

    # 使用了路由分发
    from django.conf.urls import url
    from api import views
    
    urlpatterns = [
        # 此处一定要记得,特殊的路由放在上面,避免匹配到 
        url(r'books/(?P<pk>d+)', views.BookAPIView.as_view()),
        url(r'books/', views.BookAPIView.as_view()),
    ]
    

    ④ views.py

    """单查群查、单增群增、单改群改、单删群删"""
    class BookAPIView(APIView):
        # 修改一条和多条数据
        def put(self, request, *args, **kwargs):
            if kwargs.get('pk', None):  # 修改一条数据
                # kwargs中如果没有pk这个键,就返回None,也就是不会走if中的代码
                book_obj = models.Book.objects.filter(pk=kwargs.get("pk")).first()
                book_ser = ser.BookSerializer(instance=book_obj, data=request.data)
                book_ser.save()
                return Response(request.data)
            else:  # 改多条数据
                """第一种方式,序列化器的代码不需要修改"""
    
                # book_list = []  # 此时book_list类似于[book1,book2,book3]格式的数据
                # modify_data = []  # 此时的modify_data类似于[{name:jason,price:12},{name:jason,price:12}]格式的数据
                # for item in request.data:  # 此时request.data是一个列表套字典格式的数据
                #     pk = item.pop('id')
                #     book = models.Book.objects.filter(pk=pk).first()
                #     book_list.append(book)
                #     modify_data.append(item)
                #
                # for i,si_data in modify_data:
                #     book_ser = ser.BookSerializer(instance=book_list[i],data=si_data)
                #     book_ser.is_valid(raise_exception=True)
                #     book_ser.save()
                #     return Response(data="成功")
    
                """第二种方式:复杂点,并且需要配合序列化器,实现的代码全都写在序列化器中"""
                # print(request.data)
                # return Response(request.data)
                # 前端传过来的数据格式:[{id:1,name:jason,price:12},{id:1,name:jason,price:12},{id:1,name:jason,price:12}]
                # 处理后的数据 对象列表instance = [book1,book2,book3] 修改的数据列表data = [{name:jason,price:12},{name:jason,price:12}]
                book_list = []  # 此时book_list类似于[book1,book2,book3]格式的数据
                modify_data = []  # 此时的modify_data类似于[{name:jason,price:12},{name:jason,price:12}]格式的数据
                for item in request.data:  # 此时request.data是一个列表套字典格式的数据
                    pk = item.pop('id')
                    book = models.Book.objects.filter(pk=pk).first()
                    book_list.append(book)
                    modify_data.append(item)
                # 序列化
                book_list_ser = ser.BookSerializer(instance=book_list, data=modify_data, many=True)
                # 校验数据
                book_list_ser.is_valid(raise_exception=True)
                # 保存数据
                book_list_ser.save()  # 此时的save()方法是ListSerializer的update方法,但是我们现在自己写一个update方法,使用哪自己的方法
                return Response(book_list_ser.data)
    
  • 相关阅读:
    装饰器模式
    mockups 安装
    单例设计模式
    css优先级问题
    GPU的nvadiasmi解析
    conda配置镜像并安装gpu版本pytorch和tensorflow2
    索引的优化
    [转]必须掌握的八个【cmd 命令行】
    BDE莫名的不自动COMMIT问题
    窗体控件笔记
  • 原文地址:https://www.cnblogs.com/borntodie/p/14330818.html
Copyright © 2011-2022 走看看