day83-drf

基表的作用(继承)

class BaseModel(models.Model):
    create_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True)
    is_delete = models.BooleanField(verbose_name='是否删除', default=False)
    class Meta:     
        abstract = True                   # 有该属性的Model类不会完成数据库迁移产生一张表 


class Publish(BaseModel):
    name = models.CharField(verbose_name='出版社名', max_length=32)
    address = models.CharField(verbose_name='地址', max_length=64)
    phone = models.CharField(verbose_name='电话', max_length=32)

配置media静态文件(图片路径)

settings.py:

MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

models.py:

class Author(BaseModel):
    name = models.CharField(verbose_name='作者名', max_length=32)
    icon = models.FileField(upload_to='icon', default='icon/icon.jpg')      #传入路径和默认路径
    telephone = models.CharField(verbose_name='电话', max_length=32)

其他模型类中自定义显示字段:
@property
def author_detail_list(self):
    author_detail_arr = []
    for author in self.authors.all():
        author_dic = {}      
        author_dic['icon'] = settings.MEDIA_URL + str(author.icon)       # author.icon是对象类型,不能序列化
        author_detail_arr.append(author_dic)
    return author_detail_arr

模型表的外键字段处理方法

外键处理:

1.反向查询:related_name='xxx'

2.表关系(db_constraint + on_delete ): 
    db_constraint=False                         数据库断开关联 ,也就是操作数据库时不进行逻辑判断,但用orm逻辑判断操作数据库
    on_delete=models.CASCADE                    级联删除,多对多表不需要写,因为默认级联删除
    on_delete=models.SET_NULL, null=True        删除时,外键字段为为空
    on_delete=models.SET_DEFAULT, default=0     删除时,外键字段为0
    on_delete=models.DO_NOTHING                 删除时,外键字段不处理  
案例:
class
AuthorDetail(BaseModel): CHOICE_SEX = ( (0, ''), (1, '') ) age = models.IntegerField(verbose_name='年龄') sex = models.IntegerField(verbose_name='性别', choices=CHOICE_SEX, default=0) info = models.TextField(verbose_name='个人详情') author = models.OneToOneField(verbose_name='作者', to='Author', db_constraint=False, on_delete=models.CASCADE, related_name='detail')

 模型类

class Book(BaseModel):
    name = models.CharField(verbose_name='书名', max_length=32)
    price = models.DecimalField(verbose_name='价格', max_digits=5, decimal_places=2, default=66.66)
    authors = models.ManyToManyField(verbose_name='作者们', to='Author', db_constraint=False, related_name='books')       
    publish = models.ForeignKey(verbose_name='出版社', to='Publish', db_constraint=False, on_delete=models.CASCADE,
                                related_name='books')

    class Meta:
        db_table = 'o_Book'
        verbose_name = '书籍'
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.name

    
    @property
    def publish_name(self):                                                       # 插拔字段(序列化使用):默认为read_only(不需要考虑反序列化),且不能修改为write_only    
        return self.publish.name

    @property
    def publish_detail(self):
        from . import serializers
        return serializers.PublishesModelSerializer(self.publish).data            #序列化

序列化类

class PublishesModelSerializer(serializers.ModelSerializer):
    class Meta:
        fields = ('name', 'address', 'phone')
        model = models.Publish
        extra_kwargs = {}


class BooksListSerializer(serializers.ListSerializer):
    
    def create(self, validated_data):                                   # ListSerializer已提供create的实现体,有特殊需求可以重写
        return super().create(validated_data)

    
    def update(self, instance, validated_data):                         # ListSerializer未提供update的实现体,必须重写
        for index, book_obj in enumerate(instance):
            book_dic = validated_data[index] 
            for k, v in book_dic.items():
                if hasattr(book_obj, k):
                    setattr(book_obj, k, v)
           
            book_obj.save()                                              # 同步到数据库
        return instance



class BooksModelSerializer(serializers.ModelSerializer):
 
    class Meta:                                                            #正反序列化都会用到的字段

    list_serializer_class = BooksListSerializer                      # 设置群体资源(多个)校验类
    
        fields = '__all__'                                                 # 提供该表所有字段
      
        exclude = ('id', 'create_time', 'is_delete')                       # 刨除该表的某些字段 - 不常用
                
        depth = 1                                                          # 自动深度查询(正向查询往下) - 不常用 
       
        fields = ('name', 'price', 'publish', 'authors', 'publish_name')   # 提供该表的字段和插拔式自定义字段(自定义只能在fields使用)
        
        model = models.Book
        
        
        extra_kwargs = {
         
            'authors': {
                'write_only': True                                          # 可以区分序列化与反序列化字段
            },
            'publish_name': {
                'read_only': True,
            },
            'price': {
                'required': True,                                           
                'error_messages': {                                         #提供系统默认校验信息即校验失败信息
                    'required': '价格不能为空',
                }
            },
            'name': {
                'min_length': 3,
                'error_messages': {
                    'min_length': '太短',
                }
            },
        }
    

    def validate_name(self, value: str):
      print(self.context.get('owner'))                    # 拿视图类context传递过来的参数
      if not value.isidentifier():
        raise serializers.ValidationError('名字非法')
      return value

def create(self, validated_data):                                      #ModelSerializer重写了 update 和 create,如果没有特殊业务要求,可以不需要再重写
        authors = validated_data.pop('authors')
        book_obj = models.Book.objects.create(**validated_data)
        book_obj.authors.add(*authors)
        return book_obj

视图类(十大接口)


模型表继承MSerializer类时,没有写create和update方法,需要自己写
模型表继承ModelSerializer类时,已经写了create和update方法
模型表继承ListSerializer类时,已经写了群|单create,但update方法没有写,可以在序列化类配置,表示多数据时会走这个类的create,update

from
rest_framework.views import APIView from rest_framework.response import Response from rest_framework import status from . import models, serializers from utils.response import APIResponse class BooksAPIView(APIView): def get(self, request, *args, **kwargs): # 获取所有 | 一个 pk = kwargs.get('pk') if pk: books_query = models.Book.objects.filter(is_delete=False, pk=pk) else: books_query = models.Book.objects.filter(is_delete=False).order_by('id') books_data = serializers.BooksModelSerializer(books_query, many=True).data return APIResponse(0, 'ok', books_data) def post(self, request, *args, **kwargs): # 新增多个 | 一个(这里重写create) request_data = request.data many = True if isinstance(request_data, list) else False book_ser = serializers.BooksModelSerializer(data=request_data, many=many) if book_ser.is_valid(): book_obj_list = book_ser.save() return APIResponse(0, 'ok', serializers.BooksModelSerializer(book_obj_list, many=many).data) else: return APIResponse(1, 'failed', book_ser.errors) def put(self, request, *args, **kwargs): # 整体修改一个 pk = kwargs.get('pk', 1) book_obj = models.Book.objects.filter(pk=pk, is_delete=False).first() book_ser = serializers.BooksModelSerializer(instance=book_obj, data=request.data) #必须传obj if book_ser.is_valid(): #更新用系统的 book_obj = book_ser.save() return Response({ 'status': 0, 'msg': 'ok', 'results': serializers.BooksModelSerializer(book_obj).data }) else: return Response({ 'status': 1, 'msg': 'failed', 'results': book_ser.errors }) def patch(self, request, *args, **kwargs): request_data = request.data if isinstance(request_data, list): #局部群改:往 /Books/ 发送 [{"pk":1,"name":"西游记"},{"pk":2,"price":"1.00"}] pks = [book_dic.pop('pk') for book_dic in request_data] else: #局部单改:往 /Books/(pk)/ 发送 {"name":"西游记"} pks = [kwargs.get('pk')] request_data = [request_data] book_query = models.Book.objects.filter(pk__in=pks, is_delete=False) book_ser = serializers.BooksModelSerializer(partial=True, many=True, instance=book_query, data=request_data,context={‘xxx’:‘123’}) #partial=True允许局部操作反序列化字段,context=是给序列化类传递参数 if book_ser.is_valid(): book_obj_list = book_ser.save() return APIResponse(0, 'ok', serializers.BooksModelSerializer(book_obj_list, many=True).data) else: return APIResponse(1, 'failed', book_ser.errors) def delete(self, request, *args, **kwargs): # 删除一个 /books/1/ | 删除多个 /books/ 数据[1, 2] pk = kwargs.get('pk') if pk: pks = [pk] else: pks = request.data delete_rows = models.Book.objects.filter(pk__in=pks, is_delete=False).update(is_delete=True) if delete_rows != 0: return APIResponse(0, 'ok') return APIResponse(1, '删除失败')

 Response类的详解

class PublishesAPIView(APIView):
    
    def get(self, request, *args, **kwargs):
        publishes_query = models.Publish.objects.all()
        publishes_data = serializers.PublishesModelSerializer(publishes_query, many=True).data

        # return Response({
        #     'status': 0,
        #     'msg': 'ok',
        #     'results': publishes_data
        # })

        from utils.response import APIResponse
        return APIResponse(0, 'ok', result=123,
                           headers={
            'Token': 'as12df.88og5z.qw12cv'
        }, status=status.HTTP_511_NETWORK_AUTHENTICATION_REQUIRED)

  data:要返回给前台的数据
  status:响应的网络状态码
  template_name:drf也可以渲染页面
  headers:响应头
  exception:异常信息
  content_type:响应的数据类型,接口默认application/json

 Response类的二次封装

from rest_framework.response import Response
class APIResponse(Response):
    def __init__(self, data_status, msg, results=None, headers=None, status=None, **kwargs):
        data = {
            'status': data_status,
            'msg': msg,
        }
        if results:
            data['results'] = results
        data.update(kwargs)
        super().__init__(data=data, headers=headers, status=status)
原文地址:https://www.cnblogs.com/klw1/p/11361517.html