day03 序列化器-Serializer与ModelSerializer
今日内容
- 序列化器-Serializer
- 序列化器的序列化
- 序列化器的反序列化
- 模型类序列化器ModelSerializer
- django配置文件详解
1、序列化器-Serializer
# 序列化器的作用
1. 序列化,序列化器会把模型对象转换成字典,经过response以后变成json字符串
2. 反序列化,把客户端发送过来的数据,经过request以后变成字典,序列化器可以把字典转成模型
3. 反序列化,完成数据校验功能
2、序列化器的序列化
2.1 基本使用:写出5个接口
# 针对于某个表模型,总共5个接口
获取所有 get
获取单个 get
删除单个 delete
修改单个 update
新增单个 post
# 以后你写的所有接口(跟数据库相关),都是这个5个或这5个的变形
2.11 models.py
from django.db import models
# 创建表
class Book(models.Model):
title = models.CharField(max_length=32)
price = models.IntegerField()
publish = models.CharField(max_length=32)
2.12 serializer.py
from rest_framework import serializers
from app01.models import Book
# 写序列化类
class BookSerializer(serializers.Serializer):
title = serializers.CharField()
price = serializers.IntegerField()
publish = serializers.CharField()
# 重写create,使它能够支持新增保存(派生)
def create(self, validated_data): # 校验后的数据
book = Book.objects.create(**validated_data)
return book # 返回book
# 重写update,使它能够支持修改(派生)
def update(self, instance, validated_data):
instance.title = validated_data.get('title')
instance.price = validated_data.get('price')
instance.publish = validated_data.get('publish')
instance.save() # 修改后保存
return instance
'''
总结:
使用序列化器类,需要重写新增和修改
'''
2.13 views.py
from django.shortcuts import render
# 查询所有图书的视图类
from rest_framework.views import APIView
from app01.models import Book
from app01.serializer import BookSerializer
from rest_framework.response import Response
class BookView(APIView):
# 查询所有接口
def get(self, request, *args, **kwargs):
# 查询出所有图书
books = Book.objects.all()
# 把qs对象序列化成字典,使用序列化类完成序列化
# instance=None, 是要序列化的对象(可以是单个对象,可以是多个对象(放到列表或者qs对象),一定要写many=True)
# data=empty 反序列化的字典,目前还没用到
ser = BookSerializer(instance=books, many=True) # 传入要序列化的数据
# 返回给前端 ser.data 是个字典
# 如果是浏览器,会有一个好看的页面(注册app),如果是postman,就是json格式
return Response(ser.data)
# 新增接口
def post(self, request, *args, **kwargs):
# 使用序列化类做保存
ser = BookSerializer(data=request.data)
# 数据校验:如果是True,表示校验通过,直接保存
if ser.is_valid():
ser.save() # 调用保存,但是有问题,保存不了,一定要在序列化类中重写某个方法
return Response(ser.data)
else:
return Response(ser.errors)
class BookDetailView(APIView):
# 查询单个接口
def get(self, request, pk):
# 查询单本图书
books = Book.objects.filter(pk=pk).first()
ser = BookSerializer(instance=books) # 序列化类中传入要序列化的数据
return Response(ser.data)
# 删除接口
def delete(self, request, pk):
Book.objects.filter(pk=pk).delete()
return Response()
# 修改接口
def put(self, request, pk):
book = Book.objects.filter(pk=pk).first()
ser = BookSerializer(instance=book, data=request.data)
# 数据校验:如果是True,表示校验通过,直接保存
if ser.is_valid():
ser.save() # 调用保存,但是有问题,保存不了,一定要在序列化类中重写update方法
return Response(ser.data)
else:
return Response(ser.errors)
'''
总结:
因为删除和修改都需要用到主键值,所以写到转换器类中
'''
2.13 urls.py
from app01 import views
urlpatterns = [
path('admin/', admin.site.urls),
path('books/', views.BookView.as_view()),
# 使用序列化转换器
path('books//', views.BookDetailView.as_view()),
]
2.2 常用字段
AutoField(Field)
- int自增列,必须填入参数 primary_key=True
BigAutoField(AutoField)
- bigint自增列,必须填入参数 primary_key=True
注:当model中如果没有自增列,则自动会创建一个列名为id的列
from django.db import models
class UserInfo(models.Model):
# 自动创建一个列名为id的且为自增的整数列
username = models.CharField(max_length=32)
class Group(models.Model):
# 自定义自增列
nid = models.AutoField(primary_key=True)
name = models.CharField(max_length=32)
SmallIntegerField(IntegerField):
- 小整数 -32768 ~ 32767
PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)
- 正小整数 0 ~ 32767
IntegerField(Field)
- 整数列(有符号的) -2147483648 ~ 2147483647
PositiveIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)
- 正整数 0 ~ 2147483647
BigIntegerField(IntegerField):
- 长整型(有符号的) -9223372036854775808 ~ 9223372036854775807
BooleanField(Field)
- 布尔值类型
NullBooleanField(Field):
- 可以为空的布尔值
CharField(Field)
- 字符类型
- 必须提供max_length参数, max_length表示字符长度
TextField(Field)
- 文本类型
EmailField(CharField):
- 字符串类型,Django Admin以及ModelForm中提供验证机制
IPAddressField(Field)
- 字符串类型,Django Admin以及ModelForm中提供验证 IPV4 机制
GenericIPAddressField(Field)
- 字符串类型,Django Admin以及ModelForm中提供验证 Ipv4和Ipv6
- 参数:
protocol,用于指定Ipv4或Ipv6, 'both',"ipv4","ipv6"
unpack_ipv4, 如果指定为True,则输入::ffff:192.0.2.1时候,可解析为192.0.2.1,开启此功能,需要protocol="both"
URLField(CharField)
- 字符串类型,Django Admin以及ModelForm中提供验证 URL
SlugField(CharField)
- 字符串类型,Django Admin以及ModelForm中提供验证支持 字母、数字、下划线、连接符(减号)
CommaSeparatedIntegerField(CharField)
- 字符串类型,格式必须为逗号分割的数字
UUIDField(Field)
- 字符串类型,Django Admin以及ModelForm中提供对UUID格式的验证
FilePathField(Field)
- 字符串,Django Admin以及ModelForm中提供读取文件夹下文件的功能
- 参数:
path, 文件夹路径
match=None, 正则匹配
recursive=False, 递归下面的文件夹
allow_files=True, 允许文件
allow_folders=False, 允许文件夹
FileField(Field)
- 字符串,路径保存在数据库,文件上传到指定目录
- 参数:
upload_to = "" 上传文件的保存路径
storage = None 存储组件,默认django.core.files.storage.FileSystemStorage
ImageField(FileField)
- 字符串,路径保存在数据库,文件上传到指定目录
- 参数:
upload_to = "" 上传文件的保存路径
storage = None 存储组件,默认django.core.files.storage.FileSystemStorage
width_field=None, 上传图片的高度保存的数据库字段名(字符串)
height_field=None 上传图片的宽度保存的数据库字段名(字符串)
DateTimeField(DateField)
- 日期+时间格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]
DateField(DateTimeCheckMixin, Field)
- 日期格式 YYYY-MM-DD
TimeField(DateTimeCheckMixin, Field)
- 时间格式 HH:MM[:ss[.uuuuuu]]
DurationField(Field)
- 长整数,时间间隔,数据库中按照bigint存储,ORM中获取的值为datetime.timedelta类型
FloatField(Field)
- 浮点型
DecimalField(Field)
- 10进制小数
- 参数:
max_digits,小数总长度
decimal_places,小数位长度
BinaryField(Field)
- 二进制类型
2.3 常用字段参数
#参数名称 作用
max_length 最大长度
min_lenght 最小长度
allow_blank 是否允许为空
trim_whitespace 是否截断空白字符
max_value 最小值
min_value 最大值
#通用参数:(针对所有字段)
参数名称 说明
#非常重要
read_only 表明该字段仅用于序列化输出,默认False
write_only 表明该字段仅用于反序列化输入,默认False
required 表明该字段在反序列化时必须输入,默认True
default 反序列化时使用的默认值
allow_null 表明该字段是否允许传入None,默认False
validators 该字段使用的验证器
error_messages 包含错误编号与错误信息的字典
3、序列化器的反序列化
3.1 基本使用
# 反序列化与序列化
序列化是从里面往外查询出数据
反序列化是从外面进数据
# 可以使用序列化器来完成数据反序列化的过程.这个过程可以把数据转成模型类对象.
# 可以通过实现create()和update()两个方法来实现。
from rest_framework.views import APIView
from app01.models import Book
from app01.serializer import BookSerializer
from rest_framework.response import Response
class BookView(APIView):
# 新增
def post(self, request, *args, **kwargs):
# 使用序列化类做保存
ser = BookSerializer(data=request.data)
# 数据校验:如果是True,表示校验通过,直接保存
if ser.is_valid():
ser.save() # 调用保存,但是有问题,保存不了,一定要在序列化类中重写某个方法
return Response(ser.data)
else:
return Response(ser.errors)
class BookDetailView(APIView):
# 修改接口
def put(self, request, pk):
book = Book.objects.filter(pk=pk).first()
ser = BookSerializer(instance=book, data=request.data)
# 数据校验:如果是True,表示校验通过,直接保存
if ser.is_valid():
ser.save() # 调用保存,但是有问题,保存不了,一定要在序列化类中重写update方法
return Response(ser.data)
else:
return Response(ser.errors)
'''
总结:
只有新增端口和修改端口是反序列化操作
'''
3.2 校验数据
from rest_framework import serializers
from app01.models import Book
from rest_framework.exceptions import ValidationError # 异常模块
# 写序列化类
class BookSerializer(serializers.Serializer):
title = serializers.CharField(max_length=8, min_length=3) # 校验字段
price = serializers.IntegerField()
publish = serializers.CharField()
# 局部钩子,先走字段再走局部钩子
def validate_title(self, item): # validate + 字段名
print(item)
if item.startswith('sb'):
raise ValidationError('不能以sb开头')
return item
# 全局钩子,先走字段再走局部钩子,最后在走全局钩子
def validate(self, attrs):
# 校验失败抛异常
if attrs.get('title') == attrs.get('publish'):
raise ValidationError('标题和出版社不能一样')
return attrs
4、模型类序列化器ModelSerializer
4.1 基本使用
4.1.1 serializer.py
# 反序列化,正常情况不需要重写 create和update
# 序列化:跟表模型有对应关系,不需要一个个字段都写了
class BookModelSerializer(serializers.ModelSerializer):
# 跟某个表模型建立关系
class Meta:
model = Book # 跟哪个表建立关系
fields = ['title', 'price', 'id', 'publish'] # 指定要序列化的类
# fields = '__all__' # 所有字段都序列化
# 重写字段
title = serializers.CharField(max_length=8, min_length=3)
# 局部钩子:必须和class Meta平级
def validate_price(self, price):
if not price > 100:
raise ValidationError('价格必须大于100')
return price
'''第一种方法'''
class BookModelSerializer(serializers.ModelSerializer):
# 跟某个表模型建立关系
class Meta:
model = Book # 跟哪个表建立关系
fields = ['title', 'price', 'id', 'publish'] # 指定要序列化的类
# 重写字段
title = serializers.CharField(max_length=8, min_length=3) # 第一种方式,在外面
# 第二种方式:是在class Meta里面
extra_kwargs = {
'title': {'max_length': 8, 'min_length': 3},
'price': {'min_value': 100}}
'''第二种方法'''
class BookModelSerializer(serializers.ModelSerializer):
# 跟某个表模型建立关系
class Meta:
model = Book # 跟哪个表建立关系
fields = ['title', 'price', 'id', 'publish'] # 指定要序列化的类
'''
默认是:既做序列化又做反序列化
read_only:只读,只序列化
write_only:只写,只做序列化,这个字段不做系列化
'''
extra_kwargs = {
'title': {'read_only': True}, # 只能做读操作,不能做写操作
# 'price': {'min_value': 100} # 只能做写操作,不能做读操作
}
'''
作用:有些窗口给别人开放只能查看的接口,但是修改或者别的不能开放给别人
为什么ModelSerializer不用重写create()和update()方法呢?
因为ModelSerializer里面自己写了create()和update()方法。
'''
4.1.2 views.py
from app01.serializer import BookModelSerializer
class BookView(APIView):
# 查询所有接口
def get(self, request, *args, **kwargs):
# 查询出所有图书
books = Book.objects.all()
ser = BookModelSerializer(instance=books, many=True) # 传入要序列化的数据
return Response(ser.data)
# 新增接口
def post(self, request, *args, **kwargs):
ser = BookModelSerializer(data=request.data)
if ser.is_valid():
ser.save()
return Response(ser.data)
else:
return Response(ser.errors)
class BookDetailView(APIView):
def get(self, request, pk):
# 查询单本图书
books = Book.objects.filter(pk=pk).first()
ser = BookModelSerializer(instance=books) # 序列化类中传入要序列化的数据
return Response(ser.data)
# 删除接口
def delete(self, request, pk):
Book.objects.filter(pk=pk).delete()
return Response()
# 修改接口
def put(self, request, pk):
book = Book.objects.filter(pk=pk).first()
ser = BookModelSerializer(instance=book, data=request.data)
if ser.is_valid():
ser.save()
return Response(ser.data)
4.2 常用方法
# 重点
read_only:只读,只序列化
write_only:只写,只做序列化,这个字段不做系列化
fields = '__all__' # 所有字段都序列化
# 了解
exclude = ['title'] # 除了这个字段,别的都需要序列化
depth = 1 # 表关联
5、django配置文件详解
# django项目启动之前,先执行这个配置文件(加载配置文件)
# 如果配置文件出错,整个项目启动不起来
import os
# 项目根路径
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# 秘钥:django中涉及到加密的通常用整个密码
SECRET_KEY = '@m*wf@^=)_hfd5mw)m8j@3mw%c35dalm*luvf8ag@x-l7+7gm*'
# 项目是调试模式:1是报错显示在网页上,2是可以热加载(热更新)
DEBUG = True
# 后期项目上线,需要配置服务器的地址
ALLOWED_HOSTS = []
# Application definition
# 注册app的地址
INSTALLED_APPS = [
'django.contrib.admin', # 后台管理
'django.contrib.auth', # 认证 auth组件 用户表
'django.contrib.contenttypes', # 每创建一个表,都会有一个记录
'django.contrib.sessions', # session的使用
'django.contrib.messages', # 消息框架:在不同的请求之间传递数据
'django.contrib.staticfiles', # 静态文件
'app01.apps.App01Config', # 自己写的app
]
# 中间件
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware', # 认证相关的中间件
'django.contrib.sessions.middleware.SessionMiddleware', # session放入中间件
'django.middleware.common.CommonMiddleware', # 访问路径带不带斜杠 /
'django.middleware.csrf.CsrfViewMiddleware', # csrf验证
'django.contrib.auth.middleware.AuthenticationMiddleware', # 用户登录注册
'django.contrib.messages.middleware.MessageMiddleware', # 消息框架
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
# 根路由
ROOT_URLCONF = 'drf04.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',
],
},
},
]
# 后期项目上线,使用uwsgi运行,指定的运行app
WSGI_APPLICATION = 'drf04.wsgi.application'
# 数据库的设置,可以配置多个数据库
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
# 认证的校验
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',
},
]
# 国际化:en-us;英文,zh-hans:中文
LANGUAGE_CODE = 'zh-hans' # 设置成中文
TIME_ZONE = 'Asia/Shanghai' # 因为上海在东八区,django支持上海时间
USE_I18N = True
USE_L10N = True
USE_TZ = False # 是否用UTC时间
# 静态文件
STATIC_URL = '/static/'