• Django restframe 视图函数以及ModelSerializer的使用


    建立model数据库

    from django.db import models
    
    __all__ = ['Book', 'Publisher', 'Author']
    
    
    # Create your models here.
    class Book(models.Model):
        title = models.CharField(max_length=32)
        CHOICES = ((1, 'python'), (2, 'linux'), (3, 'go'))
        category = models.IntegerField(choices=CHOICES, default=1, verbose_name='分类')
        pub_time = models.DateField(verbose_name='出版日期')
        publisher = models.ForeignKey(to='Publisher', verbose_name='出版社')
        authors = models.ManyToManyField(to='Author', verbose_name='作者')
    
        class Meta:
            db_table = 'book'
            verbose_name = '书籍表'
            verbose_name_plural = verbose_name
    
        def __str__(self):
            return self.title
    
    
    class Publisher(models.Model):
        name = models.CharField(max_length=32, verbose_name='出版社')
        address = models.CharField(max_length=32, verbose_name='地址')
    
        class Meta:
            db_table = 'publisher'
            verbose_name = '出版社表表'
            verbose_name_plural = verbose_name
    
        def __str__(self):
            return self.name
    
    
    class Author(models.Model):
        name = models.CharField(max_length=32, verbose_name='作者')
        country = models.CharField(max_length=32, verbose_name='国家')
    
        class Meta:
            db_table = 'author'
            verbose_name = '作者表'
            verbose_name_plural = verbose_name
    
        def __str__(self):
            return self.name
    

    数据库部分一共三张表,书籍表以及作则和出版社表

    admin注册

    from django.contrib import admin
    from SerDemo import models
    # Register your models here.
    for table in models.__all__:
        admin.site.register(getattr(models,table))
    

    这里用到了小技巧,利用导入的models.__all__循环批量注册model模型

    序列器的实现

    在项目下新建serializers,py文件

    from rest_framework import serializers
    from SerDemo.models import Book, Author, Publisher
    
    # 自定义检验函数在字段参数validators中作为参数添加
    def my_validate(value):
        if "敏感词汇" in value.lower():
            raise serializers.ValidationError("输入的信息含有敏感词汇")
        return value
    
    ### 创建django序列化器类,继承serializers.ModelSerializer字段可自动关联
    class BookSerializer(serializers.ModelSerializer):
        ## 需要重写的字段,SerializerMethodField 会去找get_字段名的函数并执行获取返回值作为字段值
        category_read = serializers.SerializerMethodField(read_only=True,validators=[my_validate,])
        publisher_read = serializers.SerializerMethodField(read_only=True)
        authors_read = serializers.SerializerMethodField(read_only=True)
    
        # category_read的钩子函数,返回要显示的值,注意obj是每个要显示到前端的数据对象
        def get_category_read(self,obj):
            return obj.get_category_display()
    
        # publisher_read的钩子函数,返回要显示的值
        def get_publisher_read(self,obj):
            return {'id':obj.publisher_id,'title':obj.publisher.name}
    
        def get_authors_read(self,obj):
            ret = [{'id':i.id,'name':i.name} for i in obj.authors.all()]
            return ret
        
        ## 全局校验钩子函数
        def validate(self, attrs):
            # attrs 包含所有字段的数据
            if 'se' in attrs['title']:
                #如果敏感词汇在title字段中则抛出错误
                raise serializers.ValidationError('含有敏感词汇')
            # 否则返回原信息
            return attrs
            
        # 局部校验钩子函数validate_+字段名
        def validate_title(self, data):
            if 'se' in data:
                raise serializers.ValidationError('含有敏感词汇')
            return data
        
        # 序列化器的元信息
        class Meta:
            # 绑定的数据表model
            model=Book
            #要展示的表的字段
            fields = '__all__'
            # depth = 1
            # depth 让你所有的外键关系变成read_only=True,不建议使用
            # 额外要添加的字段的属性参数
            extra_kwargs = {
                'category':{'write_only':True},
                'publisher': {'write_only': True},
                'authors':{'write_only':True},
            }
    
    

    路由以及视图函数部分

    from django.conf.urls import url
    from SerDemo.views import BooklistView,EditBookView
    urlpatterns = [
        # 展示书籍信息路由
        url(r'^booklist/',BooklistView.as_view()),
        #编辑书籍路由,接受id参数
        url(r'^editbook/(?P<id>d+)/',EditBookView.as_view())
    ]
    

    视图部分

    展示所有书籍数据和添加数据视图,

    class BooklistView(ListCreateModelMixin):
        #get 请求发送所有数据给前端
        def get(self, request):
            # 获取数据库中所有数据对象
            query_set = Book.objects.all()
            # 将queryset对象传给序列化器实例化,many=True告诉序列化器这是多个对象
            ser_obj = BookSerializer(query_set, many=True)
            # 所有要显示的数据都在ser_obj.data中用restframe的Response返回
           return Response(ser_obj.data)
    
        # post请求为添加数据
        def post(self, request):
            # 序列化前端传过来的数据(request.data)
            ser_obj = BookSerializer(data=request.data)
            # 校验各字段数据是否符合要求
            if ser_obj.is_valid():
                ser_obj.save()
                return Response(ser_obj.data)
            else:
                return Response(ser_obj.errors)
               
    

    编辑数据和删除书籍部分

    class EditBookView(UpdateDestroyModelMixin):
        # 展示当前要编辑的数据对象
        def get(self, request, id):
        #根据url中的id参数获取要编辑数据对象
            book_obj = Book.objects.filter(id=id).first()
            if book_obj:
                # 返回给前端页面
                ser_obj = BookSerializer(book_obj)
                return Response(ser_obj.data)
            return Response('没有')
    
    
        #put请求对应修改数据
        def put(self, request, id):
            #根据url中的id参数获取要编辑数据对象
            book_obj = Book.objects.filter(id=id).first()
            if book_obj:
                #将前端提交的数据和要修改的对象传给序列化器partial=True允许只修改部分字段数据
                ser_obj = BookSerializer(data=request.data, instance=book_obj, partial=True)
                if ser_obj.is_valid():
                    ser_obj.save()
                    return Response(ser_obj.data)
                else:
                    return Response(ser_obj.errors)
            
        def delete(self,request,id):
            book_obj = Book.objects.filter(id=id).first()
            if book_obj:
                book_obj.delete()
                return Response('')
            return Response('没有次对象')
    

    模仿djngo restframe源码封装各个方法

    from django.shortcuts import render, HttpResponse, redirect
    from django.http import JsonResponse
    import json
    from SerDemo.models import Author, Publisher, Book
    from django import views
    from rest_framework import serializers
    from rest_framework.views import APIView
    from rest_framework.response import Response
    from SerDemo.serializers import BookSerializer
    
    # 把每个方法抽离出来
    
    class GenericAPIView(APIView):
        query_set = None
        serializer_class = None
        def _get_queryset(self):
            return self.query_set
        def _get_serializer(self,*args,**kwargs):
            return self.serializer_class(*args,**kwargs)
    
    class ListModelMixin:
       def list(self):
           query_set = self._get_queryset().all()
    
           ser_obj = self._get_serializer(query_set, many=True)
           return Response(ser_obj.data)
    
    class CreateModelMixin:
        def create(self,request):
            ser_obj = self._get_serializer(data=request.data)
            if ser_obj.is_valid():
                ser_obj.save()
                return Response(ser_obj.data)
            else:
                return Response(ser_obj.errors)
    
    class RetrieveModelMixin:
        def retrieve(self,id):
            book_obj = self._get_queryset().filter(id=id).first()
            if book_obj:
                ser_obj = self._get_serializer(book_obj)
                return Response(ser_obj.data)
            return Response('没有')
    
    class UpdateModelMixin:
        def update(self,request,id):
            book_obj = self._get_queryset().filter(id=id).first()
            if book_obj:
                ser_obj = self._get_serializer(data=request.data, instance=book_obj, partial=True)
                if ser_obj.is_valid():
                    ser_obj.save()
                    return Response(ser_obj.data)
                else:
                    return Response(ser_obj.errors)
    
    class DestroyModelMixin:
        def destroy(self,id):
            book_obj = self._get_queryset().filter(id=id).first()
            if book_obj:
                book_obj.delete()
                return Response('')
            return Response('没有次对象')
    
    class ListCreateModelMixin(GenericAPIView,ListModelMixin, CreateModelMixin):
        pass
    
    class UpdateDestroyModelMixin(GenericAPIView,DestroyModelMixin,UpdateModelMixin,RetrieveModelMixin):
        pass
    
    class BooklistView(ListCreateModelMixin):
        query_set = Book.objects.all()
        serializer_class = BookSerializer
        def get(self, request):
            # query_set = Book.objects.all()
            # ser_obj = BookSerializer(query_set, many=True)
            # return Response(ser_obj.data)
            return self.list()
    
        def post(self, request):
            # ser_obj = BookSerializer(data=request.data)
            # if ser_obj.is_valid():
            #     ser_obj.save()
            #     return Response(ser_obj.data)
            # else:
            #     return Response(ser_obj.errors)
            return self.create(request)
    
    
    class EditBookView(UpdateDestroyModelMixin):
        query_set = Book.objects.all()
        serializer_class = BookSerializer
        def get(self, request, id):
            # book_obj = Book.objects.filter(id=id).first()
            # if book_obj:
            #     ser_obj = BookSerializer(book_obj)
            #     return Response(ser_obj.data)
            # return Response('没有')
            return self.retrieve(id)
    
    
        def put(self, request, id):
            # book_obj = Book.objects.filter(id=id).first()
            # if book_obj:
            #     ser_obj = BookSerializer(data=request.data, instance=book_obj, partial=True)
            #     if ser_obj.is_valid():
            #         ser_obj.save()
            #         return Response(ser_obj.data)
            #     else:
            #         return Response(ser_obj.errors)
            return self.update(request,id)
    
        def delete(self,request,id):
            # book_obj = Book.objects.filter(id=id).first()
            # if book_obj:
            #     book_obj.delete()
            #     return Response('')
            # return Response('没有次对象')
            return self.destroy(id)
    
    
    
  • 相关阅读:
    Nginx.conf 配置文件详细说明
    CentOs中iptables配置允许mysql远程访问
    CentOS 6.4下编译安装MySQL 5.6.14
    CentOS6.4下Mysql数据库的安装与配置
    让nginx支持.htaccess文件实现伪静态的方法!
    MySQL导入.sql文件及常用命令
    PHP里10个鲜为人知但却非常有用的函数
    Nginx配置文件详细说明
    linux 开机启动nginx
    Redhat系列使用ISO或者光盘制作yum本地安装源
  • 原文地址:https://www.cnblogs.com/Kingfan1993/p/10106052.html
Copyright © 2020-2023  润新知