DRF---多表序列化,请求与响应,知识补充

1 多表序列化

# 图书表,出版社表,作者,作者详情   (中间表)

1.1 路由

urlpatterns = [
    path('admin/', admin.site.urls),
    path('books/', views.BookView.as_view()),
    path('books/<int:pk>', views.BookDetailView.as_view()),
]

1.2 视图类

from .models import Book,Author,AuthorDetail,Publish
from rest_framework.response import Response
from .serializer import BookSerializer
class BookView(APIView):
    def get(self, request):
        book_list=Book.objects.all()
        #序列化
        ser=BookSerializer(book_list,many=True)
        return Response(ser.data)

    # 反序列化的新增
    def post(self,request):
        ser=BookSerializer(data=request.data)
        if ser.is_valid():
            ser.save()
            return Response({'code':100,'msg':'新增成功'})
        else:
            return Response({'code':101,'msg':'新增失败','err':ser.errors})

class BookDetailView(APIView):
    def get(self, request,pk):
        book=Book.objects.all().filter(pk=pk).first()
        ser=BookSerializer(book)
        return Response(ser.data)

    def put(self,request,pk):
        book = Book.objects.all().filter(pk=pk).first()
        ser = BookSerializer(instance=book,data=request.data)
        if ser.is_valid():
            ser.save()
            return Response({'code':100,'msg':'修改成功'})
        else:
            return Response({'code':101,'msg':'修改失败','err':ser.errors})

1.3 序列化类


from rest_framework import serializers
# 相对导入---->一个py文件中如果使用相对导入,这个文件不能以脚本运行
from .models import Book
# # 绝对导入
# from app01.models import Book


class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model=Book
        # fields="__all__"
        fields=['nid','name','price',    'publish_detail', 'author_list',    'publish','authors']
        # depth   不要用  --->外键关联一层,我建议不要超过3  不可控,比如我们只想要某几个字段
        # depth=1
        extra_kwargs={
            'publish':{'write_only':True},
            'authors': {'write_only': True},
        }

    # 方式一:重写字段+必须配合一个方法,方法返回啥,该字段就是什么--->该字段只能序列化
    publish_detail=serializers.SerializerMethodField(read_only=True)
    def get_publish_detail(self,obj):
        # 就是当前 book对象
        print(obj)
        # return obj.publish.name
        return {'name':obj.publish.name,'city':obj.publish.city}

    # 方式二:在表模型models中写方法,在序列化类中写到fields中


    # 把所有的作者:作者名字和作者addr
    # 方式一
    author_list=serializers.SerializerMethodField(read_only=True)
    def get_author_list(self,obj):
        # 作者有多个,先拿到所有作者,---》正向查询
        author_list=[]
        for author in obj.authors.all():
            author_list.append({'name':author.name,'addr':author.author_detail.addr})
        return author_list



1.4 模型类

from django.db import models

# Create your models here.
class Book(models.Model):
    nid = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    price = models.DecimalField(max_digits=5, decimal_places=2)
    # publish_date = models.DateField(null=True)

    #关联关系
    publish = models.ForeignKey(to='Publish',to_field='nid',on_delete=models.CASCADE)
    authors=models.ManyToManyField(to='Author')  #自动生成中间表
    def __str__(self):
        return self.name

    # def publish_detail(self):
    #     return {'name':self.publish.name,'email':self.publish.email}

    # 作者详情
    # def author_list(self):
    #     author_list=[]
    #     for author in self.authors.all():
    #         author_list.append({'name':author.name,'addr':author.author_detail.addr})
    #     return author_list


class Author(models.Model):
    nid = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    age = models.IntegerField()
    author_detail = models.OneToOneField(to='AuthorDetail',on_delete=models.CASCADE)

    '''
     on_delete可以选择的请情况
        -models.CASCADE   级联删除
        -models.SET_NULL  关联字段置为空    null=True
        -models.SET_DEFAULT 关联字段设为默认值 default=0
        -models.DO_NOTHING     由于数据库有约束会报错,去掉外键关系(公司都不建立外键)
        -on_delete=models.SET(值,函数内存地址)  设置上某个值,或者运行某个函数
    
    
    '''


class AuthorDetail(models.Model):
    nid = models.AutoField(primary_key=True)
    telephone = models.BigIntegerField()
    birthday = models.DateField()
    addr = models.CharField(max_length=64)


class Publish(models.Model):
    nid = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    city = models.CharField(max_length=32)
    email = models.EmailField()
    def __str__(self):
        return self.name

2 请求与响应

2.1 请求

# django ---->请求对象----》request
# django ---->响应对象----》render,HttpResponse,Redirect,JsonResponse---》本质都是HttpResponse

# drf中---》请求对象----》新的request---》drf的Request类的对象
# drf的请求对象
	-request.data
    -request.query_params
    -request.FILES
    
# 控制前端传入的编码格式---》默认 :urlencoded,form-data,json
	# 全局生效
	-项目配置文件中加入
        REST_FRAMEWORK = {
            'DEFAULT_PARSER_CLASSES':[
                'rest_framework.parsers.JSONParser',  # 能够解析json
        		'rest_framework.parsers.FormParser',  # 能够解析urlencoded
        		'rest_framework.parsers.MultiPartParser', #能够解析form-data
               ],
        }
    # 局部生效---》视图类中配置
    class BookView(APIView):
    	parser_classes = [JSONParser,]
        
        
   # 优先级:先找 视图类---》项目配置文件----》drf配置文件

2.2 响应

from rest_framework.response import Response

#初始化对象,传入的参数,response对象的属性
    data=None,   # 要序列化的数据,字典,列表,字符串
    status=None, # http响应状态码
    headers=None, # 响应头---》字典
    -------最重要的-----
    template_name=None, #模板名字---》浏览器看的时候,看到好看的页面,postman看,纯json
    content_type=None # 默认json格式,前后端分离项目,前端传用json,后端响应也用json格式
    
    
    
# 浏览器看的时候,看到好看的页面,postman看,纯json----》想控制,都是json格式,无论是浏览器还是postman

	# 全局生效
	-项目配置文件中加入
        REST_FRAMEWORK = {
            'DEFAULT_RENDERER_CLASSES':[
          		'rest_framework.renderers.JSONRenderer',   #json格式
        		'rest_framework.renderers.BrowsableAPIRenderer', #浏览器格式
               ],
        }
    # 局部生效---》视图类中配置
    class BookView(APIView):
    	renderer_classes = [JSONRenderer,BrowsableAPIRenderer]
        
        
   # 优先级:先找 视图类---》项目配置文件----》drf配置文件

3 视图介绍

# 今天写的5个接口 book的
# 如果让你写 publish的5个接口


# 1 多表的序列化,book表,5个接口写好
# 2 5个接口中,查询所有和新增一个,没有浏览器显示的样子
# 3 5个接口中,修改,只能用json格式



# 4 有余力的同学,尝试封装第一层,写5个接口
    class MyView(APIView):
        queryset = None
        serializer_class = None
        
# 5 写出5个视图扩展类,如果要写publish的接口

# 查询所有
class ListModelMixin():
    def list(self, request):
        book_list = self.qs
        print(book_list)
        ser = self.serializer_class(book_list, many=True)
        # return Response(ser.data,203,headers={'xx':'oo'})
        print(ser.data)
        return Response(ser.data)
    
 # 
class PublishView(MyView,ListModelMixin,CreateModelMixin):
    serializer_class = PublishSerializer
    qs = Publish.objects.all()
    def get(self,request):
        # 调用父类的list
        return super().list(request)
    # 反序列化的新增
    def post(self,request):
        return super().create(request)
    
    
----有余力的----
# 多对多,手动创建中间表
# 基于对象的 .  跨表查
# 基于双下滑线 的连表查询

补充

1 相对导入和绝对导入

# 绝对导入---》绝对指的是 环境变量   sys.path 里面的路径,项目跟路径在pycharm自动加入环境变量
# 相对导入---->一个py文件中如果使用相对导入,这个文件不能以脚本运行

2 django国际化配置

# django 国际化---》配置文件改

# 国际化相关
LANGUAGE_CODE = 'zh-hans'
#时区:改成东八区
TIME_ZONE = 'Asia/Shanghai'
USE_I18N = True
USE_L10N = True
USE_TZ = False

3 models 的级联删除相关

    '''
     on_delete可以选择的请情况
        -models.CASCADE   级联删除
        -models.SET_NULL  关联字段置为空    null=True
        -models.SET_DEFAULT 关联字段设为默认值 default=0
        -models.DO_NOTHING     由于数据库有约束会报错,去掉外键关系(公司都不建立外键)
        -on_delete=models.SET(值,函数内存地址)  设置上某个值,或者运行某个函数
    '''

4 原生django,如何向响应头写数据

def test(request):
    obj=HttpResponse('ok')
    # obj=render()
    # obj=redirect('/index')
    # obj=JsonResponse()
    obj['xxx']='ooo'  #直接放
    return obj
posted @   早安_1207  阅读(88)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
返回顶端
点击右上角即可分享
微信分享提示