1、FBV与CBV简介
FBV:Function Based View(基于函数的view)
就是在视图里使用函数处理请求。
CBV:Class Based View(基于类的view)
就是在视图里使用类处理请求。
我们之前写过的都是基于函数的view,就叫FBV。还可以把view写成基于类的,那就是CBV。
1.1、FBV基于函数的视图
路由配置:
urlpatterns = [path("login/", views.login),]
from django.shortcuts import render,HttpResponsedef login(request):if request.method == "GET":return HttpResponse("GET 方法")if request.method == "POST":user = request.POST.get("user")pwd = request.POST.get("pwd")if user == "runoob" and pwd == "123456":return HttpResponse("POST 方法")else:return HttpResponse("POST 方法1")
如果我们在浏览器中直接访问 http://127.0.0.1:8000/login/ ,输出结果为:
1.2、CBV基于类的视图
基于类的视图,就是使用了类来处理用户的请求,不同的请求我们可以在类中使用不同方法来处理,这样大大的提高了代码的可读性。
定义的类要继承父类 View,所以需要先引入库:
from django.views import View
执行对应请求的方法前会优先执行 dispatch 方法(在get/post/put…方法前执行),dispatch() 方法会根据请求的不同调用相应的方法来处理。
其实,在我们前面学到的知识都知道 Django 的 url 是将一个请求分配给可调用的函数的,而不是一个类,那是如何实现基于类的视图的呢? 主要还是通过父类 View 提供的一个静态方法 as_view() ,as_view 方法是基于类的外部接口, 他返回一个视图函数,调用后请求会传递给 dispatch 方法,dispatch 方法再根据不同请求来处理不同的方法。
路由配置:
urlpatterns = [path("login/", views.Login.as_view()),# as_view()方法绑定路由和 基于类的视图CBV]
from django.shortcuts import render,HttpResponsefrom django.views import Viewclass Login(View):def get(self,request):return HttpResponse("GET 方法")def post(self,request):user = request.POST.get("user")pwd = request.POST.get("pwd")if user == "runoob" and pwd == "123456":return HttpResponse("POST 方法")else:return HttpResponse("POST 方法 1")
如果我们在浏览器中直接访问 http://127.0.0.1:8000/login/ ,输出结果为:
2、CVB基于类的视图-实现增删改查
这个应用的models.py
from django.db import models# Create your models here.class BaseModel(models.Model): # 基类update_time = models.DateTimeField(auto_now=True)create_time = models.DateTimeField(auto_now_add=True)class Meta:abstract = True # 说明这个类只是用来继承的。(就不会创建这个表了)# 定义一个 班级表 模型类class Grade(BaseModel): # 继承这个基类name = models.CharField(verbose_name="班级", max_length=30, unique=True)desc = models.CharField(verbose_name="班级描述", max_length=50, null=True, blank=True)def __str__(self):return self.name# 定义一个 学生表 模型类class Student(BaseModel): # 继承这个基类name = models.CharField(max_length=30, verbose_name="姓名")phone = models.CharField(max_length=11, verbose_name="手机号", unique=True)qq = models.CharField(max_length=11, verbose_name="qq", unique=True)grade = models.ForeignKey(Grade, on_delete=models.CASCADE)def __str__(self):return self.name
这个应用的forms.py
from . import modelsfrom django import forms # 导入forms# 如果form对应了一个modelclass GradeForm(forms.ModelForm):# password2 = forms.CharField(min_length=6,max_length=13)# 数据库表中没有的字段,业务上需要校验的字段,可以在这里定义,和普通的form一样class Meta:model = models.Gradefields = "__all__" # 校验表里面所有字段# fields = ["name",""] # 校验表里面哪些字段# exclude = [] # 不校验表里哪些字段# 如果字段需要单独校验,也可以像普通的form一样 单独 用clean_xxx 去校验# def clean_name(self):# name = self.cleaned_data["name"]# if not name.startswith("班级"):# raise forms.ValidationError("班级名需要以“班级”开头")# return name
2.1、实现增加表记录-POST接口
from django.core.paginator import Paginatorfrom django.forms import model_to_dictfrom django.shortcuts import renderfrom django.views import Viewfrom django.http.response import JsonResponsefrom django.db.models import Qfrom . import forms, modelsclass GradeView(View):# 用于给班级表新增记录def post(self, request):form = forms.GradeForm(request.POST)#把请求参数传递给 表单验证if form.is_valid():obj = form.save() # 保存到数据库,并返回这个记录的对象return JsonResponse({"code": 0, "msg": "操作成功", "id": obj.id})return JsonResponse({"code": -1, "msg": form.errors.get_json_data()})# 如果没有校验通过,返回form的校验信息
注意:
别忘了把这个基于类的视图绑定好路由
2.2、实现修改表记录-PUT接口
Django暂不支持PUT请求,获取不到PUT请求传递过来的参数
先定义一个中间件
用来解决PUT请求参数接收不到的问题
from django.http import QueryDictfrom django.middleware.common import MiddlewareMixinclass PutMiddleware(MiddlewareMixin):"""给 Django 的request对象 增加 一个 PUT 对象"""def process_request(self, request):if request.method.upper() == "PUT":if "multipart" in request.content_type: # form-data# 上面这种是能传文件的那种formdata, files = request.parse_file_upload(request.META, request)request.PUT = datarequest._files = fileselse:data = QueryDict(request.body) # 这种是把普通k-v传参的转成字典request.PUT = data
编写视图函数
- 先确定修改哪条记录
- 然后再修改 ```python from django.core.paginator import Paginator from django.forms import model_to_dict from django.shortcuts import render from django.views import View from django.http.response import JsonResponse from django.db.models import Q from . import forms, models
class GradeView(View):
def put(self, request):id = request.PUT.get("id", "")if not id:return JsonResponse({"code": -1, "msg": "请传入要修改的id"})if not id.isdigit():return JsonResponse({"code": -1, "msg": "id是数字"})query_set = models.Grade.objects.filter(id=id)if not query_set.exists():return JsonResponse({"code": -1, "msg": "要修改的id不存在"})grade = query_set.first() # 定义的Grade 模型类的一个实例对象(就是表中的一条记录)form = forms.GradeForm(request.PUT, instance=grade) # 加入instance=模型类实例对象, 表明本次是修改记录,不是新增记录if form.is_valid():obj = form.save() # 保存到数据库return JsonResponse({"code": 0, "msg": "操作成功", "id": obj.id})return JsonResponse({"code": -1, "msg": form.errors.get_json_data()})
**接口工具调用一下接口,POST请求,修改记录**<br /><br /><a name="szXN3"></a>## 2.3、实现删除表记录-DELETE接口因为DELETE请求不带参数,只能在url中通过 查询字符串来传参,确定删除哪条记录```pythonfrom django.core.paginator import Paginatorfrom django.forms import model_to_dictfrom django.shortcuts import renderfrom django.views import Viewfrom django.http.response import JsonResponsefrom django.db.models import Qfrom . import forms, modelsclass GradeVies(View):def delete(self, request):id = request.GET.get("id")# 因为DELETE请求不带参数,只能在url中通过 查询字符串来传参,确定删除哪条记录if not id:return JsonResponse({"code": -1, "msg": "请传入要修改的id"})if not id.isdigit():return JsonResponse({"code": -1, "msg": "id是数字"})query_set = models.Grade.objects.filter(id=id)if not query_set.exists():return JsonResponse({"code": -1, "msg": "要修改的id不存在"})query_set.delete()return JsonResponse({"code": 0, "msg": "删除成功!"})
2.5、实现查询表记录-GET接口请求
- 查询所有的数据 -> 分页
- 查询单条数据
- 模糊查询 -> 分页
- 筛选查询
用来实现灵活配置的模糊查询,支持分页
from django.core.paginator import Paginatorfrom django.forms import model_to_dictfrom django.shortcuts import renderfrom django.views import Viewfrom django.http.response import JsonResponsefrom django.db.models import Qfrom . import forms, modelsclass GradeView(View):#用于实现模糊查询 方式1 新增需要模糊匹配的字段时 需要改代码# def get(self, request):# """# 1、查询所有的数据 -》 分页# 2、查询单条数据# 3、模糊查询 -》分页# 4、筛选# """# limit = request.GET.get("limit", 10)# page = request.GET.get("page", 1)# search = request.GET.get("search", )# if search:# all_data = models.Grade.objects.filter(Q(name__contains=search) | Q(desc__contains=search))# else:# all_data = models.Grade.objects.all()### # all_data = models.Grade.objects.all()# paginator = Paginator(all_data, limit)# page_data = paginator.get_page(page) # [<grade<1>,<garde2>]# data_list = [model_to_dict(data) for data in page_data]# data = {"code": 0, "msg": "查询成功", "data": data_list, "count": paginator.count}# return JsonResponse(data)# 方式2 模糊查询,灵活配置的,不需要改代码,search_fields = ["name", "desc"] # 指定哪些字段支持模糊查询def get(self, request):limit = request.GET.get("limit", 10)page = request.GET.get("page", 1)search = request.GET.get("search", )if search:q = Q() # Nonefor field in self.search_fields:d = {"%s__contains" % field: search}q = q | Q(**d)# all_data = models.Grade.objects.filter( Q(name__contains=search) | Q(desc__contains=search) )all_data = models.Grade.objects.filter(q)else:all_data = models.Grade.objects.all()paginator = Paginator(all_data, limit)page_data = paginator.get_page(page) # [<grade<1>,<garde2>]data_list = [model_to_dict(data) for data in page_data]data = {"code": 0, "msg": "查询成功", "data": data_list, "count": paginator.count}return JsonResponse(data)
用来实现先分类查询,再模糊查询
# 先分类查询 再模糊匹配class GradeView(View):search_fields = ["name", "desc"] # 指定哪些字段支持模糊查询filter_fields = ["id", "name"]# model Gradedef get(self, request):limit = request.GET.get("limit", 10)page = request.GET.get("page", 1)search = request.GET.get("search")query_dict = {} #{id:1,name:xxx} 用来存放筛选条件的字典q = Q() # Nonefor field in self.filter_fields:value = request.GET.get(field)if value != None:query_dict[field] = valueif search:for field in self.search_fields:d = {"%s__contains" % field: search}q = q | Q(**d)# all_data = models.Grade.objects.filter(q).filter(**query_dict)# 先模糊查询后,再分类 # 先模糊,后精确all_data = models.Grade.objects.filter(**query_dict).filter(q)# 先分类筛选后,再模糊查询 # 先精确,后模糊paginator = Paginator(all_data, limit)page_data = paginator.get_page(page) # [<grade<1>,<garde2>]data_list = [model_to_dict(data) for data in page_data]data = {"code": 0, "msg": "查询成功", "data": data_list, "count": paginator.count}return JsonResponse(data)
参考博客
菜鸟教程:Django 视图 - FBV 与 CBV
https://www.runoob.com/django/django-views-fbv-cbv.html
博客园:Django 视图之FBV与CBV
https://www.cnblogs.com/Michael—chen/p/10952134.html




