Skip to main content
 首页 » 编程设计

python之如何将其重构为 CBV django

2024年09月07日36shangdawei

我是 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?

请您参考如下方法:

这看起来像一个 ListView ,因此我们可以编写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 <i>name</i> 
        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

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

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

并不是所有的问题都可以用这种基于类的观点来解决,因为我不知道/forwoman等细节。因此你可以将其视为建议如何进一步重构它。