You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Django CBV中遵循DRY原则:同模型不同过滤视图如何复用代码

解决方案

你可以通过抽象公共父类的方式消除所有重复代码,把公共逻辑封装到基础视图中,仅将可变参数做成可配置的类属性即可。

方法1:抽象公共基类(扩展性强,推荐)

优化后views.py代码

from django.views.generic import ListView
from django.contrib.auth.mixins import LoginRequiredMixin
from .models import Block

# 封装所有公共逻辑的基础视图
class BaseBlockListView(LoginRequiredMixin, ListView):
    # 固定公共属性直接写在基类
    template_name = 'blocks/blockslist.html'
    model = Block
    # 可变配置项,子类仅需要修改这几个参数即可
    page = None
    filter_status = None
    page_title = None

    def get_queryset(self):
        # 直接调用父类查询方法,结合配置的状态过滤
        return super().get_queryset().filter(
            user=self.request.user,
            status=self.filter_status
        )

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        # 动态注入公共上下文变量
        context['page'] = self.page
        context['page_title'] = self.page_title
        return context

# 子类仅需要配置差异化参数,无任何重复逻辑
class AcceptedBlockView(BaseBlockListView):
    page = 'acceptedblock'
    filter_status = 'Accepted'
    page_title = '已接收区块'

class CompletedBlockView(BaseBlockListView):
    page = 'completedblock'
    filter_status = 'Completed'
    page_title = '已完成区块'

方法2:直接在URL配置传参(更简洁,适合简单场景)

如果不需要给子类加额外逻辑,甚至可以不用定义多个视图类,直接在urls.py中通过as_view传递配置参数:

from django.urls import path
from .views import BaseBlockListView

urlpatterns = [
    path('accepted/', BaseBlockListView.as_view(
        page='acceptedblock',
        filter_status='Accepted',
        page_title='已接收区块'
    ), name='acceptedblock'),
    path('completed/', BaseBlockListView.as_view(
        page='completedblock',
        filter_status='Completed',
        page_title='已完成区块'
    ), name='completedblock'),
    # 后续新增其他状态的列表页,只需要加一行URL配置即可,无需修改views代码
]

可选优化:简化HTML模板

可以把页面标题做成变量传入,去掉模板里的硬编码判断,让模板更通用:

<h2>{{ page_title }}</h2>
<table>
    <thead class="thed-dark">
        <tr>
            <th>#</th>
            <th>Title</th>
            <th>Update Block</th>
            <th>Status</th>
            <th>User</th>
        </tr>
    </thead>
    <tbody>
        {% for instance in object_list %}
        <tr>
            <td>{{ forloop.counter }}</td>
            <td>{{ instance.title }}</td>
            <td><a href="{% url 'updateblock' instance.id %}">Update</a></td>
            <td>{{ instance.status }}</td>
            <td>{{ instance.user }}</td>
        </tr>
        {% endfor %}
    </tbody>
</table>
<p>点击查看 <a href="{% url 'allblocks' %}">所有区块</a></p>
<p>点击查看 <a href="{% url 'acceptedblock' %}">已接收区块</a></p>
</div>

内容的提问来源于stack exchange,提问作者Visionary

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 04:06:04