git补充
drf补充
开始之前
修改功能
1.写视图
def update(self, request, pk):
# 查询要修改的数据
try:
student = Student.objects.get(id=pk)
except Student.DoesNotExist:
return Response(status=HTTP_404_NOT_FOUND)
# 获取前端传入的数据进行反序列化
serializer = StudentSerializer(student, data=request.data) # 序列化对象没有传入instance, save()做create保存;传入则进行update保存
# 校验
serializer.is_valid(raise_exception=True)
# 对数据进行修改
serializer.save()
return Response(serializer.data) # 通过序列化器对象的data属性获取序列化后的数据(json格式的数据)
2. 写路由
3.效果
4. 做修改
删除功能
1.写视图
def destroy(self, request, pk):
# 查询要修改的数据
try:
student = Student.objects.get(id=pk)
except Student.DoesNotExist:
return Response(status=HTTP_404_NOT_FOUND)
student.delete()
return Response(status=HTTP_204_NO_CONTENT)
2. 写路由
3. 页面效果
4.删除
总:
1.模型类
from django.db import models
# Create your models here.
class Student(models.Model):
SEX_CHOICES = (
(0, '女'),
(1, '男'),
)
name = models.CharField(max_length=30, verbose_name='姓名')
age = models.IntegerField(verbose_name='年龄', null=True, blank=True)
sex = models.IntegerField(verbose_name='性别', null=True, blank=True, choices=SEX_CHOICES)
create_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True)
update_time = models.DateTimeField(auto_now=True, verbose_name='更新时间')
is_delete = models.BooleanField(default=False, verbose_name='逻辑删除')
class Meta: #定义原信息
db_table = 'student' # 将映射的表名设置为 student
2.序列化器
# -*- coding: utf-8 -*-
# @Time : 2021/11/12
# @Author : LY
# @Email : ly@mq.com
# @File : .py
# @Software :
"""
序列化器
本质就是一个类,和模型类差不多的类
用于JSON格式与模对象进行互转以及校验数据
定义的属性就是要参与转换的字段
序列化器字段可以少于或多于模型类字段(属性)
定义返回的数据有哪些字段
"""
from rest_framework import serializers
from .models import Student
class StudentSerializer(serializers.ModelSerializer):
class Meta:
model = Student # 指定序列化器映射的模型类
fields = '__all__' # fields指定映射字段__all__表示所有字段
# fields = ['id', 'name', 'age'] # 只映射id,name,age
# exclude = ['id'] # 映射除id字段之外的所有字段
# 修改映射字段
extra_kwargs = {
'age': {'min_value': 0, 'max_value': 200},
}
# 追加额外的校验逻辑
def validate_name(self, value):
if 'python' not in value.lower():
raise serializers.ValidationError('name error')
return value
# # 对象级别的额外验证
#
# def validate(self, data):
# if 'python' not in data['name'].lower():
# raise serializers.ValidationError('name error')
# return data
3.视图
from django.shortcuts import render
from rest_framework import viewsets
from rest_framework.response import Response
from rest_framework.status import HTTP_404_NOT_FOUND, HTTP_204_NO_CONTENT
from .models import Student
from .serializers import StudentSerializer
# Create your views here.
class StudentViewSet(viewsets.ViewSet):
def list(self, request):
# 获取所有的学生信息,返回的是模型类集合
student = Student.objects.all()
# 序列化: 实例化序列化器。传入要转换的模型集合,如果是多条数据一般我们加一个参数many=True
serializer = StudentSerializer(student, many=True)
# 返回响应: 返回序列化后的数据
return Response(serializer.data)
def create(self, request):
# 获取前端传入的数据
serializer = StudentSerializer(data=request.data) # 得到的是前端的数据,我们需要转模型,反序列化
# 校验
serializer.is_valid(raise_exception=True)
# 保存数据
serializer.save()
# 返回响应: 返回序列化数据
return Response(serializer.data)
def retrieve(self, request, pk):
try:
student = Student.objects.get(id=pk)
except Student.DoesNotExist:
return Response(status=HTTP_404_NOT_FOUND)
serializer = StudentSerializer(instance=student) # instance 序列化 , data 反序列化
return Response(serializer.data)
def update(self, request, pk):
# 查询要修改的数据
try:
student = Student.objects.get(id=pk)
except Student.DoesNotExist:
return Response(status=HTTP_404_NOT_FOUND)
# 获取前端传入的数据进行反序列化
serializer = StudentSerializer(student, data=request.data) # 序列化对象没有传入instance, save()做create保存;传入则进行update保存
# 校验
serializer.is_valid(raise_exception=True)
# 对数据进行修改
serializer.save()
return Response(serializer.data) # 通过序列化器对象的data属性获取序列化后的数据(json格式的数据)
def destroy(self, request, pk):
# 查询要修改的数据
try:
student = Student.objects.get(id=pk)
except Student.DoesNotExist:
return Response(status=HTTP_404_NOT_FOUND)
student.delete()
return Response(status=HTTP_204_NO_CONTENT)
4. 路由
from django.urls import path
from .views import StudentViewSet
urlpatterns = [
path('student/', StudentViewSet.as_view({'get': 'list', 'post': 'create'})),
path('student/<pk>/', StudentViewSet.as_view({'get': 'retrieve', 'put': 'update', 'delete': 'destroy'}))
]
假设你要进行老师对学生表的管理,然后需要写老师的增删改查,与学生模型一
样,只是数据不一样,会使得我们进行重复复杂的操作。于是drf帮我们做了升级,帮
我们定义了ModelViewSet,帮我们实现了所有的方法(增删改查),我们只需要定义
数据集和序列化器就可以了。只有数据不一样(学生变老师),然后序列化器不一样
(不同的数据用不同的序列化器进行转化),我们只需要定义不一样的地方,交给
drf进行带入处理。
1. 修改视图
class StudentViewSet(viewsets.ModelViewSet):
queryset = Student.objects.all()
serializer_class = StudentSerializer
2. 网页效果
3. 查询
4.修改
5.增加
6.删除
关于 ModelViewSet
按住ctr键+鼠标点击 ModelViewSet,进入class ModelViewSet,里面已经帮忙定义了五种方法,如果只想要显示其中某一种,就直接继承对应的类,比如只想要查询功能(这里这作为介绍)
路由升级
1.创建路由
from rest_framework.routers import SimpleRouter
from .views import StudentViewSet
urlpatterns = [
]
router = SimpleRouter() # 创建路由器
router.register('student', StudentViewSet) # 注册路由
urlpatterns += router.urls # 获取生成的路由列表,然后拼接
逻辑删除
1.起因
2. 修改模型类
def delete(self, using=None, keep_parents=False):
self.is_delete = True
self.save()
3. 删除效果
4.优化查询功能
class StudentViewSet(ModelViewSet):
# queryset = Student.objects.all()
queryset = Student.objects.filter(is_delete=False)
serializer_class = StudentSerializer
关联序列化
1. 被 表Student 添加外键字段,关联 class 班级表,现在需要删表重建,所以要注释与该表有关的所有信息
2.迁移映射
3.将注释掉的所有信息 crt+z 撤回,恢复原样。之前的操作是为了删除数据库里面的表。
4. 定义好模型
from django.db import models
# Create your models here.
class Student(models.Model):
SEX_CHOICES = (
(0, '女'),
(1, '男'),
)
name = models.CharField(max_length=30, verbose_name='姓名')
age = models.IntegerField(verbose_name='年龄', null=True, blank=True)
sex = models.IntegerField(verbose_name='性别', null=True, blank=True, choices=SEX_CHOICES)
create_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True)
update_time = models.DateTimeField(auto_now=True, verbose_name='更新时间')
is_delete = models.BooleanField(default=False, verbose_name='逻辑删除')
classes = models.ForeignKey('Classse', on_delete=models.CASCADE) # 外键
class Meta: # 定义原信息
db_table = 'student' # 将映射的表名设置为 student
def delete(self, using=None, keep_parents=False):
self.is_delete = True
self.save()
class Classse(models.Model):
name = models.CharField(max_length=30, verbose_name="班级名")
slogan = models.TextField(verbose_name="口号", null=True, blank=True)
create_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True)
update_time = models.DateTimeField(auto_now=True, verbose_name='更新时间')
is_delete = models.BooleanField(default=False, verbose_name='逻辑删除')
class Mete: # 定义原信息,更改表名
db_table = 'Classse'
def delete(self, using=None, keep_parents=False): # 逻辑删除
self.is_delete = True
self.save()
5.迁移映射
6.写序列化器
# -*- coding: utf-8 -*-
# @Time : 2021/11/12
# @Author : LY
# @Email : ly@mq.com
# @File : .py
# @Software :
"""
序列化器
本质就是一个类,和模型类差不多的类
用于JSON格式与模对象进行互转以及校验数据
定义的属性就是要参与转换的字段
序列化器字段可以少于或多于模型类字段(属性)
定义返回的数据有哪些字段
"""
from rest_framework import serializers
from .models import Student, Classse
class StudentSerializer(serializers.ModelSerializer):
class Meta:
model = Student # 指定序列化器映射的模型类
fields = '__all__' # fields指定映射字段__all__表示所有字段
# fields = ['id', 'name', 'age'] # 只映射id,name,age
# exclude = ['id'] # 映射除id字段之外的所有字段
# 修改映射字段
extra_kwargs = {
'age': {'min_value': 0, 'max_value': 200},
}
# 追加额外的校验逻辑
def validate_name(self, value):
if 'python' not in value.lower():
raise serializers.ValidationError('name error')
return value
# # 对象级别的额外验证
#
# def validate(self, data):
# if 'python' not in data['name'].lower():
# raise serializers.ValidationError('name error')
# return data
class ClassseSerializer(serializers.ModelSerializer):
class Meta:
model = Classse # 指定序列化器映射的模型类
fields = '__all__' # fields指定映射字段__all__表示所有字段
def validated_name(self, value):
if '码趣教育' not in value:
raise serializers.ValidationError('班级名需要带有码趣教育')
return value
7.写视图
from rest_framework.viewsets import ModelViewSet
from .models import Student, Classse
from .serializers import StudentSerializer, ClassseSerializer
# Create your views here.
class StudentViewSet(ModelViewSet):
# queryset = Student.objects.all()
queryset = Student.objects.filter(is_delete=False)
serializer_class = StudentSerializer # 指定序列化器
class ClassViewSet(ModelViewSet):
# queryset = Student.objects.all()
queryset = Classse.objects.filter(is_delete=False)
serializer_class = ClassseSerializer
8.写路由
from rest_framework.routers import SimpleRouter
from .views import StudentViewSet, ClassViewSet
urlpatterns = [
]
router = SimpleRouter() # 创建路由器
router.register('student', StudentViewSet) # 注册路由
router.register('class', ClassViewSet) # 注册路由
urlpatterns += router.urls # 获取生成的路由列表,然后拼接
9.效果
10.添加数据
11.修改
12.新增班级
13.返回班级里所有的学生(班级关联学生)
student_set = StudentSerializer(many=True)
说明部分:因为个人原因,这里已经删除表格重建,就是上面有步骤说明,相关表格信息全部注释然后映射提交。
我只是为了修改表名,话不多说,强迫症犯病了。取消所有注释,修改表名后,在映射提交。
(1)模型类
from django.db import models
# Create your models here.
class Student(models.Model):
SEX_CHOICES = (
(0, '女'),
(1, '男'),
)
name = models.CharField(max_length=30, verbose_name='姓名')
age = models.IntegerField(verbose_name='年龄', null=True, blank=True)
sex = models.IntegerField(verbose_name='性别', null=True, blank=True, choices=SEX_CHOICES)
create_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True)
update_time = models.DateTimeField(auto_now=True, verbose_name='更新时间')
is_delete = models.BooleanField(default=False, verbose_name='逻辑删除')
classes = models.ForeignKey('Classes', on_delete=models.CASCADE) # 外键
class Meta: # 定义原信息
db_table = 'student' # 将映射的表名设置为 student
def delete(self, using=None, keep_parents=False):
self.is_delete = True
self.save()
class Classes(models.Model):
name = models.CharField(max_length=30, verbose_name="班级名")
slogan = models.TextField(verbose_name="口号", null=True, blank=True)
create_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True)
update_time = models.DateTimeField(auto_now=True, verbose_name='更新时间')
is_delete = models.BooleanField(default=False, verbose_name='逻辑删除')
class Mete: # 定义原信息,更改表名
db_table = 'class'
def delete(self, using=None, keep_parents=False): # 逻辑删除
self.is_delete = True
self.save()
def __str__(self):
return self.name
(2)序列化器
# -*- coding: utf-8 -*-
# @Time : 2021/11/12
# @Author : LY
# @Email : ly@mq.com
# @File : .py
# @Software :
"""
序列化器
本质就是一个类,和模型类差不多的类
用于JSON格式与模对象进行互转以及校验数据
定义的属性就是要参与转换的字段
序列化器字段可以少于或多于模型类字段(属性)
定义返回的数据有哪些字段
"""
from rest_framework import serializers
from rest_framework.relations import StringRelatedField
from .models import Student, Classes
class StudentSerializer(serializers.ModelSerializer):
# Classes = StringRelatedField(read_only=True)
class Meta:
model = Student # 指定序列化器映射的模型类
fields = '__all__' # fields指定映射字段__all__表示所有字段
# fields = ['id', 'name', 'age'] # 只映射id,name,age
# exclude = ['id'] # 映射除id字段之外的所有字段
# 修改映射字段
extra_kwargs = {
'age': {'min_value': 0, 'max_value': 200},
}
# 追加额外的校验逻辑
def validate_name(self, value):
if 'python' not in value.lower():
raise serializers.ValidationError('name error')
return value
# # 对象级别的额外验证
#
# def validate(self, data):
# if 'python' not in data['name'].lower():
# raise serializers.ValidationError('name error')
# return data
class ClassesSerializer(serializers.ModelSerializer):
# student_set = StudentSerializer(many=True)
class Meta:
model = Classes # 指定序列化器映射的模型类
fields = '__all__' # fields指定映射字段__all__表示所有字段
def validated_name(self, value):
if '码趣教育' not in value:
raise serializers.ValidationError('班级名需要带有码趣教育')
return value
(3)视图
from rest_framework.viewsets import ModelViewSet
from .models import Student, Classes
from .serializers import StudentSerializer, ClassesSerializer
# Create your views here.
class StudentViewSet(ModelViewSet):
# queryset = Student.objects.all()
queryset = Student.objects.filter(is_delete=False)
serializer_class = StudentSerializer # 指定序列化器
class ClassViewSet(ModelViewSet):
# queryset = Student.objects.all()
queryset = Classes.objects.filter(is_delete=False)
serializer_class = ClassesSerializer
(4)路由
# -*- coding: utf-8 -*-
# @Time : 2021/11/12
# @Author : LY
# @Email : ly@mq.com
# @File : .py
# @Software :
from rest_framework.routers import SimpleRouter
from .views import StudentViewSet, ClassViewSet
urlpatterns = [
]
router = SimpleRouter() # 创建路由器
router.register('student', StudentViewSet) # 注册路由
router.register('class', ClassViewSet) # 注册路由
urlpatterns += router.urls # 获取生成的路由列表,然后拼接
(5)总路由
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('user/', include('user.urls'))
]
1.班级获取学生信息
2.逻辑删除
发现一个问题:我的表名为啥没有更改成功?原因是Meta写成了Mete了,于是我修改后,重新映射提交后,表明被成功修改
3. 获取最后一条数据
@action(methods=['get'], detail=False) # 定义路由的请求方法 detail=False 不需要通过编号去获取
def last(self, request):
classes = Classes.objects.last() # 查询最后一条数据,及最新的数据
serializer = self.get_serializer(classes) # 拿到指定的序列化器
return Response(serializer.data)
修改
@action(methods=['get'], detail=False) # 定义路由的请求方法 detail=False 不需要通过编号去获取
def last(self, request):
# classes = Classes.objects.last() # 查询最后一条数据,及最新的数据
classes = Classes.objects.filter(is_delete=False).last() # 去掉逻辑删除查询最后一条数据,及最新的数据
serializer = self.get_serializer(classes) # 拿到指定的序列化器
return Response(serializer.data)
新增一个功能,添加路由只需要@装饰器(设置访问的请求方式,设是否是详情的方法)
反爬的功能(有时候会被限流,限制访问的次数,为了保护服务器)
1.新建一个配置
REST_FRAMEWORK = {
'DEFAULT_THROTTLE_CLASSES': [
'rest_framework.throttling.AnonRateThrottle', # 没有登录(匿名)的访问频次
'rest_framework.throttling.UserRateThrottle' # 登录的用户访问频次
],
'DEFAULT_THROTTLE_RATES': {
'anon': '100/day', # 匿名访问次数(1天) # day hour minute second 都可以设置
'user': '1000/day' # 用户访问次数(1天)
}
}
2.修改设置访问
如何生成官方文档?
1.下载依赖包
pip install coreapi -i https://pypi.douban.com/simple
2. 重启pycharm
3. 配置
'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema'
3. 配置接口文档使用路由(总路由)
from django.contrib import admin
from django.urls import path, include
from rest_framework.documentation import include_docs_urls
urlpatterns = [
path('admin/', admin.site.urls),
path('user/', include('user.urls')),
path('docs/', include_docs_urls('DRF Study API 接口文档')),
]
5. 访问路由(看接口文档)
6.修改描述说明
7.添加中文说明
补充内容:删除分支