Django3.1:如何通过类视图实现按钮点击设置最佳答案?
用Django类视图实现“设置最佳答案”功能
当然可以用类视图替代你的函数视图,Django的通用类视图能让代码更简洁、更贴合模型操作的规范,这里给你两种适配Django3.1的最优实现方案:
方案一:使用UpdateView(推荐,贴合模型更新场景)
UpdateView是Django专门用于更新模型实例的通用类视图,非常适合你这种仅修改单个字段的场景,还能轻松集成权限验证逻辑:
1. 编写类视图
from django.views.generic.edit import UpdateView from django.contrib.auth.mixins import UserPassesTestMixin from .models import Answer class SetBestAnswerView(UserPassesTestMixin, UpdateView): model = Answer fields = ['is_best_answer'] # 指定需要更新的字段 def form_valid(self, form): # 直接将字段设为True,无需渲染表单让用户输入 form.instance.is_best_answer = True # 也可以直接调用你原有的set_best_answer方法: # form.instance.set_best_answer() return super().form_valid(form) def get_success_url(self): # 操作成功后跳回对应问题的详情页,和你原有的逻辑一致 return self.object.question.get_absolute_url() def test_func(self): # 权限验证:仅允许提问者设置最佳答案(可根据需求调整) answer = self.get_object() return self.request.user == answer.question.author
2. URL配置
替换原来的函数视图路由,改成类视图的调用方式:
from django.urls import path from .views import SetBestAnswerView urlpatterns = [ # ... 其他URL配置 path('answer/<int:pk>/best-answer/', SetBestAnswerView.as_view(), name='select'), ]
方案二:使用RedirectView(轻量无表单场景)
如果不需要表单渲染,只需要做简单的状态更新+跳转,RedirectView是更轻量的选择:
1. 编写类视图
from django.views.generic.base import RedirectView from django.contrib.auth.mixins import UserPassesTestMixin from .models import Answer class SetBestAnswerRedirectView(UserPassesTestMixin, RedirectView): permanent = False # 使用临时重定向 def get_redirect_url(self, *args, **kwargs): pk = kwargs.get('pk') answer = Answer.objects.get(pk=pk) # 调用你原有的方法完成最佳答案设置 answer.set_best_answer() # 跳回问题详情页 return answer.get_absolute_url() def test_func(self): # 同样添加权限验证逻辑 answer = Answer.objects.get(pk=self.kwargs.get('pk')) return self.request.user == answer.question.author
2. URL配置
path('answer/<int:pk>/best-answer/', SetBestAnswerRedirectView.as_view(), name='select'),
额外优化建议
- 权限控制:上面的
UserPassesTestMixin确保只有有权限的用户(比如提问者)才能设置最佳答案,你可以根据业务需求修改test_func的判断条件; - 避免多最佳答案:如果一个问题只能有一个最佳答案,建议在
set_best_answer方法中先取消该问题下其他答案的最佳状态:def set_best_answer(self): # 先重置该问题下所有最佳答案 self.question.answers.filter(is_best_answer=True).update(is_best_answer=False) self.is_best_answer = True self.save() - 模板复用:你原有的模板跳转链接
{% url 'select' answer.id %}无需修改,可直接适配两种类视图方案。
内容的提问来源于stack exchange,提问作者spotnag
相关产品推荐
相关产品推荐

