如何将其重构为CBV django?

时间:2018-09-09 10:42:01

标签: python django refactoring

我是CBV的初学者,可以寻求帮助来重构我的FBV。也许您可以向我展示一些示例或建议。如您所见,我对DRY原理也有疑问。

我的FBV:

def formen(request):
    html = 'man_index.html'
    ip, is_routable = get_client_ip(request)

    if request.user.is_authenticated and request.user.sex == 'M':
        queryset = Post.objects.filter(sex=request.user.sex, is_published=True)

        query = request.GET.get('q')
        if query:
            queryset = queryset.filter(title__icontains=query)


        paginator = Paginator(queryset, 6)
        page = request.GET.get('page')
        try:
            elements = paginator.page(page)
        except PageNotAnInteger:
            elements = paginator.page(1)
        except EmptyPage:
            elements = paginator.page(paginator.num_pages)
        elements = paginator.get_page(page)


        context = {
            'all_posts': elements,
            'page_range' : paginator.page_range,
        }
    elif request.user.is_authenticated and request.user.sex == 'W':
        return redirect('/forwomen')

    else:
        queryset = Post.objects.filter(sex='M', is_published=True)
        query = request.GET.get('q')
        if query:
            queryset = queryset.filter(title__icontains=query)

        paginator = Paginator(queryset, 3)
        page = request.GET.get('page')
        try:
            elements = paginator.page(page)
        except PageNotAnInteger:
            elements = paginator.page(1)
        except EmptyPage:
            elements = paginator.page(paginator.num_pages)
        elements = paginator.get_page(page)

        context = {
            'all_posts': elements,
            'page_range' : paginator.page_range,
        }

    return render(request, html, context)

我应该使用什么方法将其重构为CVB?

1 个答案:

答案 0 :(得分:2)

这看起来像一个列表视图,因此我们可以编写ListView [django-doc]类的子类:

从django.views.generic.list导入ListView

class ForMenView(ListView):
    model = Post
    template_name = 'man_index.html'
    context_object_name = 'all_posts'
    paginate_by = 3

    def get_queryset(self):
        query = request.GET.get('q')
        qs = Post.objects.filter(sex='M', is_published=True)
        if query:
            return qs.filter(title__icontains=query)
        return qs

    def get_paginate_by(self, queryset):
        user = self.request.user
        if user.is_authenticated and user.sex == 'M':
            return 6
        return self.paginate_by

    def dispatch(self, request, *args, **kwargs):
        user = request.user
        if user.is_authenticated and user.sex == 'W':
            return redirect('/forwomen')  # please replace it with the view name
        else:
            return super(ArticleListView, self).dispatch(*args, **kwargs)

    def get_context_data(self, *args, **kwargs):
        kwargs = super(ArticleListView, self).get_context_data(*args, **kwargs)
        kwargs['page_range'] = kwargs['paginator'].page_range
        return kwargs

但是基于函数的视图显示了一些奇怪的东西:

  1. 女性身份验证用户的路径是硬编码的,最好指定视图的名称(或对函数的引用);
  2. 分页取决于用户是否登录的事实是很奇怪的;
  3. 无论如何,对女人有不同的看法是很奇怪的。如果变化很小,最好将其合并为一个视图;
  4. 引用paginator.page_range作为单独的变量是很奇怪的,因为通过使用对分页器本身的引用,可以访问更多属性。

使用这种基于类的视图并不能解决所有问题,因为我不知道/forwoman等的详细信息。因此,您可以将其视为 advice 的重构方法