django 基于类的视图
原创博客,转载请只用写本文url链即可。
View
最基本的视图。除了get,post等方法,还能用几个Mixin以外,其他和函数差不多。
导入:
from django.views import View
ListView
定义这个类视图必须写如下两个参数或者之一:model
or queryset
or get_queryset()
。我比较推荐用queryset
。queryset
就是写一个queryset
,字面意思。model
就是模型名。get_queryset()
就是返回一个queryset
。还是觉得用queryset
简单,无痛。
使用如下:
class IndexView(ListView):
queryset = User.objects.all()
template_name = 'index.html' # mypp/user_list.html
context_object_name = 'ones' # 如果不设置,它的默认名字就是user_list.html
paginate_by = 3 # 每页显示多少个数据
# page_kwarg = 'page' # 这个参数是查询第几页的参数名,不写默认是page
# ordering = None # 排序规则,传入一个元组
# paginator_class = Paginator # 这个可以不用写,这个是django默认的分页方式
# extra_context = {"hello": "world!"} # 添加额外参数,也可以使用get_context_data函数来添加额外参数,推荐使用函数方式,这样可读性更好。
def get_context_data(self, **kwargs):
# 这个方法就是用来给添加新的模板渲染变量的
context = super().get_context_data(**kwargs)
context['hello'] = "world!"
return context
get_context_data再推荐一种写法,这个写法是源码复用时候的写法:
def get_context_data(self, **kwargs):
kwargs['hello'] = 'world'
return super().get_context_data(**kwargs)
DetailView
获得模型中的单一数据。
使用代码如下:
class DetaiPageView(DetailView):
queryset = User.objects.all() # model or queryset or get_queryset()
template_name = 'detail.html' # 如果不设置,它的默认名字就是user_detail.html
context_object_name = 'one'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['hello'] = "world"
return context
默认是找主键,也可以自定义参数,如果要自定义参数,需要保证模型中有slug字段,然后在urls.py中这么写:
path("detail/<slug>/", views.DetaiPageView.as_view(), name="detail"),
# path("detail/<pk>/", views.DetaiPageView.as_view(), name="detail"), 如果写pk就是找主键了,注意,这里只能找pk或者slug,不能写id,username之类的字段
注意:urls.py中参数变量只能是pk或者slug字段。所以写pk或者slug。如果你想使用其他参数,比如username作为这个变量,你可以设置这个属性:
slug_field = "username"
然后在urls.py中还是要写slug:
path("detail/<slug>/", views.DetaiPageView.as_view(), name="detail"),
TemplateView
这个类方法很简单,如果你会用ListView和DetailView,这个类会很好上手。
最简单的使用:
path("template/", TemplateView.as_view(template_name="template.html"), name="template"),
一行代码直接解决一个页面。
如果想要给模板加上变量参数可以这么写:
path("template/", TemplateView.as_view(template_name="template.html", extra_context={"hello": "world"}), name="template"),
RedirectView
class RedirectPageView(RedirectView):
parmanent = False # 是否是永久重定向,就是状态码会不同,默认是False
pattern_name = 'detail' # name值
# url 属性 : 这个属性是直接写url链接跳转,不过不建议,就写上面的name值就可以了
如果重定向的页面有参数的话,这个方法是我发现的,不过个人认为有点蹩脚。所以,呃,不是很推荐使用,但是如果要有重定向有参数的需求的时候,可以这么写,只需要把参数这么写:
class RedirectPageView(RedirectView):
pattern_name = 'detail'
def get_redirect_url(self):
return super().get_redirect_url(pk=1)
当然,能一行代码搞定的事情为什么要写几行呢,来吧,一行重定向:
path("redirect/", views.RedirectView.as_view(pattern_name="template"), name="redirect"),
FormView
这么写:
from django.views.generic import FormView
from django.urls import reverse_lazy
from myapp.forms import UserForm
class FormPageView(FormView):
success_url = reverse_lazy("template")
form_class = UserForm
template_name = "forms.html"
# initial = {"username": "catfish"} 设置初始值
# prefix = "catfish" 设置表单name前缀,比如,如果设置的是catfish,则name为"catfish-username"
这里如果不用reverse_lazy用reverse会报错:
django.core.exceptions.ImproperlyConfigured: The included URLconf 'drf_project.urls' does not appear to have any patterns in it. If you see valid patterns in the file then the issue is probably caused by a circular import.
原因就是因为在调用urls.py
之前使用了reverse
反转了一个空的url
链接,所以会报错。而reverse_lazy可以使它延迟在加载urls.py
之后再加载。一般来说,在FBV
中使用reverse
,在CBV
中使用reverse_lazy
。
所以,如果是在类属性中调用reverse
会报错,这个时候我们需要使用reverse_lazy
使它延迟加载,如果是在类的方法中使用reverse是不会报错的。因为方法是在它被调用的时候加载,而类属性是加载类的时候就会加载。加载类的时候加载在urls.py
之前,而调用类中的方法是在访问页面的时候,也就是被调用的时候被加载,此时的urls.py
已经被加载了,所以不会报错。
说了这么多,来个总结:在类视图的属性中使用reverse_lazy,在类视图的方法和函数视图中可以使用reverse。
CreateView
这个方法就是提交表单并创建一个对象。使用代码如下:
class CreatePageView(CreateView):
form_class = UserForm
template_name = "create.html"
success_url = '/'
推荐这么写,这样可以用到表单的验证。也可以定义model和field字段指定然后创建,不过使用model和field字段只会在已能输入的字段上进行models.py里面的验证,不能输入的字段中不能使用该验证,会默认保存为一个空的字符串。
这个类方法的特色是,多了个self.object
属性,如果表单识别验证通过会出现这个属性,如果不通过则不会返回。
extra_context和get_context_data适用于这个方法。urls.py代码如下:
path("create/", views.CreatePageView.as_view(), name="create"),
DeleteView
使用代码如下:
from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_exempt
from django.views.generic import DeleteView
@method_decorator(csrf_exempt, name='dispatch')
class DeletePageView(DeleteView):
queryset = User.objects.all()
# 或者定义:slug_field
success_url = "/"
DeleteView用途则用于使用post请求删除相关的数据。所以,我这里避开了csrf验证。get请求没什么用。urls.py代码如下:
path("delete/<pk>/", views.DeletePageView.as_view(), name="delete"),
UpdateView
用于更新数据,代码如下:
class UpdatePageView(UpdateView):
form_class = UserForm # 一定要写queryset,不能用form_class代替
queryset = User.objects.all()
template_name = "update.html"
context_object_name = 'one'
success_url = '/'
urls.py代码如下:
path("update/<pk>/", views.UpdatePageView.as_view(), name="update"),