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

如何避免在Django多个类视图中重复代码段?我的模型方法尝试失效

Django 视图重复代码复用问题及解决方法

问题场景

在多个Django类视图中重复使用以下两行代码,尝试通过Server模型的实例方法复用逻辑,但实现后无法正常工作:

moderator = ServerModerator.objects.get(user=request.user)
server = Server.objects.get(Q(creator=request.user) | Q(moderators=moderator), Q(tag=server_tag))

原实现代码

models.py

class Server(models.Model):
    ...
    creator = models.ForeignKey(User , on_delete=models.CASCADE, related_name='user_servers')
    moderators = models.ManyToManyField('ServerModerator', related_name='server')

    def moderator_checker(self, current_user):
        moderator = ServerModerator.objects.get(user=current_user)
        server = Server.objects.get(Q(creator=current_user) | Q(moderators=moderator),Q(tag=self.tag))
        return server

views.py

class TagsAndFlairsView(LoginRequiredMixin, View):
form_class = CreatePostTagForm
form_class_2 = CreateUserTagForm

def get(self, request, server_tag):
    ...
    # 注释掉的原重复代码
    # moderator = ServerModerator.objects.get(user=request.user)
    # server = Server.objects.get(Q(creator=request.user) | Q(moderators=moderator), Q(tag=server_tag))
    check = Server.moderator_checker(request.user)
    server_post_tags = check.post_tags.all()
    server_user_tags = check.user_tags.all()
    return render(request, 'servers/tags-flairs.html', {"server":check, "server_post_tags":server_post_tags, "server_user_tags":server_user_tags, "create_post_tag_form":create_post_tag_form, "create_user_tag_form":create_user_tag_form})

问题原因

  1. 实例方法误用为类方法:moderator_checker是实例方法(带self参数),但调用时直接用Server.moderator_checker(request.user),会把request.user当作self传入,参数匹配错误。
  2. 无效的self.tag引用:调用类方法时没有Server实例,self不存在,self.tag会抛出属性错误。
  3. 缺少必要参数:查询需要server_tag条件,但原方法未接收该参数。

修正方案

将模型方法改为类方法,补充必要参数并完善异常处理:

修正后的models.py

class Server(models.Model):
    ...
    creator = models.ForeignKey(User, on_delete=models.CASCADE, related_name='user_servers')
    moderators = models.ManyToManyField('ServerModerator', related_name='server')

    @classmethod
    def get_moderated_server(cls, current_user, server_tag):
        try:
            # 获取当前用户对应的 moderator 实例
            moderator = ServerModerator.objects.get(user=current_user)
            # 查询符合条件的服务器
            return cls.objects.get(
                Q(creator=current_user) | Q(moderators=moderator),
                Q(tag=server_tag)
            )
        except (ServerModerator.DoesNotExist, Server.DoesNotExist):
            # 根据业务需求抛出异常或返回None,这里示例抛出值错误
            raise ValueError("用户无权限访问该服务器或服务器不存在")

修正后的views.py调用

class TagsAndFlairsView(LoginRequiredMixin, View):
    form_class = CreatePostTagForm
    form_class_2 = CreateUserTagForm

    def get(self, request, server_tag):
        ...
        try:
            # 调用类方法获取服务器实例
            server = Server.get_moderated_server(request.user, server_tag)
        except ValueError as e:
            # 处理异常,示例返回403禁止访问
            return HttpResponseForbidden(str(e))
        
        server_post_tags = server.post_tags.all()
        server_user_tags = server.user_tags.all()
        return render(request, 'servers/tags-flairs.html', {
            "server": server, 
            "server_post_tags": server_post_tags, 
            "server_user_tags": server_user_tags, 
            "create_post_tag_form": create_post_tag_form, 
            "create_user_tag_form": create_user_tag_form
        })

关键优化点

  • 使用@classmethod装饰器,将方法转为类级别,无需实例化即可调用。
  • 方法名改为get_moderated_server,语义更清晰,明确其作用是获取用户有权限管理的服务器。
  • 接收server_tag参数,补全查询所需条件。
  • 增加异常捕获,避免get()方法抛出的DoesNotExist异常导致程序崩溃,可根据业务需求调整异常处理逻辑(如返回404页面、403响应等)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 09:27:38