django之CSRF接口(一)

2022/4/6 6:20:49

本文主要是介绍django之CSRF接口(一),对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

序列化

后端的数据到前端(get请求),以json的格式

准备工作,在models中新建表格,并且自己添加2行数据

from django.db import models


class Book(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    price = models.DecimalField(max_digits=8, decimal_places=2)
    author = models.CharField(max_length=32, null=True)

 

 

 

第一, 自己写一个序列化器serializer,里面写需要序列化的字段(在项目下新建serializer.py文件)

from rest_framework import serializers
class BookSerializer(serializers.Serializer):
    name = serializers.CharField(max_length=32)
    price = serializers.CharField()
    author = serializers.CharField()

第二,在views中,重新重写get方法,继承的是APIView

from rest_framework.views import APIView
from .models import Book
from rest_framework.response import Response
from .serializer import BookSerializer


class BookView(APIView):
    def get(self, request):
        book_list = Book.objects.all()
        res = BookSerializer(instance=book_list, many=True)
        # print(res)
        return Response(res.data)

第三,开放后台端口,在url中添加路由,路由book是接口路径

from django.contrib import admin
from django.urls import path
from app01 import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('book/', views.BookView.as_view()),
]

启动项目,访问接口地址,http://127.0.0.1:8000/book/

显示接口数据,用postman访问,结果为

 

 

 定制字段的2中方法,经过流程参照下图

 

 

 

第一种,在自定义的序列化器中,增加字段,且需要配合一个同名方法使用

from rest_framework import serializers
class BookSerializer(serializers.Serializer):
    name = serializers.CharField(max_length=32)
    price = serializers.CharField()
    author = serializers.CharField()
    # 定制价格字段,必须在views中,写入get_price_info
    price_info = serializers.SerializerMethodField()
    def get_price_info(self,obj):
        return '价格是' + str(obj.price)

 

 

 第二种,在序列化类里写新方法的同时,在models中写方法,这里的字段就是models的方法名,price_info是什么,就返回什么

serializer中新增

from rest_framework import serializers
class BookSerializer(serializers.Serializer):
    name = serializers.CharField(max_length=32)
    price = serializers.CharField()
    author = serializers.CharField()
   # 下面是新增的字段
    price_info = serializers.CharField()

models中新增get_方法

from django.db import models


class Book(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    price = models.DecimalField(max_digits=8, decimal_places=2)
    author = models.CharField(max_length=32, null=True)

    def price_info(self):
        return '价格是' + str(self.price)

在系列化类中,可以增加各种选项参数,最常用,且需要记住的是

CharField  # 输出的是字符串
  IntegerField  # 输出的是整形
  FloatField  #  输出的是浮点型
  DecimalField #  输出的是浮点型,可以制定小数的位数
DateTimeField # 输出的是时间

内部参数如下

| 字段                    | 字段构造方式                                                 |
| ----------------------- | ------------------------------------------------------------ |
| **BooleanField**        | BooleanField()                                               |
| **NullBooleanField**    | NullBooleanField()                                           |
| **CharField**           | CharField(max_length=None, min_length=None, allow_blank=False, trim_whitespace=True) |
| **EmailField**          | EmailField(max_length=None, min_length=None, allow_blank=False) |
| **RegexField**          | RegexField(regex, max_length=None, min_length=None, allow_blank=False) |
| **SlugField**           | SlugField(max*length=50, min_length=None, allow_blank=False) 正则字段,验证正则模式 [a-zA-Z0-9*-]+ |
| **URLField**            | URLField(max_length=200, min_length=None, allow_blank=False) |
| **UUIDField**           | UUIDField(format=’hex_verbose’) format: 1) `'hex_verbose'` 如`"5ce0e9a5-5ffa-654b-cee0-1238041fb31a"` 2) `'hex'` 如 `"5ce0e9a55ffa654bcee01238041fb31a"` 3)`'int'` - 如: `"123456789012312313134124512351145145114"` 4)`'urn'` 如: `"urn:uuid:5ce0e9a5-5ffa-654b-cee0-1238041fb31a"` |
| **IPAddressField**      | IPAddressField(protocol=’both’, unpack_ipv4=False, **options) |
| **IntegerField**        | IntegerField(max_value=None, min_value=None)                 |
| **FloatField**          | FloatField(max_value=None, min_value=None)                   |
| **DecimalField**        | DecimalField(max_digits, decimal_places, coerce_to_string=None, max_value=None, min_value=None) max_digits: 最多位数 decimal_palces: 小数点位置 |
| **DateTimeField**       | DateTimeField(format=api_settings.DATETIME_FORMAT, input_formats=None) |
| **DateField**           | DateField(format=api_settings.DATE_FORMAT, input_formats=None) |
| **TimeField**           | TimeField(format=api_settings.TIME_FORMAT, input_formats=None) |
| **DurationField**       | DurationField()                                              |
| **ChoiceField**         | ChoiceField(choices) choices与Django的用法相同               |
| **MultipleChoiceField** | MultipleChoiceField(choices)                                 |
| **FileField**           | FileField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL) |
| **ImageField**          | ImageField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL) |
| **ListField**           | ListField(child=, min_length=None, max_length=None)          |
| **DictField**           | DictField(child=)                                            |

选项参数和通用参数(重要)

**选项参数:**

| 参数名称            | 作用                          |
| ------------------- | ----------------------------- |
| **max_length**      | 最大长度(CharField)         |
| **min_lenght**      | 最小长度(CharField)         |
| **allow_blank**     | 是否允许为空(CharField)     |
| **trim_whitespace** | 是否截断空白字符(CharField) |
| **max_value**       | 最小值 (IntegerField)       |
| **min_value**       | 最大值(IntegerField)        |
**通用参数**:

| 参数名称           | 说明                                          |
| ------------------ | --------------------------------------------- |
| **read_only**      | 表明该字段仅用于序列化输出,默认False         |
| **write_only**     | 表明该字段仅用于反序列化输入,默认False       |
| **required**       | 表明该字段在反序列化时必须输入,默认True      |
| **default**        | 反序列化时使用的默认值                        |
| **allow_null**     | 表明该字段是否允许传入None,默认False         |
| **validators**     | 该字段使用的验证器(不太用)                    |
| **error_messages** | 包含错误编号与错误信息的字典                  |
| **label**          | 用于HTML展示API页面时,显示的字段名称         |
| **help_text**      | 用于HTML展示API页面时,显示的字段帮助提示信息 |

 

反序列化(增删改查)

反序列化 之 新增数据

补充is_valid方法

首先我们看看一般验证过程:
1.方法函数is_valid()的作用检查seld.errors是否都正确,例如长度,空值,类型等
2.分析errors.里面判断_errors是都为空,如果为空返回self.full_clean(),否则返回self._errors
3.跳到full_clean(),该函数里面设置_errors和cleaned_data这两个字典,分别是存放存错误字段和正确字段的。
4.在full_clean的最后有是[self._clean_fields()],表示校验字段,(5,6,7是关于_errors和cleaned_data的左右)
5._clean_fields函数开始循环校验每个字段,而真正校验字段的是field.clean(value)
6.在_clean_fields中可以看到,会将字段按结果添加到_errors和cleaned_data这两个字典中
7.结尾部分还设置了钩子,找clean_XX形式的,并且会执行。执行错误信息也会添加到_errors中
至此校验完成~

反序列化,需要用到post请求,来保证数据的安全,后端接收到之后入库

首先,在views的BookView中中新增post方法

    def post(self, request):
        # 首先要把前端传过来的json数据,先接收,再校验,再进行序列化
        ser = BookSerializer(data=request.data)  # 得到的是对象
        print(ser)
        if ser.is_valid():
            ser.save()
            # 但是这里是我们自己新增的save方法,但是不知道要save到哪张表
            # 又因为save的本质,是create方法,所以我们要在序列化类中,重写create方法
            return Response(ser.data)
        return Response({'code': 100, 'msg': '保存成功'})

第二,在serialiser中,重写create方法

class BookSerializer(serializers.Serializer):
    name = serializers.CharField(max_length=32)
    price = serializers.CharField()
    author = serializers.CharField()
    # 定制价格字段,必须在views中,写入get_price_info
    # price_info = serializers.SerializerMethodField()
    # def get_price_info(self,obj):
    #     return '价格是' + str(obj.price)
    price_info = serializers.CharField(read_only=True) # 这里的参数表示只读,不能新增

    def create(self, validated_data):
        #  指定这里返回的是book表
        book = Book.objects.create(**validated_data)
        return book

此时,从postman中以post新增数据

 

反序列化 之修改字段中的数据

修改,查询单个,删除一个,需要向不同的地址来发送请求,最好重写一个视图类

首先,需要修改路由

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

第二,需要重写update方法

    def update(self, instance, validated_data):
        # validated_data校验过后的数据,instance 是要修改的对象
        instance.name = validated_data.get('name')
        instance.price = validated_data.get('price')
        instance.author = validated_data.get('author')
        instance.save()  # 这里是模型对象自带的save方法,保存到数据库中
        return instance  #

第三,在views中,重写视图类,新增put请求

class BookDetailView(APIView):
    def get(self, request, pk):
        pass

    def delete(self, request, pk):
        pass

    def put(self, request, pk):
        # 修改什么数据
        book = Book.objects.filter(pk=pk).first()
        # 既有instance,又有data,表示修改
        ser = BookSerializer(instance=book, data=request.data)
        if ser.is_valid():
            ser.save()  # 调用内部方法的save
            return Response(ser.data)  # 修改成功返回的数据
        return Response({'mag':'修改错了', 'err': ser.errors})

 

反序列化 之修改字段中的数据中的单个值

需要在update中来进行判断,null=None,序列化类中,增加require参数=True,表示非必填

 

反序列化 之 查询单条数据

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

反序列化 之 删除单条数据

    def delete(self, request, pk):
        res = Book.objects.filter(pk=pk).delete()
        print(res)  # 注意,这里res返回的是一个元祖,前面1个数值表示影响的行数,(1, {'app01.Book': 1})
        if res[0] == 0:
            return Response({'msg': '数据不存在'})
        return Response({'msg': '删除成功'})

 

反序列化 之 局部钩子校验

校验,就是max_lenth,min_lenth等,但是我觉得不够,所以可以自定义校验钩子,写在自定义的序列化类中写,之前需要先导入异常模块

from rest_framework.exceptions import ValidationError


    def validate_name(self, attrs):  # 这里的name,需要和序列化类中的字段名相对应
        # attrs就是前端传过来的数据,然后再这里进行校验
        if attrs.startswith('sb'):  # 名字不能以sb开头
            raise ValidationError('名字不能用sb开头')  # 导入模块之后,抛出异常
        else:
            return attrs

反序列化 之 全局钩子校验

执行顺序:先走字段自己规则,再走局部钩子,再走全局钩子

    def validate(self, attrs):
        if attrs.get('name') == attrs.get('author'):
            raise ValidationError('书名不能等于作者名')
        else:
            return attrs

继承ModelSerializer和添加额外的参数

 查询所有,查询单挑,删除,都与上面相同

但是 新增 与 修改 有一点点差别,并且自定义字段的话,需要在fields中注册

自定义字段

class BookSerializer2(serializers.ModelSerializer):
    class Meta:
        model = Book  # 表示跟哪个表有关系
        # fields = '__all__'  # 因为是在修改源码,所以变量的单词千万不能拼错
        # 如果要自定义字段,也要在这里进行注册
        fields = ['name', 'price', 'author', 'price_info']  # 列表中的字段,会在前端显示
    price_info = serializers.SerializerMethodField()
    def get_price_info(self, obj):
        return '价格是'+ str(obj.price)

 

限制条件

class BookSerializer2(serializers.ModelSerializer):
    class Meta:
        model = Book  # 表示跟哪个表有关系
        # fields = '__all__'  # 因为是在修改源码,所以变量的单词千万不能拼错
        # 如果要自定义字段,也要在这里进行注册
        fields = ['name', 'price', 'author', 'price_info']  # 列表中的字段,会在前端显示

        extra_kwargs = {
            'name': {'write_only': True, 'max_length': 8, 'min_length': 3} # 相当于和之前括号里面加的限制条件一样
        }
    price_info = serializers.SerializerMethodField()

    def get_price_info(self, obj):
        return '价格是' + str(obj.price)

 



这篇关于django之CSRF接口(一)的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程