django_restfreamwork 3 视图组件

Posted on 2020-08-21 19:03  王石头py  阅读(154)  评论(0)    收藏  举报

DRF【视图组件】

通用配置

总路由

from django.urls import path, include
import xadmin
xadmin.autodiscover()
# version模块自动注册需要版本控制的 Model
from xadmin.plugins import xversion
xversion.register_models()

urlpatterns = [
    # path('admin/', admin.site.urls),
    path(r'xadmin/', xadmin.site.urls),
    path('books/', include("SerDemo.urls")),
]

模型

from django.db import models

__all__ = ["Book", "Publisher", "Author"]

class Book(models.Model):
    title = models.CharField(max_length=32, verbose_name="图书名称")
    CHOICES = ((1, "Python"), (2, "Go"), (3, "Linux"))
    category = models.IntegerField(choices=CHOICES, verbose_name="图书的类别")
    pub_time = models.DateField(verbose_name="图书的出版日期")

    publisher = models.ForeignKey(to="Publisher", on_delete=None)
    author = models.ManyToManyField(to="Author")

    def __str__(self):
        return self.title

    class Meta:
        db_table = "book"
        verbose_name_plural = "图书表"

class Publisher(models.Model):
    title = models.CharField(max_length=32, verbose_name="出版社的名称")

    def __str__(self):
        return self.title

    class Meta:
        db_table = "publisher"
        verbose_name_plural = "出版社表"

class Author(models.Model):
    name = models.CharField(max_length=32, verbose_name="作者的姓名")

    def __str__(self):
        return self.name

    class Meta:
        db_table = "author"
        verbose_name_plural = "作者表"

多个get/post/..请求多个函数的实例

5个方法结构图

子路由

只写一个类 BookModelViewSet

请求 list 接口的 get 请求,找这个类 BookModelViewSet list 函数

请求 retrieve/<int:pk> 接口的 get 请求 找这个类 BookModelViewSet retrieve 函数

from django.urls import path, include
from .views import BookModelViewSet

urlpatterns = [
    path('list', BookModelViewSet.as_view({"get": "list", "post": "create"})),
  	# <int:pk> 必须起名为pk,如果是id就报错
    path('retrieve/<int:pk>', BookModelViewSet.as_view({"get": "retrieve", "put": "update", "delete": "destroy"})),
]

继承【ModelViewSet】的视图

继承 ModelViewSet

from .serializers import BookSerializer
from .models import Book
from rest_framework.viewsets import ModelViewSet
class BookModelViewSet(ModelViewSet):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

序列化器

没有改变

class BookSerializer(serializers.ModelSerializer):
    """继承ModelSerializer,序列化器会与models进行结合"""

    class Meta:
        """先对序列化器的model进行配置"""
        model = Book
        fields = "__all__"  # 返回__all__所有字段,或者指定字段["id", "title", "pub_time"]
        # depth = 1       #代表外键嵌套层数为1层,有可能外键关联的表还会外键关联第三张表,这代表停到第一层就停止
        extra_kwargs = {
                    "category": {"write_only": True},   # category 字段不写的话,会返回出去,这个字段不想通过接口提供出去
                    "publisher": {"write_only": True},  # 就写在这里,这个字段作为反序列化post请求过来修改字段用
                    "author": {"write_only": True}
                }

    ############ SerializerMethodField 取出关联表想要的字段,不想要的可以不要 ,下面的变量名会带着值变成返回给前端 ##########
    category_display = serializers.SerializerMethodField(read_only=True)
    # 如果拿出想外键对应表中的字段,不是外键id,下面需要继续定义 def get_<publisher/字段名> 函数,返回想要关联表(外键/manytomany)的字段
    publisher_info = serializers.SerializerMethodField(read_only=True)
    # manytomany字段对应表中的值,下面需要继续定义 def get_<authors/字段名> 函数
    authors = serializers.SerializerMethodField(read_only=True)

    def get_category_display(self,obj):
        return obj.get_category_display()   # orm方法 get_字段_display ,获取chiose中文 ((1,张三),(2,李四))

    def get_publisher_info(self, obj):
        """
            函数以 get_字段命名
            obj是序列化的每个book对象,因为Class meta 中定义了model=book
        """
        publisher_obj = obj.publisher  # 根据publisher外键取 Publisher 表里的值
        return {
            "id": publisher_obj.id,
            "title": publisher_obj.title
        }

    def get_authors(self, obj):
        """
            函数以 get_字段命名
            obj是序列化的每个book对象,因为Class meta 中定义了model=book
        """
        authors_query_set = obj.author.all()
        return [{"id": author_obj.id, "name": author_obj.name} for author_obj in authors_query_set]

DRF【路由组件】

解决路由太多的问题

如果总路由还是 'books' 进行路由分发

那么子路由 使用 DefaultRouter 模块

传入视图类

from .views import BookModelViewSet
from rest_framework.routers import DefaultRouter
router = DefaultRouter()
router.register(r"", BookModelViewSet)

urlpatterns = [
]

urlpatterns += router.urls

视图和序列化器不变,那么请求url就改变了

比如查看所有数据 books/ 查看单条数据 books/1 或者books/xx

缺点

如果自动生成路由的话,但是业务还没有这么多需求,就会暴露很多接口,会有风险
只有业务匹配度很高才能这么用