一. APIView版本

1. models.py

from django.db import models

# Create your models here.

class CommonField(models.Model):
is_delete = models.BooleanField(default=0, verbose_name='True标记被删除的数据,False标记正常使用的数据')
create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
update_time = models.DateTimeField(auto_now=True, verbose_name='最后更新时间') class Meta:
"""
参数拓展:
db_table: 指定字符串. 用来修改表名
abstract: 指定布尔值. 用来建立抽象表, 该表不会在数据库中创建
unique_together: 指定容器. 用来建立多字段唯一
index_together: 指定容器. 用来建立多字段之间的联合索引
单个字段,有索引,有唯一
多个字段,有联合索引,联合唯一
verbose_name: 指定字符串. 用来admin中显示表名, 默认加后缀s.
verbose_name_plural: 指定字符串. 用来admin中显示表名, 默认不加后缀s.
"""
abstract = True # 指定布尔值. 用来建立抽象表, 该表不会在数据库中创建 class Book(CommonField):
"""
参数拓展:
blank: 指定布尔值. 用来表示admin后台管理该字段时候可以为空.
help_text: 指定字符串. 用来表示admin后台管理的提示信息. 外键关联:
to_field: 指定关联的表的外键字段. 默认不写,关联到关联表的主键值.
db_constraint: 逻辑上的关联,实质上没有外键练习,增删不会受外键影响,以及不影响orm查询.
ForeignKey 与 OneToOneField
由源码得知OneToOneField继承ForeignKey, 并且默认制定了unique=True参数
ForeignKey(to='AuthorDetail', unique=True)
OneToOneField(to='AuthorDetail') on_delete参数:
1、表之间没有外键关联,但是有外键逻辑关联(有充当外键的字段)
2、断关联后不会影响数据库查询效率,但是会极大提高数据库增删改效率(不影响增删改查操作)
3、断关联一定要通过逻辑保证表之间数据的安全,不要出现脏数据,代码控制
4、断关联
5、级联关系
作者没了,详情也没:on_delete=models.CASCADE
出版社没了,书还是那个出版社出版:on_delete=models.DO_NOTHING
部门没了,员工没有部门(空不能):null=True, on_delete=models.SET_NULL
部门没了,员工进入默认部门(默认值):default=0, on_delete=models.SET_DEFAULT
"""
title = models.CharField(max_length=32, verbose_name='书名')
price = models.DecimalField(max_digits=4, decimal_places=2, verbose_name='价格')
publish = models.ForeignKey(to='Publish', to_field='id', db_constraint=False, on_delete=models.DO_NOTHING)
# 提示: to_field不能指定pk, 而是需要指定对应关联表的实际字段. 如果指定pk, 将会抛出如下异常:
'''
publish = models.ForeignKey(to='Publish', to_field='pk', on_delete=models.DO_NOTHING, db_constraint=False)
ERRORS:
api.Book.publish: (fields.E312) The to_field 'pk' doesn't exist on the related model 'api.Publish'.
'''
authors = models.ManyToManyField(to='Author', db_constraint=False) # 有第三张表,没有on_delete参数
# 什么时候需要半自动,主要看第三张变需要扩字段,比如要看第三张表的两个字段什么时候建立关系的,扩展一张时间表
# 半自动表的创建db_constraint参数的存在就会抛出如下异常:
'''
TypeError: __init__() got an unexpected keyword argument 'db_contraint'
''' # 半自动
# authors = models.ManyToManyField(to='Author', through_fields=('book', 'author'), through='Author2Book', db_constraint=False)
class Meta:
verbose_name = '图书表'
verbose_name_plural = verbose_name def __str__(self):
return self.title @property # 提示: property装饰器可以不指定
def publish_name(self):
return self.publish.name # @property # 提示: property装饰器可以不指定
def author_list(self):
# lis = []
# for author_obj in self.authors.all(): # 子查询正向,字段名,多个加all()
# lis.append({'name': author_obj.name, 'sex': author_obj.get_gender_display()})
# return lis
# 列表推导式
return [{'name': author_obj.name, 'sex': author_obj.get_gender_display()} for author_obj in self.authors.all()] # class Author2Book(models.Model):
# author = models.ForeignKey(to='Author', on_delete=models.DO_NOTHING, db_constraint=False)
# book = models.ForeignKey(to='Book', on_delete=models.NOT_PROVIDED, db_constraint=False) class Publish(CommonField):
name = models.CharField(max_length=32, verbose_name='出版社名')
addr = models.CharField(max_length=64, verbose_name='地址') class Meta:
verbose_name = '出版社表'
verbose_name_plural = verbose_name def __str__(self):
return self.name class Author(CommonField):
name = models.CharField(max_length=32, verbose_name='作者名')
gender_choice = (
(0, '男'),
(1, '女'),
(2, '秘密')
)
gender = models.IntegerField(choices=gender_choice, default=2, verbose_name='作者性别')
author_detail = models.OneToOneField(to='AuthorDetail', db_constraint=False, on_delete=models.CASCADE) class Meta:
verbose_name = '作者表'
verbose_name_plural = verbose_name def __str__(self):
return self.name class AuthorDetail(CommonField):
phone = models.CharField(max_length=11, verbose_name='作者手机号') class Meta:
verbose_name = '作者详情表'
verbose_name_plural = verbose_name def __str__(self):
return self.phone

2. ser.py 自定义序列化.py文件

from rest_framework import serializers
from app01 import models # many的设置后,重写update方法
class BookListSerializer(serializers.ListSerializer):
# def create(self, validated_data): # ListSerializer的create已帮写好了,不需要重写
# pass
def update(self, instance, validated_data):
return [self.child.update(instance[k], attrs) for k, attrs in enumerate(validated_data)] # 提示: 序列化操作的是数据库的表,推荐使用ModelSerializer
class BookModelSerializer(serializers.ModelSerializer):
# 第一种方式: 通过指定参数read_only=True, 在反序列化的时候不需要传该字段指定的值
# publish_name = serializers.CharField(source='publish.name', read_only=True) # 一对多关系,字段名
# read_only解决反序列化的问题 # 第二种方式: 在模型类中写方法, 通过方法关联到这里的字段. 如authors_list字段
class Meta:
"""
depth: 指定整数. 表示跨表查询的深度.
如果指定2, 查询的时候就会将本实例中Book表关联的表, 以及关联表的关联的表所有的数据获取出来.
"""
# 视图类中有many参数的,利用了元类的控制不同的类来生成对象,重写ListSerializer的方法,需要list_serializer_class = BookListSerializer
list_serializer_class = BookListSerializer
model = models.Book
# fields = '__all__'
# depth = 0
fields = ('id', 'title', 'price', 'publish', 'publish_name', 'authors', 'author_list')
extra_kwargs = {
'publish': {'write_only': True},
'publish_name': {'read_only': True},
'authors': {'write_only': True},
'author_list': {'read_only': True},
'pk': {'read_only': True}
}

3. views.py

from rest_framework.views import APIView
from rest_framework.response import Response
from app01 import models
from app01 import ser
from utils.exception import NonentityError from utils.response import CommonResponse # Create your views here. class BookAPIView(APIView):
def get(self, request, *args, **kwargs):
'''
# 如何区分请求过来是获取单条还是多条数据?
先配置2条路由, 2条路由都指向同一个视图类. 再通过url传递过来kwargs中是时候有pk值.
有: 单条数据 没有: 多条数据
# 前提: 所有的获取都需要在过滤is_delete=True的字段, 获取的只是没有标记被删除的is_delete=False的数据
# 获取单条数据: 直接获取到数据对象, 再使用自定义的序列化类序列话数据. 拿到序列化之后的结果
# 获取多条数据: 直接获取到queryset对象, 序列化时需要指定many=True, 即可
'''
# 获取一条
pk = kwargs.get('pk')
if pk:
book_obj = models.Book.objects.filter(pk=pk, is_delete=False).first()
book_ser = ser.BookModelSerializer(book_obj)
# 获取多条
else:
book_query = models.Book.objects.all().filter(is_delete=False) # 筛选出为删除的
book_ser = ser.BookModelSerializer(book_query, many=True)
return CommonResponse(results=book_ser.data)
# return Response({'code': 1000, 'msg': '成功', 'data': book_ser.data}) def post(self, request, *args, **kwargs):
'''
# 如何区分请求过来是新增单条还是多条数据?
在postman中的数据格式
单条数据格式: {}
多条数据格式: [{}, {}]
# 新增单条数据 和 新增多条数据
数据都是从body中获取, 反序列化时指定的参数是data, 还需要注意的就是多条数据需要指定many=True.
提示: 新增多条数据, ListSerializer中定义了create方法
本质就是通过for循环, 再调用ModelSerializer中的create方法.
def create(self, validate_data):
# self.child就是当前视图中所指序列化类实例化得到的对象(BookModelSerializer对象)
return [self.child.create(attrs) for attrs in validate_data]
'''
# 新增一条
if isinstance(request.data, dict):
book_ser = ser.BookModelSerializer(data=request.data) # 关键字参数传参
# 新增多条
elif isinstance(request.data, list):
book_ser = ser.BookModelSerializer(data=request.data, many=True) # 关键字参数传参,增多条
# book_ser是ListSerializer对象,for循环后,就是单个新增
else:
raise NonentityError('Add data through lists or dictionaries!')
book_ser.is_valid(raise_exception=True)
book_ser.save()
return CommonResponse(results=book_ser.data) def put(self, request, **kwargs):
'''
# 如何区分请求过来是修改单条还是多条数据?
判断: 通过路由的又名分组, 到kwargs中时候能获取pk值来判断
单条数据格式: pk -> {}
多条数据格式: [{'pk': ... }, {'pk': ... }]
# 修改单条数据
先获取传递过来的pk, 过滤出需要修改的数据对象
再往序列化的类中传递需要修改的对象, 以及该对象修改的数据 # 修改多条数据
先将传过来的列表套字典格式的数据中的所有字典中pk获取, 再使用双下划线过滤出对应的所有对象, 返回一个queryset对象.
再往序列换的类很重传递需要修改的queryset对象, 以及传递过来的要修改成什么样子的数据, 注意: 需要指定many=True
提示: 上面指定了many=True, 序列化完毕以后返回的是一个由ListSerializer类. ListSerializer类中定义了create,
但是没办法书写update方法, 因此需要我们重写.
步骤:
1) 新建一个类, 继承ListSerializer
2) 重写create方法
def create(self, instance, validate_data):
return [self.child.update(instance[i], attrs) for i, attrs in enumerate(validate_data)]
3) 在当前视图中执行序化类中在其, Meta中声明处理many=True时的类. list_serializer_class = 新建类名
'''
# 修改一条
pk = kwargs.get('pk')
if pk:
book_obj = models.Book.objects.filter(pk=pk).first()
print(request.data)
book_ser = ser.BookModelSerializer(instance=book_obj, data=request.data, partial=True)
# partial=True,可以对部分字段进行上传修改,没有的话,就要整个表的字段进行上传
book_ser.is_valid(raise_exception=True)
book_ser.save()
return CommonResponse(results=book_ser.data)
# 修改多条
elif isinstance(request.data, list):
# 第一种方案,request.data是列表套字典[{},{}],按id,生成[书对象1,书对象2],对应修改数据列表
# for循环一个一个的修改
book_obj_list = []
modify_data = []
for book_dic in request.data:
pk = book_dic.get('id')
book_obj_list.append(models.Book.objects.filter(pk=pk).first())
modify_data.append(book_dic)
# book_ser_list =[]
# for k, v in enumerate(modify_data):
# book_ser = ser.BookModelSerializer(instance=book_obj_list[k], data=v)
# book_ser.is_valid(raise_exception=True)
# book_ser.save()
# book_ser_list.append(book_ser.data)
# return CommonResponse(results=book_ser_list)
# 第二种方案,重写ListSerializer的update方法
book_ser = ser.BookModelSerializer(instance=book_obj_list, data=modify_data, many=True)
book_ser.is_valid(raise_exception=True)
book_ser.save()
return CommonResponse(results=book_ser.data)
else:
raise NonentityError('Specifies that the keyword can be partially modified or that the dictionary \
format of the list can be modified multiple times!') def delete(self, request, *args, **kwargs):
'''
# 如何区分请求过来是修改单条还是多条数据?
单条数据: 判断kwargs中是否有pk值
多条数据: {'pks': [1, 2, 3]}
# 删除单个 和 删除多个数据
提示: 不是真正的删除, 而是修改对应数据中的is_delete字段等于True
删除单个可
'''
pk = kwargs.get('pk')
pks = []
if pk:
# 单条删除
pks.append(pk)
# 不管单条删除还是多条删除,都是按照多条删除的方式来
# 多条删除
# 前端传过来的格式是{'pks':[1,2,3]}
else:
pks = request.data.get('pks')
# 不是真的删除,只是把is_delete设置为True
res = models.Book.objects.filter(pk__in=pks, is_delete=False).update(is_delete=True)
# is_delete=False,把为删除的数据筛选出来
print(res)
if res:
return CommonResponse(msg='删除成功')
else:
return CommonResponse(msg='没有要删除的数据')

4. urls.py

from django.contrib import admin
from django.urls import path
from app01 import views urlpatterns = [
path('admin/', admin.site.urls),
path('books/', views.BookAPIView.as_view()),
path('books/<int:pk>/', views.BookAPIView.as_view()),
# 分页器
path('books1/', views.BookListAPIView.as_view()),
path('books2/', views.BookAPIView1.as_view()),
]

5. utils 自定义工具包

1) exception_handler.py 自定义异常处理

from rest_framework.views import exception_handler
from rest_framework import status
from .response import CommonResponse def custom_exception_handler(exc, context):
response = exception_handler(exc, context)
if not response:
obj = CommonResponse(code=2000, messages='失败', error=str(exc), results=str(context),
status=status.HTTP_403_FORBIDDEN)
else:
obj = CommonResponse(code=2001, messages='失败', error=str(response.data), results=str(context),
status=status.HTTP_403_FORBIDDEN)
return obj

2) exception.py 自定义错误类型

class NonentityError(Exception):
def __init__(self, value):
self.value = value
super().__init__() def __str__(self):
return '< %s >' % self.value

3) response.py 自定义封装response对象

from rest_framework.response import Response

class CommonResponse(Response):
def __init__(self, code=1000, msg='成功', results=None, error=None, status=None,
template_name=None, headers=None,
exception=False, content_type=None, **kwargs):
dic = {'code': code, 'msg': msg}
if results:
dic['results'] = results
if error:
dic['error'] = error
dic.update(kwargs)
super().__init__(data=dic, status=status, template_name=template_name, headers=headers, exception=exception,
content_type=content_type)

4) throttle.py 自定义频率校验

from rest_framework.throttling import SimpleRateThrottle

class CustomSimpleRateThrottle(SimpleRateThrottle):
scope = 'custom' def get_cache_key(self, request, view):
# 'REMOTE_ADDR': '127.0.0.1',
# print(request.META.get('REMOTE_ADDR'))
return request.META.get('REMOTE_ADDR')

6. 总结

# 设计模型表的总结
1. 所有的表应该都有三个基本字段: is_delete, create_time, update_time
因此新增一个类继承Model, 之后的所有的类表继承它即可.
注意: 新增的类表默认会在执行数据库迁移命令以后, 会在数据库中生成,
因此应该新建Meat类, 指定abstract=True抽象表, 这样它就不会生成该表了.
2. 外键关联字段需要注意如下几种问题
1) 一对一关系要建立在查询次数较多的一行
2) 一对多关系要建立在多的一方, 如果建立在一的一行, 那么以后一的一行该外键对应的值将会是一个'[1, 2, 3]'这种结构.
这不是我们想要的. 我们最起码应该满足数据的数据设计存储规范.
3) 级联关系: 建立外键关联的字段要着重考虑on_delete参数.
如果一方没了, 那么另一方应该没有. 那么使用models.CASCADE(提示: 一对一关系表, 一般都是指定这个参数)
如果一方没了, 那么另一方应该存在. 那么使用models.DO_NOTHING
如果一方没了, 那么另一行应该设置为空. 那么使用models.SET_NULL
如果一方没了, 那么另一行应该转移到设置的默认情况上. 那么使用models.SET_DEFAULT
4) 断关联: 建立外键关联的字段最好使用db_constraint=False.
使用它可以提升对数据的操作, 不用依照外键之间删除数据, 新增数据的限制, 就可以直接对数据进行操作,
使用这种名义上的关联能最大化的提升数据库增删改的效率.
缺点: 如果直接操作数据库会出现脏数据, 因此不要直接操作数据库, 代码层面对数据的操作, 可以进行有效的控制即可
3. 疑问: 为什么创建半自动表使用db_constraint=False就会出现问题??? # 序列化器实现总结
1. 序列化操作涉及到数据库的操作, 推荐使用ModelSerializer
2. depth: 指定整数. 表示跨表查询的深度. 提示: 一般都不深度查询
3. 重点: 关于外键关联, 序列化 与 反序列化 是有所不同的
1) 专门用与序列化的字段设计: 新建一个外键字段指定只读
2种方法:
第一种: 序列化器中使用source
第二种: 模型类中写方法, 在fields中声明
注意: 该字段只读, 可在extra_kwargs中声明
2) 专门用与反序列化的字段设计: 默认的外键字段指定只写. # 视图方法实现总结
# get
# 如何区分请求过来是获取单条还是多条数据?
先配置2条路由, 2条路由都指向同一个视图类. 再通过url传递过来kwargs中是时候有pk值.
有: 单条数据 没有: 多条数据
# 前提: 所有的获取都需要在过滤is_delete=True的字段, 获取的只是没有标记被删除的is_delete=False的数据
# 获取单条数据: 直接获取到数据对象, 再使用自定义的序列化类序列话数据. 拿到序列化之后的结果
# 获取多条数据: 直接获取到queryset对象, 序列化时需要指定many=True, 即可 # post
# 如何区分请求过来是新增单条还是多条数据?
单条数据格式: {}
多条数据格式: [{}, {}]
# 新增单条数据 和 新增多条数据
数据都是从body中获取, 反序列化时指定的参数是data, 还需要注意的就是多条数据需要指定many=True.
提示: 新增多条数据, ListSerializer中定义了create方法
本质就是通过for循环, 再调用ModelSerializer中的create方法.
def create(self, validate_data):
# self.child就是当前视图中指行序列化类实例化得到的对象
return [self.child.create(attrs) for attrs in validate_data] # put
# 如何区分请求过来是修改单条还是多条数据?
判断: 通过路由的又名分组, 到kwargs中时候能获取pk值来判断
单条数据格式: pk -> {}
多条数据格式: [{'pk': ... }, {'pk': ... }]
# 修改单条数据
先获取传递过来的pk, 过滤出需要修改的数据对象
再往序列化的类中传递需要修改的对象, 以及该对象修改的数据 # 修改多条数据
先将传过来的列表套字典格式的数据中的所有字典中pk获取, 再使用双下划线过滤出对应的所有对象, 返回一个queryset对象.
再往序列换的类很重传递需要修改的queryset对象, 以及传递过来的要修改成什么样子的数据, 注意: 需要指定many=True
提示: 上面指定了many=True, 序列化完毕以后返回的是一个由ListSerializer类. ListSerializer类中定义了create,
但是没办法书写update方法, 因此需要我们重写.
步骤:
1) 新建一个类, 继承ListSerializer
2) 重写create方法
def create(self, instance, validate_data):
return [self.child.update(instance[i], attrs) for i, attrs in enumerate(validate_data)]
3) 在当前视图中执行序化类中在其, Meta中声明处理many=True时的类. list_serializer_class = 新建类名 # delete
# 如何区分请求过来是修改单条还是多条数据?
单条数据: 判断kwargs中是否有pk值
多条数据: {'pks': [1, 2, 3]}
# 删除单个 和 删除多个数据
提示: 不是真正的删除, 而是修改对应数据中的is_delete字段等于True
删除单个可

二. GenericAPIView版本

from rest_framework.generics import GenericAPIView
from . import models
from . import ser
from utils.response import CommonResponse
from utils.exception import NonentityError class BookAPIView(GenericAPIView):
queryset = models.Book.objects.all()
serializer_class = ser.BookModelSerializer def get(self, request, *args, **kwargs):
pk = kwargs.get('pk')
if pk:
instance = self.get_object()
# is_delete=True表示数据是做了删除标记的
if instance.is_delete:
raise NonentityError('The data as well does not exist anymore!')
else:
serializer = self.get_serializer(instance=instance)
else:
instance = self.get_queryset().filter(is_delete=False)
serializer = self.get_serializer(instance=instance, many=True)
return CommonResponse(results=serializer.data) def post(self, request, *args, **kwargs):
if isinstance(request.data, list):
serializer = self.get_serializer(data=request.data, many=True)
elif isinstance(request.data, dict):
serializer = self.get_serializer(data=request.data)
else:
raise NonentityError('Add data through lists or dictionaries!')
serializer.is_valid(raise_exception=True)
serializer.save()
return CommonResponse(results=serializer.data) def put(self, request, *args, **kwargs):
pk = kwargs.get('pk')
if pk:
instance = self.get_object()
serializer = self.get_serializer(instance=instance, data=request.data, partial=True)
elif isinstance(request.data, list):
# request.data = [{'id': 1, 'name': 'xxx', 'price': 'xxx'}]
pks = [dic.get('id') for dic in request.data]
instance = self.get_queryset().filter(pk__in=pks)
serializer = self.get_serializer(instance=instance, data=request.data, many=True)
else:
raise NonentityError(
'Specifies that the keyword can be partially modified or that the dictionary \
format of the list can be modified multiple times!')
serializer.is_valid(raise_exception=True)
serializer.save()
return CommonResponse(results=serializer.data) def delete(self, request, *args, **kwargs):
pk = kwargs.get('pk')
pks = []
pks = pks.append(pk) if pk else request.date.get('pks')
affected_rows = self.get_queryset().filter(pk__in=pks).update(is_delete=True)
return CommonResponse(results={'affected_rows': affected_rows})

总结

主要要明白GenericAPIView中提供的三种主要的方法的返回值
self.get_object() 返回数据对象
self.get_queryset() 返回queryset对象. 因此这里就可以继续有filter(), update()等连点操作
self.get_serializer() many=

三、user表练习

作业讲解

1 自定义user表,新增phone唯一约束字段,新增icon图片字段

2 在自定义user表基础上,用GenericViewSet + CreateModelMixin + serializer,完成user表新增接口(就是注册接口)(重要提示:序列化类要重写create方法,不然密码就是明文)

3 在自定义user表基础上,用GenericViewSet + RetrieveModelMixin + serializer 完成user表单查(就是用户中心)

4 在自定义user表基础上,用GenericViewSet + UpdateModelMixin + serializer 完成头像的修改

models.py

from django.db import models
from django.contrib.auth.models import AbstractUser # Create your models here. class UserInfo(AbstractUser):
phone = models.CharField(max_length=11, unique=True) # 唯一
icon = models.ImageField(upload_to='icon', default='icon/default.png') # ImageField依赖于pillow模块 class Book(models.Model):
name = models.CharField(max_length=64) def __str__(self):
return self.name class Car(models.Model):
name = models.CharField(max_length=64) def __str__(self):
return self.name

view.py

# 作业讲解
from rest_framework.viewsets import GenericViewSet
from rest_framework.mixins import CreateModelMixin, RetrieveModelMixin, UpdateModelMixin
from app01 import models
from app01 import ser class RegisterView(GenericViewSet, CreateModelMixin, RetrieveModelMixin, UpdateModelMixin):
queryset = models.UserInfo.objects.all()
serializer_class = ser.UserModelSerializer '''
假设get请求和post请求,用的序列化类不一样,如何处理?
重写get_serializer_class,返回啥,用的序列化类就是啥
注册,用的序列化类是UserModelSerializer,查询一个用的序列化类是UserReadOnlySerializer
''' def get_serializer_class(self):
if self.action == 'create':
return ser.UserModelSerializer
elif self.action == 'retrieve':
return ser.UserReadOnlySerializer
elif self.action == 'update':
return ser.UserImageViewSerializer

ser.py

from rest_framework import serializers
from rest_framework.exceptions import ValidationError
from app01 import models class UserModelSerializer(serializers.ModelSerializer):
re_password = serializers.CharField(max_length=11, required=True, write_only=True) # 因为re_password在表中没有,需要在这里定义 class Meta:
model = models.UserInfo
fields = ['username', 'password', 'phone', 're_password', 'icon']
extra_kwargs = {
'username': {'max_length': 16},
'password': {'write_only': True}
} # 局部钩子
def validate_phone(self, data):
if not len(data) == 11:
raise ValidationError('手机号是11位')
return data # 全局钩子
def validate(self, attrs):
if not attrs.get('password') == attrs.get('re_password'):
raise ValidationError('两次密码不一致')
attrs.pop('re_password')
return attrs # 重写新增方法
def create(self, validated_data):
# models.UserInfo.objects.create(**validated_data) # 密码是明文,所以要重写create方法
user_obj = models.UserInfo.objects.create_user(**validated_data)
return user_obj class UserReadOnlySerializer(serializers.ModelSerializer):
class Meta:
model = models.UserInfo
fields = ['username', 'icon'] class UserImageViewSerializer(serializers.ModelSerializer):
class Meta:
model = models.UserInfo
fields = ['icon', ]

urls.py

from app01 import views
from rest_framework.routers import SimpleRouter rooter_obj = SimpleRouter()
rooter_obj.register('register', views.RegisterView, 'register') urlpatterns = [
# path('register/', views.RegisterView.as_view({'post': 'create'})),
]
urlpatterns += rooter_obj.urls

总路由urls.py

# meida文件下的图片展示的总路由配置,就是把meida文件暴露给外界
from django.views.static import serve
from django.conf import settings # 建议用该种导入,也可以用项目导入 urlpatterns = [
path('media/<path:path>/', serve, {'document_root': settings.MEDIA_ROOT})
]

drf(Book序列化练习、user表练习)的更多相关文章

  1. Django框架深入了解_02(DRF之序列化、反序列化)

    序列化:将Python对象准换成json格式的字符串,反之即为反序列化 DRF的序列化使用过程: 使用drf的序列化组件 -1 新建一个序列化类继承Serializer -2 在类中写要序列化的字段 ...

  2. drf框架 - 序列化组件 | Serializer

    序列化组件 知识点:Serializer(偏底层).ModelSerializer(重点).ListModelSerializer(辅助群改) 序列化与反序列化 序列化: 将对象序列化成字符串用户传输 ...

  3. Django drf:序列化增删改查、局部与全局钩子源码流程、认证源码分析、执行流程

    一.序列化类的增.删.改.查 用drf的序列化组件   -定义一个类继承class BookSerializer(serializers.Serializer):   -写字段,如果不指定source ...

  4. DRF的序列化组件

    目录 DRF的序列化组件 Serializer组件 序列化 反序列化 ModelSerializer组件 序列化和反序列化 自定义Response方法 基表相关 DRF中ORM的多表关联操作 外键设计 ...

  5. drf框架序列化和返序列化

    0903自我总结 drf框架序列化和反序列化 from rest_framework import serializers 一.自己对于序列化和反序列化使用的分类 前后端交互主要有get,post,p ...

  6. 第三章、drf框架 - 序列化组件 | Serializer

    目录 第三章.drf框架 - 序列化组件 | Serializer 序列化组件 知识点:Serializer(偏底层).ModelSerializer(重点).ListModelSerializer( ...

  7. 【Django drf】 序列化类常用字段类和字段参数 定制序列化字段的两种方式 关系表外键字段的反序列化保存 序列化类继承ModelSerializer 反序列化数据校验源码分析

    目录 序列化类常用字段类和字段参数 常用字段类 常用字段参数 选项参数 通用参数 序列化类高级用法之source source填写类中字段 source填写模型类中方法 source支持跨表查询 定制 ...

  8. Drf 序列化 ModelSerializer跨表取数据

    1.对于OneToOne.Foreignkey.choices字段可以使用source取出相关信息: class CourseSerializer(serializers.ModelSerialize ...

  9. drf之序列化器的使用

    一.序列化器-Serializer 作用: 1. 序列化,序列化器会把模型对象转换成字典,经过response以后变成json字符串 2. 完成数据校验功能 3. 反序列化,把客户端发送过来的数据,经 ...

  10. Django框架(十八)—— drf:序列化组件(serializer)

    序列化组件 # 模型层 from django.db import models class Book(models.Model): nid = models.AutoField(primary_ke ...

随机推荐

  1. 《ASP.NET Core 微服务实战》-- 读书笔记(第1章 、第2章)

    译者序 微服务设计方法清晰定义了各个开发团队的业务边界,微服务框架以不同方式实现了服务之间的协作与集成. .NET Core 作为全新的 .NET 技术,它不仅完全开源.跨平台,更面向云原生开发进行了 ...

  2. 在.NET Core下的机器学习--学习笔记

    摘要 .NET Core 在机器学习的应用场景,除了 ML .NET 还会介绍一个非常棒的開源技術 TensorFlow .NET , Keras .NET. 讲师介绍 本课内容 人工智能介绍 ML ...

  3. MySQL最左匹配原则

    最左匹配原则都是针对联合索引来说的,那么为什么要使用联合索引呢? 一.为什么要使用联合索引? 1.减少开销. 建一个联合索引(col1,col2,col3),实际相当于建了(col1),(col1,c ...

  4. google三驾马车之一:Bigtable解读(英文版)

    本文重点关注了系统设计相关的内容,paper后半部分的具体应用此处没有过多涉及.从个人笔记修改而来,因此为英文版本. Bigtable: A Distributed Storage System fo ...

  5. CF1861

    只做出 A,身败名裂 A 显然不管怎么排,13,31 总有一个会出现,看看哪个出现. B 给定两个 01 串,每次可以挑一个串的一个子串,要求两端相同,然后把这个子串全部变得和两端相同. 问经过若干次 ...

  6. 你应该知道的提升Visual Studio开发能力的5个技巧

    如果你像我一样,或许你也沉迷于开发者工具.这就是我喜欢 Visual Studio 的原因之一--它有无数的生产力技巧. 这篇文章将展示五个这样的技巧,这些技巧对我每天的工作都有帮助.请注意,这些仅适 ...

  7. CF1823D Unique Palindromes

    题目链接 题解 知识点:构造. 首先反证法容易证明一个结论:每次增加一个字符,本质不同的回文子串至多增加一个. 那么无解的条件就是,\(c_i - c_{i-1} > x_i -x_{i-1}\ ...

  8. NC20951 网络优化

    题目链接 题目 题目描述 <梦三国2>是一款3D MOBA类网游.游戏继承<梦三国>的三国文化背景和基础玩法,并加入许多全新地图和全新竞技玩法.由于人气高,游戏在线人数与日俱增 ...

  9. P3078题解

    P3078题解 看到题解区,我有点震惊,什么贪心.线段树.各种优化都有,在此%%%.但其实这道题一个小小的差分就可解决. 前置芝士:前缀和/差分 by OI Wiki 题意简述 在一个 $card$ ...

  10. 【framework】WindowContainer简介

    1 前言 ​ WindowContainer 继承自 ConfigurationContainer,是 WMS 家族的重要基类.ConfigurationContainer简介 中,已介绍 Confi ...