函数视图-类视图-mixins视图-通用视图-视图集
1.函数视图
@api_view(['get', 'post'])
def student_list_or_create(request, format=None):
"""
学生列表,学生创建视图
:param request:
:return:
"""
if request.method == 'GET':
# 1. 拿到所有的对象
objs = Student.objects.all()
# 2. 序列化
serializer = StudentSerializer(objs, many=True)
# 3. 返回drf的响应
return Response(serializer.data)
elif request.method == 'POST':
# 1. 创建序列化器对象
serializer = StudentSerializer(data=request.data)
# 2. 校验
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
else:
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
#在视图函数里加关键字参数format,默认可浏览的api模式html(format=None)
@api_view(['get', 'put', 'delete'])
def student_detail_update_delete(request, pk, format=None):
"""
学生详情,更新,删除视图
:param request:
:param pk:
:return:
"""
# 1. 获取对象
obj = get_object_or_404(Student, pk=pk)
# 2. 判断操作
if request.method == 'GET':
serializer = StudentSerializer(obj)
return Response(serializer.data)
elif request.method == 'PUT':
# 创建序列化器
# 应为是要更新对象,所以序列化器里需要传入data
serializer = StudentSerializer(obj, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
else:
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
elif request.method == 'DELETE':
obj.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
函数视图设置路由
from django.urls import path
from rest_framework.urlpatterns import format_suffix_patterns
from . import views
urlpatterns = [
# 添加到应用路由中
path('students/', views.student_list_or_create, name='list_create'),
path('students/<int:pk>/', views.student_detail_update_delete, name='detail_update_delete'),
]
# 处理一下路由,可以选择不同的渲染格式
urlpatterns = format_suffix_patterns(urlpatterns)
2.类视图
类视图和我们的django的类视图没有什么区别。
django类视图
from django.views import View
class StudentView(View):
"""
学生视图
"""
def get(self, request, pk=None):
"""
学生列表、学生详情
:param request:
:param pk:
:return:
"""
if pk is None:
# 学生列表
# 1. 获取学生列表
objs = Student.objects.all()
# 2. 序列化
# 使用序列化器序列化查询集
serializer = StudentSerializer(objs, many=True)
# 3.返回json响应
return JsonResponse(data=serializer.data, safe=False) #当data不是一个字典的时候,要加上safe=False
else:
# 学生详情
# 1. 获取学生对象
obj = get_object_or_404(Student, pk=pk)
# 2. 序列化
serializer = StudentSerializer(obj)
# 3.返回json响应
return JsonResponse(data=serializer.data)
def post(self, request):
"""
创建学生
:param request:
:return:
"""
# 1. 接受数据转换为字典
data = json.loads(request.body)
# 创建序列化器
serializer = StudentSerializer(data=data)
# 2.校验
if serializer.is_valid():
serializer.save()
# 校验成功返回创建对象的信息
return JsonResponse(data=serializer.data, status=201)
else:
# 校验不成功返回错误信息
return JsonResponse(data=serializer.errors, status=400)
def put(self, request, pk):
"""
修改学生
:param request:
:param pk:
:return:
"""
# 1. 获取对象
obj = get_object_or_404(Student, pk=pk)
# 2. 获取数据转换成字典
data = json.loads(request.body)
# 3. 创建序列化器
serializer = StudentSerializer(instance=obj, data=data)
# 4. 校验
if serializer.is_valid():
serializer.save()
# 校验成功返回创建对象的信息
return JsonResponse(data=serializer.data, status=200)
else:
# 校验不成功返回错误信息
return JsonResponse(data=serializer.errors, status=400)
def delete(self, request, pk):
"""
删除学生
:param request:
:param pk:
:return:
"""
# 1. 获取对象
obj = get_object_or_404(Student, pk=pk)
# 2. 删除
obj.delete()
return HttpResponse(status=204)
路由设置
from django.urls import path, include
from rest_framework.urlpatterns import format_suffix_patterns
from rest_framework.routers import DefaultRouter
from . import views
urlpatterns = [
path('students/', views.StudentView.as_view(), name='list_create'),
path('students/<int:pk>/', views.StudentView.as_view(), name='detail_update_delete')
]
# 处理一下路由,可以选择不同的渲染格式
urlpatterns = format_suffix_patterns(urlpatterns)
drf类视图
from rest_framework.views import APIView
class CustomGenericApiView(APIView):
# 视图使用的查询集
queryset = None
# 序列化器类
serializer_class = None
def get_queryset(self):
if self.queryset is None:
raise ValueError('必须设置一个queryset属性')
queryset = self.queryset
queryset = queryset.all()
return queryset
def get_serializer_class(self):
if self.serializer_class is None:
raise ValueError('必须设置一个serializer_class属性')
return self.serializer_class
def get_serializer(self, instance=None, data=empty, **kwargs):
serializer_class = self.get_serializer_class()
return serializer_class(instance, data, **kwargs)
3.mixins视图
import json
from django.shortcuts import (
render, get_object_or_404, redirect,
reverse
)
from django.views import View
from django.http.response import JsonResponse, HttpResponse
from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework import status, generics, mixins
from rest_framework.views import APIView
from rest_framework.fields import empty
from rest_framework.viewsets import ModelViewSet, ReadOnlyModelViewSet
from .models import Student, Channel, Course
from .serializers import StudentSerializer, CourseSerializer
class MixinListView:
def get(self, request, format=None):
# 1. 拿到所有的对象
objs = self.get_queryset()
# 2. 序列化
serializer_class = self.get_serializer_class()
serializer = serializer_class(objs, many=True)
# 3. 返回drf的响应
return Response(serializer.data)
class MixinCreateView:
def post(self, request, format=None):
# 1. 创建序列化器对象
serializer = self.get_serializer(data=request.data)
# 2. 校验
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
else:
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
4.通用视图
#drf类视图
class CustomGenericApiView(APIView):
"""
自定义通用视图
"""
# 视图使用的查询集
queryset = None
# 序列化器类
serializer_class = None
def get_queryset(self):
if self.queryset is None:
raise ValueError('必须设置一个queryset属性')
queryset = self.queryset
queryset = queryset.all()
return queryset
def get_serializer_class(self):
if self.serializer_class is None:
raise ValueError('必须设置一个serializer_class属性')
return self.serializer_class
def get_serializer(self, instance=None, data=empty, **kwargs):
serializer_class = self.get_serializer_class()
return serializer_class(instance, data, **kwargs)
#自定义通用视图
class StudentListCreateView(CustomGenericApiView, MixinListView, MixinCreateView):
"""
学生列表,创建视图
"""
queryset = Student.objects.all()
serializer_class = StudentSerializer
##rest_framework提供的通用视图
#(generics.RetrieveAPIView,generics.UpdateAPIView,generics.DestroyAPIView等等)
class StudentDetailUpdateDeleteView(generics.RetrieveAPIView,
generics.UpdateAPIView,
generics.DestroyAPIView,
):
"""
学生详情,更新,删除视图
"""
queryset = Student.objects.all()
serializer_class = StudentSerializer
路由设置
from django.urls import path, include
from rest_framework.urlpatterns import format_suffix_patterns
from . import views
# 通过视图集创建视图,并为视图绑定所需要的http方法
student_list_create = views.StudentViewSet.as_view({'get': 'list', 'post': 'create'})
student_detail_update_delete = views.StudentViewSet.as_view({
'get': 'retrieve',
'put': 'update',
'patch': 'partial_update',
'delete': 'destroy'
})
urlpatterns = [
# 添加到应用路由中
path('students/', student_list_create, name='student-list-create'),
path('students/<int:pk>/', student_detail_update_delete, name='student-detail-update-delete'),
]
# 处理一下路由,可以选择不同的渲染格式
urlpatterns = format_suffix_patterns(urlpatterns)
5.视图集
drf框架包含了一个处理视图集的抽象,还自动处理url。
视图集类与视图类几乎是相同,不同的是提供retrieve,update
这样的操作,而不是put,get.
class CourseViewSet(ModelViewSet):
"""
课程列表,创建视图
"""
queryset = Course.objects.all()
serializer_class = CourseSerializer
class StudentViewSet(ModelViewSet):
"""
学生视图集
"""
queryset = Student.objects.all()
serializer_class = StudentSerializer
路由设置
from django.urls import path, include
from rest_framework.urlpatterns import format_suffix_patterns
from rest_framework.routers import DefaultRouter
from . import views
# 创建一个路由器帮我们生成视图集上的路由
router = DefaultRouter()
# 注册课时视图集到路由对象
router.register(r'courses', views.CourseViewSet)
urlpatterns = [
]
# 处理一下路由,可以选择不同的渲染格式
urlpatterns = format_suffix_patterns(urlpatterns)
urlpatterns.append(path('', include(router.urls)))
Models.py代码
from django.db import models
from django.db.models import UniqueConstraint
class Student(models.Model): # 必须继承
name = models.CharField('姓名', max_length=20, help_text='姓名')
age = models.SmallIntegerField('年龄', null=True, blank=True, help_text='年龄')
sex = models.SmallIntegerField('性别', default=1, help_text='性别')
qq = models.CharField('qq号码', max_length=20, null=True, blank=True, unique=True, help_text='qq号码')
phone = models.CharField('手机号码', max_length=20, null=True, blank=True, unique=True, help_text='手机号码')
channel = models.ForeignKey('Channel', on_delete=models.SET_NULL, null=True, verbose_name='渠道', help_text='渠道来源', related_name='students')
c_time = models.DateTimeField('创建时间', auto_now_add=True)
def __str__(self):
return self.name
class Meta:
db_table = 'tb_student' # 设置创建表示的表名
verbose_name = '学生信息'
verbose_name_plural = verbose_name # django admin中显示模型的说明
# ordering = ['-age'] # 安装age从大到小排序
class Channel(models.Model):
name = models.CharField('名称', max_length=20, help_text='名称', unique=True)
def __str__(self):
return self.name
class Meta:
db_table = 'tb_channel'
verbose_name = '渠道来源'
verbose_name_plural = verbose_name
class Course(models.Model):
name = models.CharField('课程名称', max_length=24, help_text='课程名称', unique=True)
price = models.IntegerField('价格', help_text='课程价格')
period = models.SmallIntegerField('课时', help_text='课时,以小时为单位')
students = models.ManyToManyField(Student, through='Entry', verbose_name='学生', help_text='包名课程的学生')
def __str__(self):
return self.name
class Meta:
db_table = 'tb_course'
verbose_name = '课程表'
verbose_name_plural = verbose_name
class Entry(models.Model):
student = models.ForeignKey(Student, verbose_name='学生', help_text='报名学生', on_delete=models.PROTECT)
course = models.ForeignKey(Course, verbose_name='课程', help_text='报名课程', on_delete=models.PROTECT, db_constraint=False)
c_time = models.DateTimeField('报名时间', auto_now_add=True, help_text='报名时间')
def __str__(self):
return '{}-{}'.format(self.student.name, self.course.name)
class Meta:
db_table = 'tb_entry'
verbose_name = '报名表'
verbose_name_plural = verbose_name
constraints = [
UniqueConstraint(fields=['student', 'course'], name='unique_student_course')
]
class StudentDetail(models.Model):
STATION_CHOICES = [
('功能测试工程师', '功能测试工程师'),
('自动化测试工程师', '自动化测试工程师'),
('测试开发工程师', '测试开发工程师'),
('测试组长', '测试组长'),
('测试经理', '测试经理'),
]
class SalaryChoice(models.TextChoices):
FIRST = '5000以下', '5000以下'
SECOND = '5000-10000', '5000-10000'
THIRD = '10000-15000', '10000-15000'
FOURTH = '15000-20000', '15000-20000'
FIFTH = '20000以上', '20000以上'
student = models.OneToOneField(Student, verbose_name='学生', on_delete=models.CASCADE, help_text='学生', null=True)
city = models.CharField('所在城市', max_length=24, help_text='所在城市', null=True, blank=True)
company = models.CharField('任职公司', max_length=48, help_text='任职公司', null=True, blank=True)
station = models.CharField('岗位', max_length=24, help_text='岗位', choices=STATION_CHOICES, default='功能测试工程师' )
salary = models.CharField('薪资', max_length=24, help_text='薪资区间', choices=SalaryChoice.choices, default=SalaryChoice.FIRST)
def __str__(self):
return self.student.name
class Meta:
db_table = 'tb_student_detail'
verbose_name = '学生详情表'
verbose_name_plural = verbose_name
class Topping(models.Model):
name = models.CharField('名称', max_length=24)
class Pizza(models.Model):
name = models.CharField('名称', max_length=24)
toppings = models.ManyToManyField(Topping)
Serializers.py代码
from rest_framework import serializers
from rest_framework.validators import UniqueValidator
from .models import Student, Course
class CourseSerializer(serializers.ModelSerializer):
class Meta:
model = Course
exclude = ['students']
class StudentSerializer(serializers.ModelSerializer):
qq = serializers.CharField(allow_blank=True, allow_null=True, help_text='qq号码', label='Qq号码', max_length=20, required=False,
validators=[ UniqueValidator(queryset=Student.objects.all())],
error_messages={
'max_length': 'qq号码长度大于20位'
})
phone = serializers.RegexField(r'^1[3-9]\d{9}$',allow_blank=True, allow_null=True, help_text='手机号码', label='手机号码', max_length=11, min_length=11, required
=False, validators=[ UniqueValidator(queryset=Student.objects.all())])
# 元信息
class Meta:
# 指定根据哪个模型生成序列化器
model = Student
# 指定序列化哪些字段
# fields = ['id', 'name', 'sex']
# 所有字段
fields = '__all__'
# fields = ['id', 'name', 'channel_name']
# 排除
# exclude = ['id']
class CustomStudentSerializer(serializers.Serializer):
"""
学生序列化器
"""
# 定义需要序列化、反序列化的字段
id = serializers.IntegerField(label='学生id', read_only=True)
name = serializers.CharField(label='姓名')
sex = serializers.IntegerField(label='性别', default=1)
age = serializers.IntegerField(label='年龄', required=False, allow_null=True)
qq = serializers.IntegerField(label='qq号码', required=False, allow_null=True)
phone = serializers.IntegerField(label='手机号码', required=False, allow_null=True)
channel = serializers.CharField(label='渠道', read_only=True)
c_time = serializers.DateTimeField(label='创建时间', read_only=True)
def create(self, validated_data):
"""
创建对象时调用
:param validated_data:
:return:
"""
return Student.objects.create(**validated_data)
def update(self, instance, validated_data):
"""
更新对象时调用
:param instance:
:param validated_data:
:return:
"""
for key, value in validated_data.items():
setattr(instance, key, value)
instance.save()
return instance
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)