DRF简单复习

DRF

上周回顾

1.web开发模型:   混合开发 前后端分离
2.web api   :    前后端传输的媒介(接口)json格式
3.postman使用 :   测接口  很多软件  非必须使用这个
4.# restful规范十条(面试很大可能会问)
5.djangorestframework   :django的第三方插件(也叫app),常用的第三方插件 内置的:auth、分页器、froms。  第三方:djangorestframework
6.drf好几大组件
    请求(apiview源码,request对象)和响应(response)
    序列化(重点)
    视图(第二重要)
    路由(手动写,自动生成)
    action装饰器
	解析器(DEFAULT_PARSER_CLASSES、全局配置、局部配置)
	响应器(DEFAULT_RENDERER_CLASSES、全局配置、局部配置)
    认证:验证是否登录(有内置、自定义、全局配置、局部配置)
	权限:是否有权限访问某些接口(有内置、自定义、全局配置、局部配置)
	频率:限制访问接口的访问频次(有内置、自定义、全局配置、局部配置、可以根据用户id或者ip)
    过滤:筛选符合条件的  #他其实不算内置的组件
    排序:对结果进行排序  #他其实不算内置的组件
    异常:全局异常(自定义,全局配)
    分页器:顾名思义,进行分页
    
    下面的不属于drf内置组件
    文档生成   
    jwt认证
    x

1.DRF简单复习

1.1DRF创建类

from django.db import models


# Create your models here.
class BaseModel(models.Model):
    is_delete = models.BooleanField(default=False)
    create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
    last_update_time = models.DateTimeField(auto_now=True, verbose_name='最后登录或修改时间')

    class Meta:
        # 单个字段有索引,有唯一
        # 多个字段,有联合索引,联合唯一
        abstract = True  # 抽象表,不在数据库建表


class Book(BaseModel):
    id = models.AutoField(primary_key=True)
    #verbose_name:中文显示  help_text:输入框的一个小注释
    title = models.CharField(max_length=32, verbose_name='书名',help_text='这里填书名')
    price = models.DecimalField(max_digits=5, decimal_places=2, verbose_name='价格')

    # 关联字段写在多的一方,to_field默认不用写 关联表的字段
    # db_constraint=False:逻辑上和Publish有关联,增删不受外键影响,orm查询不影响,本质就是保留跨表查询的便利(双下划线跨表查询```),但是不用约束字段了,一般公司都用false,这样就省的报错,因为没有了约束(Field字段对象,既约束,又建立表与表之间的关系)

    Publish = models.ForeignKey(to='Publish', on_delete=models.CASCADE, db_constraint=False, verbose_name='出版社')

    # 自动:第三张表只有关联字段    手动:可以进行扩展
    # 不能写on_delete 因为是第三张表
    authors = models.ManyToManyField(to='Author', db_constraint=False, verbose_name='作者')

    class Meta:
        # admin中的表名中文显示
        verbose_name_plural = '书籍表'

    def __str__(self):
        return self.title

class Publish(BaseModel):
    id = models.AutoField(primary_key=True)
    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='作者名字')
    gender = models.IntegerField(choices=((1, '男'), (2, '女')), verbose_name='性别')
    # 一对一 写在任意一方  OneToOneField本质其实就是foreignkey加unique
    authordetail = 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=32, verbose_name='电话号')


    class Meta:
        verbose_name_plural = '作者详情'

    def __str__(self):
        return self.mobile

#迁移数据库 makemigrations   migrate  创建超级用户  creatsuperuser

1.2DRF序列化类

from rest_framework import serializers

#如果序列化的是数据库的表,尽量用ModelSerializer
# 声明序列化器,所有的序列化器都要直接或者间接继承于 Serializer
# 其中,ModelSerializer是Serializer的子类,ModelSerializer在Serializer的基础上进行了代码简化
from api import models


class BookModelSerialzer(serializers.ModelSerializer):
    #解决多表联合显示问题
    #第一种方案 序列化可以 反序列化有问题
    # publish=serializers.CharField(source='publish.name')

    #第二种方案models中写方法 加上一个@property 这里调用

    class Meta:
        model = models.Book  #跟那个表建立关系
        #fields = '__all__' #序列化的字段
        #depth = 1 #表关联 1:查询关联的表的信息, 0:还是只显示id

        fields = ('title','price','authors','publish','publish_name','authors_list')
        #我们可以使用extra_kwargs参数为ModelSerializer添加或修改原有的选项参数
        extra_kwargs={
            'publish':{'write_only': True},
            'publish_name':{'read_only':True},
            'authors':{'write_only': True},
            'authors_list':{'read_only':True},
        }


1.3路由分法

1.总路由
from django.contrib import admin
from django.urls import path,include


urlpatterns = [
    path('admin/', admin.site.urls),
    #路由分法
    path('api/', include('api.urls')),

]

2.分路由
from django.urls import path
from api import views

urlpatterns = [
    path('books/', views.BookAPIView.as_view()),
]

1.4admin配置

from django.contrib import admin

# Register your models here.

from api import models
#为了让admin页面可以显示这几张表
admin.site.register(models.Book)
admin.site.register(models.Publish)
admin.site.register(models.Author)
admin.site.register(models.AuthorDetail)

1.5settings配置

1.6启动测试

发现路由分发起了作用

1.7加上之后的呢

1.8views视图

class BookAPIView(APIView):
    def get(self,request,*args,**kwargs):
        #获取图书全部列表
        book_list=models.Book.objects.all().filter(is_delete=False)
        #获取数据
        book_list_ser=ser.BookModelSerialzer(instance=book_list,many=True)
        print(book_list_ser.data)
        return Response(data=book_list_ser.data)

1.8.1但是还有一些问题,查询时候外键显示的有问题

#序列化类BookModelSerialzer  加一些东西
class BookModelSerialzer(serializers.ModelSerializer):
    #解决多表联合显示问题
    #第一种方案 序列化可以 反序列化有问题
    # publish=serializers.CharField(source='publish.name')

    #第二种方案models中写方法 加上一个@property 这里调用

    class Meta:
        model = models.Book
        # fields = '__all__'
        # depth = 1

        fields = ('title','price','authors','publish','publish_name','authors_list')
        #我们可以使用extra_kwargs参数为ModelSerializer添加或修改原有的选项参数
        extra_kwargs={
            'publish':{'write_only': True},
            'publish_name':{'read_only':True},
            'authors':{'write_only': True},
            'authors_list':{'read_only':True},
        }

        
 ###########################models类##################
class Book(BaseModel):
    id = models.AutoField(primary_key=True)
    #verbose_name:中文显示  help_text:输入框的一个小注释
    title = models.CharField(max_length=32, verbose_name='书名',help_text='这里填书名')
    price = models.DecimalField(max_digits=5, decimal_places=2, verbose_name='价格')

    # 关联字段写在多的一方,to_field默认不用写 关联表的字段
    # db_constraint=False:逻辑上和Publish有关联,增删不受外键影响,orm查询不影响,本质就是保留跨表查询的便利(双下划线跨表查询```),但是不用约束字段了,一般公司都用false,这样就省的报错,因为没有了约束(Field字段对象,既约束,又建立表与表之间的关系)

    publish = models.ForeignKey(to='Publish', on_delete=models.CASCADE, db_constraint=False, verbose_name='出版社')

    # 自动:第三张表只有关联字段    手动:可以进行扩展
    # 不能写on_delete 因为是第三张表
    authors = models.ManyToManyField(to='Author', db_constraint=False, verbose_name='作者')

    class Meta:
        # admin中的表名中文显示
        verbose_name_plural = '书籍表'

    def __str__(self):
        return self.title

    #让他前端显示publish.name
    @property
    def publish_name(self):
        return self.publish.name

    #显示作者列表
    def authors_list(self):
        authors_list=self.authors.all()
        # get_xxx_display 获取CharField choices 对应的值
        ll =[{'name':author.name,'gender':author.get_gender_display()} for author in authors_list]
        return ll

1.8.2目前结果如下图

2.post请求插入数据 (单条数据)

#在views视图加入post方法
class BookAPIView(APIView):
    def get(self,request,*args,**kwargs):
        #获取图书全部列表
        book_list=models.Book.objects.all().filter(is_delete=False)
        #获取数据
        book_list_ser=ser.BookModelSerialzer(instance=book_list,many=True)
        print(book_list_ser.data)
        return Response(data=book_list_ser.data)

    def post(self, request, *args, **kwargs):
        # 1.反序列化接受的参数  前端传入的数据,在request.data中,是个字典
        book_ser = ser.BookModelSerialzer(data=request.data)
        print(book_ser)
        # 2.数据校验:如果是True,表示校验通过,直接保存,raise_exception等于True会主动抛出异常
        book_ser.is_valid(raise_exception=True)
        book_ser.save()  # 调用保存,但是有问题,保存不了,一定要在序列化类中重写某个方法
        #返回前端
        return Response(data=book_ser.data)

3.post请求插入数据 (多条数据)

#判断request.data是字典还是列表 就可以分辨是单条数据还是多条数据

    def post(self, request, *args, **kwargs):

        #函数来判断一个对象是否是一个已知的类型
        if isinstance(request.data,dict): #如果是一个字典  单条数据

            # 1.反序列化接受的参数  前端传入的数据,在request.data中,是个字典
            book_ser = ser.BookModelSerialzer(data=request.data)
            print(book_ser)
            # 2.数据校验:如果是True,表示校验通过,直接保存,raise_exception等于True会主动抛出异常
            book_ser.is_valid(raise_exception=True)
            book_ser.save()  # 调用保存,但是有问题,保存不了,一定要在序列化类中重写某个方法
            #返回前端增加的数据
            return Response(data=book_ser.data)
        elif isinstance(request.data,list):#如果是一个列表  多条数据
            # 1.反序列化接受的参数  前端传入的数据,在request.data中,是个字典
            #现在book_ser 是listSerializer
            book_ser = ser.BookModelSerialzer(data=request.data,many=True)
            print(book_ser)
            # 2.数据校验:如果是True,表示校验通过,直接保存,raise_exception等于True会主动抛出异常
            book_ser.is_valid(raise_exception=True)
            #调用的是是listSerializer的save方法 所以可以批量增
            book_ser.save()  # 调用保存,但是有问题,保存不了,一定要在序列化类中重写某个方法
            #返回前端增加的数据
            return Response(data=book_ser.data)

4.修改单条数据


5.修改多条数据

序列化类里面
		Meta里面
		# 声明这句 调用save 会走自己设置的方法
         list_serializer_class = MyListSerializer

#重写一个类 继承ListSerializer,重写update方法
class MyListSerializer(serializers.ListSerializer):
    #                        validated_data校验过后的数据
    # def create(self, validated_data):
    #     print(validated_data)
    #     return super().create(validated_data)

    # instance
    def update(self, instance, validated_data):
        print(instance)
        print(validated_data)
        #保存数据
        #self.child是BookModelSerialzer对象
        return [
            #    修改的是数据对象  key   value  通过for循环得到   enumerate 循环结果为key+value
            self.child.update(instance[i],attrs) for i,attrs in enumerate (validated_data)
        ]
    
 #视图类里
 def put(self,request,*args,**kwargs):
        #修改单个
        if kwargs.get('pk',None):
            book=models.Book.objects.filter(pk=kwargs.get('pk')).first()
            book_ser=ser.BookModelSerialzer(data=request.data)
            book_ser.is_valid(raise_exception=True)
            book_ser.save()
            return Response(data=book_ser.data)
        else:
            #修改多个
            #处理前端传过来的数据[{boo1},{book2}] 列表套子典

            book_list=[]
            modify_data=[]
            #循环传过来的数据
            for item in request.data:
                #pop 删除item里面的id 并把id的值赋值给pk
                pk=item.pop('id')
                book = models.Book.objects.get(pk=pk)
                book_list.append(book)
                modify_data.append(item)
            #instance对象列表  data要修改的数据列表
            # 第一种方案for循环的方式
            for i,si_data in enumerate(modify_data):
                #序列化
                book_ser = ser.BookModelSerialzer(instance=book_list[i],data=si_data)
                book_ser.is_valid(raise_exception=True)
                book_ser.save()
            return Response(data='成功')
            # 第二种方案
            book_ser=ser.BookModelSerialzer(instance=book_list,data=modify_data,many=True)
            book_ser.is_valid(raise_exception=True)
            book_ser.save() #调用自己的update方法
            return Response(data=book_ser.data)

#总结:就是把传入的数据变成循环出来
posted @ 2022-01-19 10:20  迪迦张  阅读(61)  评论(0编辑  收藏  举报