基表的作用(继承)
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)