我对Django比较新,所以我不确定我能问的是什么。
我正在建立一个网站,其功能可以评估用户并撰写评论。我有用户模型(具有平均评分字段)和评论模型(包含author
,user_profile
,grade
和review
字段。我正在使用CreateView
进行评论。
我正在尝试执行以下操作:
进行查询以获取该人的所有以前成绩(来自Reviews
模型)。
进行计算(将所有以前的成绩相加,添加新成绩以及所有除以成绩的数量(包括新成绩))
将新的平均成绩保存到UserProfile
型号
将评论保存到Reviews
模型
将用户重定向到当前详细信息视图
Models.py
class UserProfile(models.Model):
...
avg_grade = models.FloatField(blank=True, null=True)
...
class Reviews(models.Model):
user_profile = models.ForeignKey(UserProfile, on_delete=models.CASCADE)
grade = models.PositiveIntegerField()
review = models.CharField(max_length=256, null=True, blank=True)
author = models.CharField(max_length=256)
在views.py
我设法查询该用户的成绩,但不确定在哪里计算新的平均成绩(如果在基于类的视图中可以这样做):
class CreateReview(LoginRequiredMixin, CreateView):
form_class = Forma_recenzije
success_url = reverse_lazy('detail')
template_name = 'accounts/recenzija.html'
def get_queryset(self):
u = UserProfile.objects.get(id=int(self.kwargs['pk']))
return Reviews.objects.filter(user_profile=u)
def form_valid(self, form):
form.instance.author = self.request.user
form.instance.user_profile = UserProfile.objects.get(id=int(self.kwargs['pk']))
return super(CreateReview, self).form_valid(form)
urlpatterns的:
[...
url(r'^dadilje/(?P<pk>[-\w]+)/$', views.DadiljaDetailView.as_view(), name="detail"),
url(r'^dadilje/(?P<pk>[-\w]+)/recenzija$', views. CreateReview.as_view(), name="recenzije")
...
]
答案 0 :(得分:1)
在您返回回复之前,您可以在调用super()
后计算新的平均值。
def form_valid(self, form):
form.instance.author = self.request.user
user_profile = UserProfile.objects.get(id=int(self.kwargs['pk']))
form.instance.user_profile = user_profile`
response = super(CreateReview, self).form_valid(form)
avg_grade = Review.objects.filter(user_profile=user_profile).aggregate(Avg('grade'))['grade__avg']
user_profile.avg_grade = avg_grade
user_profile.save()
return response
或者,如果您发现调用super()
使得很难看到正在发生的事情,您可以明确保存表单并重定向:
def form_valid(self, form):
form.instance.author = self.request.user
user_profile = UserProfile.objects.get(id=int(self.kwargs['pk']))
form.instance.user_profile = user_profile`
review = form.save()
avg_grade = Review.objects.filter(user_profile=user_profile).aggregate(Avg('grade'))['grade__avg']
user_profile.avg_grade = avg_grade
user_profile.save()
return HttpResponseRedirect(self.success_url)
请注意,您可能不必将avg_grade
存储在用户个人资料中 - 您可以使用annotate
在需要时计算平均值。
答案 1 :(得分:1)
对于你想要做的事情,Django有你可以听的信号。
例如,您可以使用一个函数来监听保存UserProfile
的时间,该函数会清除与该配置文件相关的缓存键。
这些功能通常会在您的应用中添加到signals.py
,或者在您定义模型后添加到models.py
文件中。
必须在模型之后加载信号,因此,如果使用signals.py
,我倾向于使用apps.py
;
class MyAppConfig(AppConfig):
"""App config for the members app. """
name = 'my app'
verbose_name = _("My App")
def ready(self):
""" Import signals once the app is ready """
# pylint: disable=W0612
import myapp.signals # noqa
以下是信号接收器的示例,pre_save
恰好在保存对象之前发生,因此您可以在此时运行计算结果;
@receiver(pre_save, sender=UserProfile)
def userprofile_pre_save(sender, instance, **kwargs):
"""
Calc avg score
"""
reviews = Reviews.objects.filter(user_profile=instance).aggregate(Avg('grade'))
instance.avg_grade = reviews['grade_avg']
您可能希望您的接收器处于Review
更改,但以上是一个简单的示例!!
如果你是django的新手,这可能有点复杂,但请阅读; https://simpleisbetterthancomplex.com/tutorial/2016/07/28/how-to-create-django-signals.html
答案 2 :(得分:0)
我认为这里的最佳解决方案是使用django signals
结果你分开了视图和域逻辑,你的计算将在每次更改后应用(不仅仅是视图中的更改)
此外,如果您的计算需要花费大量时间,您可以轻松地在异步作业中移动此功能(例如celery)