如何避免在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})
问题原因
- 实例方法误用为类方法:
moderator_checker是实例方法(带self参数),但调用时直接用Server.moderator_checker(request.user),会把request.user当作self传入,参数匹配错误。 - 无效的
self.tag引用:调用类方法时没有Server实例,self不存在,self.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') @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
相关产品推荐
相关产品推荐

