python - 与普通的基于函数的视图相比,ListView 的优缺点是什么,反之亦然?(姜戈)
问题描述
更具体地说,一个比另一个更可取吗?我知道扩展 ListView 的视图可能有更多可读的代码(而且更少),但即便如此,基于函数的视图通常可以用两行代码编写,其中包含所有内容,包括模板和传递的数据进入模板。各有什么好处?
解决方案
我认为这个问题是指两种不同的编程风格/图表,功能和 OOP。
作为一般 OOP 思想,在 Django 中使用基于类的视图的最佳部分是您可以从其他类继承(和多重继承),这使您的视图更加广泛,并且可在代码上重用。
例如,您有一系列views
需要在主进程块之前进行一些数据完整性检查的class-based view
样式,您可以将这些数据检查代码写入自定义mixin
的用于多继承的.
# mixins.py
# inherit from login required mixin and add data integrity check
class PostDataCheckMixin(LoginRequiredMixin):
def dispatch(self, request, *args, **kwargs):
try:
data = json.loads(request.body.decode())
except:
return JsonResponse({'res': 0, 'errmsg': 'Invalid data'})
return super().dispatch(request, *args, **kwargs)
# views.py
class OrderProcessView(PostDataCheckMixin, View):
def post(self, request, *args, **kwargs):
# ...
class OrderPaymentView(PostDataCheckMixin, View):
def post(self, request, *args, **kwargs):
# ...
这里想具体提另一个例子ListView
。如您所知,默认情况下内置ListView
提供pagination
,您可能会看到如下内容:
class ProductListView(ListView):
model = ProductSKU
context_object_name = 'products'
template_name = 'shop/product-list.html'
paginate_by = 3
paginate_orphans = 1
然后神奇地在您的 Html 模板中,您得到了一些上下文变量,例如page_obj
,paginator
和is_paginated
,例如:
<!-- PAGINATION-->
{% if is_paginated %}
<nav aria-label="Page navigation">
<ul class="pagination justify-content-center justify-content-lg-end">
{% if page_obj.has_previous %}
<!--...-->
{% endif %}
{% for num in paginator.page_range %}
<li class="page-item {% if page_obj.number == num %} active {% endif %}">
<a class="page-link" href="{% qs_url 'page' num request.GET.urlencode %}">{{ num }}</a>
</li>
{% endfor %}
{% if page_obj.has_next %}
<!--...-->
{% endif %}
</ul>
</nav>
{% endif %}
到底他妈发生了什么?如果您检查源代码,那么您将意识到它们在一个get_context_data
方法中,该方法将准备将它们context variables
传递到您的模板中。此外,您可以通过继承轻松扩展要传递到模板中的内容,例如:
class ProductListView(ListView):
# ...
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
# at this moment your 'context' variable already contains 'page_obj', 'paginator' etc.
category_slug = self.kwargs.get('category_slug')
if category_slug:
category = category_slug.replace('-', ' ')
context['category'] = category
# here you add a new context variable 'category'
return context
想象一下,如果您需要编写一个函数来提供此分页器功能,当然,更多地了解Paginator
对象及其方法将是一个好习惯,但您仍在某种程度上重建轮子。
基于类的视图的难点太抽象了,这让包括我在内的很多人一开始就很困扰,你不知道为什么代码这么短,幕后发生了什么。
这需要你阅读那些内置通用视图的源代码,一开始可能很难。一旦你习惯了它,你不仅会理解它是如何工作的,而且还可以用你自己的方式重写和扩展它。
函数式编程更直观、更直接,你不必担心那些决定行为的不可见的抽象部分,你可以设计一个视图函数,让一切尽在掌握。
缺点很明显,你不能重用那些内置的基于类的视图,它们有很多不错的功能和特性。这些将减少你在一个巨大的函数中编写所有内容的时间。
我知道关于这个话题有很多争议和个人偏好,我个人建议尝试学习基于类的观点。随着项目的增长,使您的代码可重用将非常有帮助,有时甚至可以挽救生命。并且我相信,当您将来学习其他语言或框架时,这种经验将成为您的宝贵财富。
推荐阅读
- sql - 协助:ORA-00907:缺少右括号
- c - 从子 COM 对象获取父 COM 对象
- mongodb - 通过 for 循环或 foreach 保存在 mobgodb 模式中,每个项目确实节省了不止一次
- symfony - API平台和Symfony,多个实体管理器和一些api操作的动态连接问题
- c# - 如何在C#中调用另一个类的私有方法
- android - 构建命令失败。使用参数执行进程 C:\Users\user\AppData\Local\Android\Sdk\ndk\21.0.6113669\ndk-build.cmd 时出错
- flutter - 我在颤振http中需要帮助,但我不知道我在做什么
- elasticsearch - 带有弹性搜索数据库的 CubeJS 仪表板
- angular - 除非数据已更改,否则防止角度组件重新渲染
- ios - 无法在设备“watchOS 7.4 (18T187) 上安装应用程序”