Django rest_frameword 之项目流程

Posted mofujin

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Django rest_frameword 之项目流程相关的知识,希望对你有一定的参考价值。

后端开发软件目录规范

 技术图片

 

一.Model 

技术图片
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)

    # 在建基表的时候要设置 abs 来声明基表,作为基表的model 不能再数据库中行成对应的表

    class Meta:
        abstract = True


class Book(BaseModel):
    name = models.CharField(max_length=32)
    price = models.DecimalField(max_digits=8, decimal_places=2)
    img = models.ImageField(upload_to=img, default=img/default.jpg/)
    # 外键字段的建表规则健在查询频率少的那张表 效率的问题
    # 多对对外键健在那张表都可以
    authors = models.ManyToManyField(to=Author,
                                     db_constraint=False,
                                     related_name=books)

    publisher = models.ForeignKey(
        to=Publish,
        related_name=books,  # 反向查字典的关键字publish_obj.books就能访问改出版社的所有书籍

        on_delete=models.DO_NOTHING,
    db_constraint=False)

    class Meta:
        db_table = book
        verbose_name = 书籍表
        verbose_name_plural = verbose_name

    @property
    def author_list(self):
        # 查表 作者有多个值的
        return self.authors.values(name, age,detail__addr,detail__phone).all()

    @property
    def publish_name(self):
        # 正向按字段
        return self.publisher.name


    def __str__(self):
        return "<%s>" % self.name


class Author(BaseModel):
    name = models.CharField(max_length=32)
    age = models.IntegerField()

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

    def __str__(self):
        return "%s" % self.name


class Publish(BaseModel):
    name = models.CharField(max_length=32)
    addr = models.CharField(max_length=32)

    class Meta:
        db_table = publish
        verbose_name = 出版社表
        verbose_name_plural = verbose_name

    def __str__(self):
        return "%s" % self.name


class AuthorDetail(BaseModel):
    addr = models.CharField(max_length=32)
    phone = models.CharField(max_length=11, null=True)

    # 外键字段一对多还是建立多方
    # 一对一就健在查询评率低的一方
    # 一对一的cascade是同步的进行同删同减
    author_detail = models.OneToOneField(to=Author,
                                         db_constraint=False,
                                         related_name=detail,
                                         on_delete=models.CASCADE)

    class Meta:
        db_table = author_detail
        verbose_name = 详情表
        verbose_name_plural = verbose_name

    def __str__(self):
        return "%s" % self.author_detail.name
View Code

 api 或者项目名下的__init__

import pymysql
pymysql.install_as_MySQLdb()

 

二.settings

数据库和全局文件的配置 图片的暴露接口

技术图片
"""
Django settings for day71_djproj project.

Generated by ‘django-admin startproject‘ using Django 1.11.11.

For more information on this file, see
https://docs.djangoproject.com/en/1.11/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/1.11/ref/settings/
"""

import os

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = ^zqxsy^v6z)!9klipb^^3@=txceu7^b4!-rsp#8r55&_u^p11h

# SECURITY WARNING: don‘t run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = []


# Application definition

INSTALLED_APPS = [
    django.contrib.admin,
    django.contrib.auth,
    django.contrib.contenttypes,
    django.contrib.sessions,
    django.contrib.messages,
    django.contrib.staticfiles,
    api.apps.ApiConfig,

    rest_framework
]

MIDDLEWARE = [
    django.middleware.security.SecurityMiddleware,
    django.contrib.sessions.middleware.SessionMiddleware,
    django.middleware.common.CommonMiddleware,
    django.middleware.csrf.CsrfViewMiddleware,
    django.contrib.auth.middleware.AuthenticationMiddleware,
    django.contrib.messages.middleware.MessageMiddleware,
    django.middleware.clickjacking.XFrameOptionsMiddleware,
]

ROOT_URLCONF = day71_djproj.urls

TEMPLATES = [
    {
        BACKEND: django.template.backends.django.DjangoTemplates,
        DIRS: [os.path.join(BASE_DIR, templates)]
        ,
        APP_DIRS: True,
        OPTIONS: {
            context_processors: [
                django.template.context_processors.debug,
                django.template.context_processors.request,
                django.contrib.auth.context_processors.auth,
                django.contrib.messages.context_processors.messages,
            ],
        },
    },
]

WSGI_APPLICATION = day71_djproj.wsgi.application


# Database
# https://docs.djangoproject.com/en/1.11/ref/settings/#databases

DATABASES = {
    default: {
        ENGINE: django.db.backends.mysql,
        NAME: day71_dj,
        USER: "root",
        PASSWORD: 123,
        HOST:"127.0.0.1",
        PORT: 3306
    }
}


# Password validation
# https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        NAME: django.contrib.auth.password_validation.UserAttributeSimilarityValidator,
    },
    {
        NAME: django.contrib.auth.password_validation.MinimumLengthValidator,
    },
    {
        NAME: django.contrib.auth.password_validation.CommonPasswordValidator,
    },
    {
        NAME: django.contrib.auth.password_validation.NumericPasswordValidator,
    },
]


# Internationalization
# https://docs.djangoproject.com/en/1.11/topics/i18n/

LANGUAGE_CODE = zh-hans

TIME_ZONE = UTC

USE_I18N = True

USE_L10N = True

USE_TZ = False


# Static files (CSS, javascript, Images)
# https://docs.djangoproject.com/en/1.11/howto/static-files/

STATIC_URL = /static/

# 图片
MEDIA_URL = /media/

# 图片的更目录的配置
MEDIA_ROOT = os.path.join(BASE_DIR,/media/)

# 我们还要配置解析的全局配置文件 如果想要配置局部的就要在我们自己的类函数下进行配置 方法


# 配置响应的全局文件


# 配置自定义的异常文件的全局的配置
# 自定义drf配置爱-全局响应配置
REST_FRAMEWORK = {
    # drf提供的渲染类
    DEFAULT_RENDERER_CLASSES: [
        rest_framework.renderers.JSONRenderer,
        rest_framework.renderers.BrowsableAPIRenderer,
    ],

    # drf提供类解析的数据包的格式  请求格式 再取全局进行配置 全局 进而进行局部的的设置
    DEFAULT_PARSER_CLASSES: [
        rest_framework.parsers.JSONParser,
        rest_framework.parsers.FormParser,
        rest_framework.parsers.MultiPartParser,
    ],
    # 全局配置异常模块 自定有异常模块
    EXCEPTION_HANDLER: api.exception.exception_handler,
}
View Code

准备事项配置好后 model 表的迁移命令

(1)

D:day71_djproj>python manage.py makemigrations

(2)python  manage.py migrate

或者快捷键

技术图片

 

 

 

 

三.admin 

注册超级用户 createsuperuser() 

将我们的model 模型表一一注册到我们的admin 中>>> 数据的新增 (方便测试)

from django.contrib import admin
from api import models
# Register your models here.

admin.site.register(models.Author)
admin.site.register(models.Book)
admin.site.register(models.AuthorDetail)
admin.site.register(models.Publish)

四.URL 路由的匹配

(1)总路由 >>>实现陆游的分发 

from django.conf.urls import url, include
from django.contrib import admin
# from django.conf.urls import url
# 资源暴露给外部 必须配置在全局的
# 渲染图片 接口暴露给外部
from day71_djproj import settings
from django.views.static import serve

urlpatterns = [
    url(r^admin/, admin.site.urls),
    url(r^api/, include(api.urls)),


    url(r^media/(?P<path>.*), serve, {document_root:settings.MEDIA_ROOT}),
]

(2)项目api下的路由

from django.conf.urls import url
from api import views
# 路由模块:为标准的viweset接口提供路径的简写方式
from django.conf.urls import include
from rest_framework.routers import SimpleRouter
router = SimpleRouter()
# 路径对象进注册
router.register(v6/books,views.BookModelViewSet)

urlpatterns = [

    url(r^books/$,views.V2Book.as_view()),
    url(r^books/(?P<pk>.*)/$,views.V2Book.as_view()),
    url(r"^v1/books/$",views.BookApIView.as_view()),
    url(r"^v1/books/(?P<pk>.*)/$", views.BookApIView.as_view()),

    url(r"^v2/books/$", views.BookGenericAPIView.as_view()),
    url(r^v2/books/(?P<pk>.*)/$, views.BookGenericAPIView.as_view()),

    url(r"^v3/books/$", views.BookMixinGenericAPIView.as_view()),
    url(r^v3/books/(?P<pk>.*)/$, views.BookMixinGenericAPIView.as_view()),
    url(r"^v4/books/$", views.BookListCreateAPIView.as_view()),
    url(r^v4/books/(?P<pk>.*)/$, views.BookListCreateAPIView.as_view()),
    url(r"^v5/books/$", views.BookGenericViewSet.as_view({"get": "my_get_list"})),
    url(r^v5/books/(?P<pk>.*)/$, views.BookGenericViewSet.as_view({"get": "my_get_obj"})),
    url(r"^vv/books/$", views.MyRequest.as_view()),
    url(r^vv/books/(?P<pk>.*)/$, views.MyRequest.as_view()),


    url(r^v7/books/$,views.BookModelViewSet.as_view({"get":list,post:create})),
    url(r^v7/books/(?P<pk>.*)/$,views.BookModelViewSet.as_view({get:retrieve,put:update,patch:partial_update,delete:destroy})),

    # 在下面进行分发应用匹配
    url(r^,include(router.urls))

]

五.视图函数

技术图片
from django.shortcuts import render

from . import serializers
from api import models
# Create your views here.
from rest_framework.views import APIView
from rest_framework.response import Response

from utils.response import APIResponse


class V2Book(APIView):
    # 单查
    # 群查
    def get(self, request, *args, **kwargs):
        # print(request.query_params,12312)
        pk = kwargs.get(pk)
        if pk:
            try:
                book_obj = models.Book.objects.get(pk=pk, is_delete=False)
                print(book_obj, type(book_obj), 3212)
                book_data = serializers.BookModelSerializer(book_obj).data
                # print(book_data,type(book_data),123)
                return Response({
                    status: 1,
                    msg: ok,
                    results: book_data
                })
            except:
                return Response({
                    "status": 0,
                    img: "数据有误"
                })
        else:
            book_query = models.Book.objects.filter(is_delete=False).all()

            book_data = serializers.BookModelSerializer(book_query, many=True).data

            return Response({
                status: 1,
                msg: ok,
                results: book_data
            })

        # 反序列化的 通过序列化组件
        # user_ser = serializer

    def post(self, request, *args, **kwargs):
        # 单增数据是与model对应的字典   获取的数据的格式和类型的检验
        request_data = request.data
        print(request_data)
        # if not isinstance(request_data,dict) or request_data == {}:
        #     return Response({
        #         ‘status‘: 1,
        #         ‘msg‘: ‘数据有误‘,
        #
        #     })
        # else:
        # 单增
        if isinstance(request_data, dict) and request_data != {}:
            many = False
            book_data = serializers.BookModelSerializer(data=request_data, many=many)  # 进行反序列化的对象赋值
            # 当前视图异常是 立即出发报错异常的进行返回到前端

            book_data.is_valid(raise_exception=True)  # 进行数据的检验
            data_result = book_data.save()
            return Response({
                status: 1,
                msg: ok,
                results: serializers.BookModelSerializer(data_result).data  # 反序列化
            })
        elif isinstance(request_data, list) and request_data != []:  # 是多个值的话 同时新增多个对象
            many = True
            book_data = serializers.BookModelSerializer(data=request_data, many=many)  # 反序列化 再存
            book_data.is_valid(raise_exception=True)  # 进行数据的检验
            # ???
            data_result = book_data.save()
            return Response({
                status: 1,
                msg: ok,
                results: serializers.BookModelSerializer(data_result, many=many).data  # 反序列化
            })

        else:
            return Response({
                status: 0,
                msg: 数据格式有误
            })
        # 获取数据
        # 全增

    def delete(self, request, *args, **kwargs):
        pk = kwargs.get(pk)
        if pk:
            # pk__in 符合下面的要求
            pks = [pk]
        else:
            pks = request.data.get(pks)
        if models.Book.objects.filter(pk__in=pks, is_delete=False).update(is_delete=True):
            # 直接返回
            return Response({
                status: 1,
                msg: 删除成功
            })
        else:
            return Response({
                status: 0,
                msg: 删除未成功

            })

    def put(self, request, *args, **kwargs):
        # 单 整体修改
        # 序列化的是对象

        pk = kwargs.get(pk)

        book_obj = models.Book.objects.filter(pk=pk).first()

        #  反序列化 数据
        request_data = request.data
        # 反序列化的对数据进行修改的三件事 1.数据是改谁的 2.将数据进行data 封装 3.完序列化后的数据的检验
        # 反序列化的是传的对象的 和值
        book_ser = serializers.BookModelSerializer(instance=book_obj, data=request_data, )
        # 反序列化传数据 还需要修改的对象
        # 检验
        book_ser.is_valid(raise_exception=True)
        # 修改入库
        result_obj = book_ser.save()  # 修改入库
        return Response({
            status: 1,
            msg: 修改成功,
            # 返回的 是序列化对象 传入的是save() 返回的对象
            results: serializers.BookModelSerializer(result_obj).data
        })

    # 进行单改和全改的patch()
    # 单体pk = [1,]
    # 多改pk=[1,2,3]

    def patch(self, request, *args, **kwargs):
        pk = kwargs.get("pk")
        request_data = request.data
        # 单改
        if pk and isinstance(request_data, dict):
            pks = [pk, ]
            request_data = [request_data, ]
        # 群改
        elif not pk and isinstance(request_data, list):
            pks = []
            #
            for data in request_data:
                # 将每个数据中的字典进行删除(本质是返回键)
                pk = data.pop(pk, None)
                if pk:
                    pks.append(pk)
                else:
                    return Response({
                        status: 0,
                        msg: 数据有误
                    })
        else:
            return Response({
                "status": 0,
                msg: "数据有误"
            })
        # 将上面的单改和群对象改进行逻辑业务处理
        # 我们需要处理的是pks中 and健值绑定的没有数据的pks 进行删除
        # 将合理的数据进保存
        objs = []
        new_data = []
        for index, pk in enumerate(pks):
            try:
                # 存储合理的数据进行修改
                obj = models.Book.objects.get(pk=pk, is_delete=False)  # BUG
                objs.append(obj)
                # 将对应上的数据保存
                new_data.append(request_data[index])
            except:
                # 继续循环 循环结束继续结束
                continue
        # 统一的逻辑
        book_ser = serializers.BookModelSerializer(instance=objs, data=new_data, partial=True, many=True)
        # 校验
        book_ser.is_valid(raise_exception=True)
        print(book_ser, 123)
        book_obj = book_ser.save()
        print(book_obj, 555)
        # 返回
        return Response({
            status: 1,
            msg: 修改成功,
            # 序列化和反序列化只要有多个必须是many = TRUE
            results: serializers.BookModelSerializer(book_obj, many=True).data
        })


# 重写response() 响应方法
class BookApIView(APIView):
    def get(self, *args, **kwargs):
        book_query = models.Book.objects.filter(is_delete=False).all()
        book_ser = serializers.BookModelSerializer(book_query, many=True)
        # print(book_ser)
        book_data = book_ser.data  # 数据是存放在data 中的
        # print(book_data)
        # 返回数据我们用封装号的
        return APIResponse(results=book_data)


# Genseric 类
from rest_framework.generics import GenericAPIView


class BookGenericAPIView(GenericAPIView):
    # 因为我们继承的是GenericAPIView   >>> 继承APIView
    # queryset = None 和serializer = None 初始值为空时需要我们进行重写的
    queryset = models.Book.objects.filter(is_delete=False)

    serializer_class = serializers.BookModelSerializer

    # 单查 pk get的方法

    lookup_field = pk

    # def get(self, request, *args, **kwargs):
    #     book_query = self.get_object()
    #     print(book_query, 55)
    #     book_ser = self.get_serializer(book_query)
    #     book_data = book_ser.data
    #     return APIResponse(results=book_data)

    # 群查
    def get(self, request, *args, **kwargs):
        book_query = self.get_queryset()
        book_ser = self.get_serializer(book_query,many=True)  # 这里加上many=True
        book_data = book_ser.data
        return APIResponse(results=book_data)


"""


# 1)mixins有五个工具类文件,一共提供了五个工具类,六个工具方法:单查、群查、单增、单删、单整体改、单局部改
# 2)继承工具类可以简化请求函数的实现体,但是必须继承GenericAPIView,需要GenericAPIView类提供的几个类属性和方法(见上方GenericAPIView基类知识点)
# 3)工具类的工具方法返回值都是Response类型对象,如果要格式化数据格式再返回给前台,可以通过 response.data 拿到工具方法返回的Response类型对象的响应数据
"""
# mixins 有五大工具六大方法
from rest_framework.mixins import ListModelMixin,CreateModelMixin,RetrieveModelMixin,UpdateModelMixin


class BookMixinGenericAPIView(ListModelMixin,CreateModelMixin,UpdateModelMixin,RetrieveModelMixin,GenericAPIView):
    # 先获取对象
    queryset = models.Book.objects.filter(is_delete=False)
    # 重写序列化
    serializer_class = serializers.BookModelSerializer

    # get 查询
    def get(self,request,*args, **kwargs):
        # mixins 中的单查 pk
        if pk in kwargs:

            response = self.retrieve(request,*args,**kwargs)
        else:
            # mixins提供的list方法的响应对象是Response,想将该对象格式化为APIResponse
            response = self.list(request, *args, **kwargs)
            # 数据都是封装在response

        return APIResponse(results=response.data)

    # 单增post 多增的操作
    def post(self, request, *args, **kwargs):
        response = self.create(request, *args, **kwargs)
        return APIResponse(results=response.data)

    # =更新put
    # 注意必须在pk = 22 有值的情况 也必须是在url 中拼接pk 才能进行目前的修改
    def put(self,request, *args, **kwargs):
        response = self.update(request, *args, **kwargs)
        return APIResponse(results=response.data)

    # patch修改 也会需要 pk url 中拼接
    def patch(self,request, *args, **kwargs):
        response = self.update(request, *args, **kwargs)
        return APIResponse(results=response.data)


# 工具视图
"""
# 1)工具视图都是GenericAPIView的子类,且不同的子类继承了不听的工具类,重写了请求方法
# 2)工具视图的功能如果直接可以满足需求,只需要继承工具视图,提供queryset与serializer_class即可
"""
# 群查 局部更新

from rest_framework.generics import ListCreateAPIView,UpdateAPIView
class BookListCreateAPIView(ListCreateAPIView, UpdateAPIView):
    queryset = models.Book.objects.filter(is_delete=False)
    serializer_class = serializers.BookModelSerializer


# 视图集..set
"""
(1)优先继承ViewSetMixin 类 再继承一个视图类(GenericViewSet 和APIView)
(2)ViewSetMixin提供重写ad_view() 方法 ,继承视图集的属兔类,-匹配路由调用da_view() 必须出入对饮的映射关系as_view("get":"my_get_list")
"""
from rest_framework.viewsets import GenericViewSet  # 视图集中导入视图类
from rest_framework import mixins  # 工具类


class BookGenericViewSet(mixins.RetrieveModelMixin, mixins.ListModelMixin, GenericViewSet):
    queryset = models.Book.objects.filter(is_delete=False)
    serializer_class = serializers.BookModelSerializer
    # 群查
    def my_get_list(self,request,*args, **kwargs):
        return self.list(request, *args, **kwargs)
    # 单查
    def my_get_obj(self, request,*args, **kwargs):
        return self.retrieve(request, *args, **kwargs)

class MyRequest(APIView):
    def post(self, request, *args, **kwargs):
        request_data = request.data

        # book_ser 序列化数据对象
        book_data = serializers.BookModelSerializer(data=request_data, many=False, context={"request": request})
        # 进行数据的检验
        book_data.is_valid(raise_exception=True)
        result_data = book_data.save()
        return APIResponse(results=result_data)  # 直接封装 create() 的话要进行many = True




# 拥有就打接口:单查/群查/单增/ 单删/单整体改/单局部改
# 补充:一般肯定需要我们重写destroy 方法
"""

class ModelViewSet(mixins.CreateModelMixin,
                   mixins.RetrieveModelMixin,
                   mixins.UpdateModelMixin,
                   mixins.DestroyModelMixin,
                   mixins.ListModelMixin,
                   GenericViewSet):  #  继承这个主要是让他遵循我们自己写的as_view({"get":"list",‘patch‘:"partial_update",‘put‘:"update","post":"create", "destroy":‘destroy‘})
"""
from rest_framework.viewsets import ModelViewSet


class BookModelViewSet(ModelViewSet):
    queryset = models.Book.objects.filter(is_delete=False)
    serializer_class = serializers.BookModelSerializer
    """
    as_view({"get":‘list‘,‘post‘:‘create‘})
    get >>>list 群查 post >>> 新增
    as_view({‘get‘:‘retrieve‘,‘put‘:‘update‘,‘patch‘:‘partial_update‘,‘delete‘:‘destroy‘}
    get >>>retrieve 单查 提供pk在url  put >>> partial = False不能进单个字段的修改 而是整体字段的更新  
    patch >>>> partial_update 默认partial = True, 
    """
    # 一般我们删除的不是真正的数据 而是将他的bOOL 改为1 /获取是Treu
    # 除了删除需要我们自己写  因为 特会将正真的数据进行删除肯定不合理 所以我们自己写优先走我们自己的

    def destroy(self, request, *args, **kwargs):
        instance = self.get_object()  # 单删 实列化对象
        if not instance:  # 改实例对象不存在
            return APIResponse(0, 删除失败)
        instance.is_delete = True
        instance.save()
        return APIResponse(1,删除成功)
View Code

六.serializer文件:对象  序列化 钩子函数

技术图片
from rest_framework.serializers import ModelSerializer,SerializerMethodField
from rest_framework.serializers import ListSerializer
from rest_framework.exceptions import ValidationError
from . import models



# 重写我们update() 方法


# 重点将我们ListSerializer()


class BookListSerializer(ListSerializer):

    def update(self, instance, validated_data):
        print(instance,111)  # [<Book: <东游记9988>>, <Book: <西游记999>>, <Book: <南游记>>]
        print(validated_data,2222)
        # [{‘name‘: ‘东游记88‘, ‘price‘: Decimal(‘66.66‘)}, {‘name‘: ‘西游记999‘,
        # ‘price‘: Decimal(‘77.88‘)}, {‘name‘: ‘南游记‘, ‘price‘: Decimal(‘8.88‘)}]
        # 获取里面的所有数据
        print(self.child,12312312)
        for index, obj in enumerate(instance):
            # 获取对象的索引和下标
            self.child.update(obj,validated_data[index])
        return instance  # 返回对象


class BookModelSerializer(ModelSerializer):
    class Meta:
        model = models.Book
        # 映射
        fields = (name,price, img,author_list, publish_name,publisher,authors)
        extra_kwargs = {
            name:{
                required:True,
                min_length:3,
                error_messages:{

                    required:必填字段,
                    min_length:不能少于3位数字
                }
            },
            publisher:{
                write_only:True,
            },
            authors:{
                write_only: True
            },
            img:{
                read_only:True,

            },
            author_list:{
                read_only:True
            },
            publish_name:{
                read_only:True
            }
        }

        # patch()方法是用save()
        # 方法进行数据的更新 但是没有进行update()方法的封装 需要我们自己 重写update() 方法
        list_serializer_class = BookListSerializer
    # 局部勾子和全局钩子

    def validate_name(self,value):
        # 书名不能有‘si‘字符
        print(self.context,1111)
        if k in value:  # ???
            raise ValidationError(该k书不能出版)
        return value

    # 全局钩子
    def validate(self, attrs):
        publisher = attrs.get(publisher)
        name = attrs.get(name)
        if models.Book.objects.filter(name=name,publisher=publisher):
            raise ValidationError({book:该书已经存在})
        return attrs
View Code

七.Media 媒体文件

技术图片

 

 八. exception自定义用异常文件

from rest_framework.views import exception_handler as drf_exception_handler
from rest_framework.views import Response
from rest_framework import status
def exception_handler(exc, context):
    # drf的exception_handler做基础处理
    response = drf_exception_handler(exc, context)
    # 为空,自定义二次处理
    if response is None:
        print(%s - %s - %s % (context[view], context[request].method, exc))
        return Response({
            detail: 服务器错误
        }, status=status.HTTP_500_INTERNAL_SERVER_ERROR, exception=True)
    return response

九.utils文件 自定义响应的数据格式 以及我们的自定义分页器

技术图片

 

 

# 我们自定义
from rest_framework.response import Response


class APIResponse(Response):
def __init__(self, data_status=1,data_msg=‘ok‘,
results=None,http_status=None, headers=None,exception=False,*kwargs): # 我们需要返回的值
# data的初始信息:
data = {
‘status‘:data_status,
‘msg‘:data_msg,
}
# data的响应数据体
# results 响应可能是False 0等数据 这些数据在我们设计的方法下是不合法的所以要进行过滤
if results is not None:
data[‘results‘] = results
# 将请求后的字典内容进行更新 有则
data.update(kwargs)
super().__init__(data=data,status=http_status,headers=headers,exception=exception)

 

 

待更新........

 

以上是关于Django rest_frameword 之项目流程的主要内容,如果未能解决你的问题,请参考以下文章

Django之真正创建一个django项目

django之创建第二个项目

Web框架之Django_02基本操作(Django项目启动配置数据库连接orm增删改查)

Django系列之第一个项目搭建

Django博客项目之个人站点

django之创建第12个项目-加载图片