类的继承
ListView处理的都是多个对象
DeleteView处理的都是单个对象
自定义类试图
继承自
LoginRequiredMixin
、AuthorRequireMixin
、DeleteView
自定义一些参数
class NewsDeleteView(LoginRequiredMixin, AuthorRequireMixin, DeleteView):
model = News
template_name = "news/news_confirm_delete.html"
# slug_url_kwarg = "slug" # 通过url,传入要删除的对象主键ID,默认值是slug
# pk_url_kwarg = "PK" # 通过url,传入要删除的对象逐主键ID, 默认值是pk
success_url = reverse_lazy("news:list") # 在项目URLConf未加载前使用
DeleteView的多继承
继承自
SingleObjectTemplateResponseMixin
、BaseDeleteView
class DeleteView(SingleObjectTemplateResponseMixin, BaseDeleteView):
template_name_suffix = '_confirm_delete'
BaseDeleteView
继承自
DeletionMixin
、BaseDetailView
class BaseDeleteView(DeletionMixin, BaseDetailView):
"""
Base view for deleting an object.
Using this base class requires subclassing to provide a response mixin.
"""
...
BaseDetailView
继承自
SingleObjectMixin
、View
class BaseDetailView(SingleObjectMixin, View):
"""
先展示当前我们要操作的对象
同时也是DetailView的父类 ==> 处理的也是 单个对象
"""
def get(self, request, *args, **kwargs):
self.object = self.get_object() # 获取要展示的对象
context = self.get_context_data(object=self.object) # 将获取到的对象放到上下文里面
return self.render_to_response(context) # 返回上下文
View
class View:
http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']
...
SingleObjectMixin
继承自
ContextMixin
class SingleObjectMixin(ContextMixin):
"""
Provide the ability to retrieve a single object for further manipulation.
"""
model = None
queryset = None
slug_field = 'slug'
context_object_name = None
slug_url_kwarg = 'slug' # 通过url,传入要删除的对象主键ID,默认值是slug
pk_url_kwarg = 'pk' # 通过url,传入要删除的对象逐主键ID, 默认值是pk
query_pk_and_slug = False
def get_object(self, queryset=None):
"""返回当前要操作的对象"""
if queryset is None:
# 先判断查询集是否为空,没有自定义的时候就是None
queryset = self.get_queryset()
# 使用pk或者是slug来过滤查询集
pk = self.kwargs.get(self.pk_url_kwarg)
slug = self.kwargs.get(self.slug_url_kwarg)
if pk is not None:
queryset = queryset.filter(pk=pk)
# Next, try looking up by slug.
if slug is not None and (pk is None or self.query_pk_and_slug):
slug_field = self.get_slug_field()
queryset = queryset.filter(**{slug_field: slug})
# 如果没有pk,也没有slug,则报错,无法查询到要操作的数据
# If none of those are defined, it's an error.
if pk is None and slug is None:
raise AttributeError(
"Generic detail view %s must be called with either "
"an object pk or a slug in the URLconf." % self.__class__.__name__)
# 将filter中的多个对象,通过get变成单个对象, 最后直接返回我们要操作的对象
try:
obj = queryset.get()
except queryset.model.DoesNotExist:
raise Http404(_("No %(verbose_name)s found matching the query") %
{'verbose_name': queryset.model._meta.verbose_name})
return obj
def get_queryset(self):
"""返回queryset"""
if self.queryset is None: # 如果没有重写queryset,则self.queryset为None
if self.model: # 查看我们设置的关联模型类
return self.model._default_manager.all() # 返回指定的模型类中的所有对象
else: # 没有设置关联模型类,则报错
raise ImproperlyConfigured(
"%(cls)s is missing a QuerySet. Define "
"%(cls)s.model, %(cls)s.queryset, or override "
"%(cls)s.get_queryset()." % {'cls': self.__class__.__name__}
)
return self.queryset.all() # 如果设置了queryset,直接返回queryset中的所有对象
def get_slug_field(self):
return self.slug_field
def get_context_object_name(self, obj):
"""
Get the name to use for the object.
这里和ListView中的一样
"""
if self.context_object_name:
# 如果自定义了,则直接返回
return self.context_object_name
# 如果没有自定义,就判断是不是关联模型类的属性
elif isinstance(obj, models.Model):
# 是,则返回这个属性的名称
return obj._meta.model_name
else:
# 不是,则返回None
return None
def get_context_data(self, **kwargs):
"""Insert the single object into the context dict."""
context = {}
if self.object:
context['object'] = self.object # 先定义一个key:object
context_object_name = self.get_context_object_name(self.object)
if context_object_name:
# 如果context_object_name存在,则使用这个上下文的名字
context[context_object_name] = self.object
context.update(kwargs) # 更新字典
return super().get_context_data(**context) # 重载父类方法,返回数据
ContextMixin
class ContextMixin:
"""
A default context mixin that passes the keyword arguments received by
get_context_data() as the template context.
"""
extra_context = None
def get_context_data(self, **kwargs):
kwargs.setdefault('view', self)
if self.extra_context is not None:
kwargs.update(self.extra_context)
return kwargs
DeletionMixin
class DeletionMixin:
"""提供删除对象的功能"""
success_url = None # 定义success_url
def delete(self, request, *args, **kwargs):
"""删除对象"""
self.object = self.get_object() # 要删除的对象
success_url = self.get_success_url() # 要跳转的URL
self.object.delete() # 执行删除操作
return HttpResponseRedirect(success_url) # 跳转到对应的URL下
# Add support for browsers which only accept GET and POST for now.
def post(self, request, *args, **kwargs):
"""
给只支持get/post请求的浏览器使用
但其实调用的还是上面的delete()
"""
return self.delete(request, *args, **kwargs)
def get_success_url(self):
"""处理需要跳转的URL"""
# 判断是否自定义了success_url
if self.success_url:
# 有,则跳转到只当的url下
return self.success_url.format(**self.object.__dict__)
else:
# 没有,直接报错
raise ImproperlyConfigured("No URL to redirect to. Provide a success_url.")
SingleObjectTemplate…
继承自
TemplateResponseMixin
class SingleObjectTemplateResponseMixin(TemplateResponseMixin):
template_name_field = None
template_name_suffix = '_detail'
def get_template_names(self):
"""
获取模板的名称
"""
TemplateResponseMixin
主要都是针对前端模板文件,很少修改
只有一个template_name
可能回修改,就不再赘述了
AuthorRequireMixin
继承自
View
,重写dispatch()
方法
class AuthorRequireMixin(View):
"""验证是否为原作者,用于状态删除、文章编辑"""
def dispatch(self, request, *args, **kwargs):
# 状态和文章实例有user属性
if self.get_object().user.username != self.request.user.username:
raise PermissionDenied # 请求不允许
return super().dispatch(request, *args, **kwargs)
View
class View:
http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']
def dispatch(self, request, *args, **kwargs):
if request.method.lower() in self.http_method_names:
handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
else:
handler = self.http_method_not_allowed
return handler(request, *args, **kwargs)
LoginRequiredMixin
继承自
AccessMixin
class LoginRequiredMixin(AccessMixin):
"""Verify that the current user is authenticated."""
def dispatch(self, request, *args, **kwargs):
if not request.user.is_authenticated:
return self.handle_no_permission()
return super().dispatch(request, *args, **kwargs)
评论区