我是一个新手,试图使用Django创建有关团队参与者的报告,而我所做的事情根本上是错误的,并且花了几个小时试图找出问题所在-该报告仍在影响数据库大约4000次以上下面是我正在做的缩写。
任何帮助,指针或其他资源将非常感谢!
对于团队模型:
class Team(BenchmarkData):
year = models.ForeignKey(Period, on_delete=models.CASCADE, null=True)
sponsor = models.ForeignKey(Person, on_delete=models.CASCADE)
goal = models.ForeignKey(Goal, on_delete=models.CASCADE, null=True)
...other non-relational properties...
def _participation_queryset(self):
from .participation import Participation
pp = Participation.objects.filter(team=self.id)
return pp
@cached_property
def average_points(self):
list_participation = [participation.calculated_yearly_points_per_hour for participation in self._participation_queryset()]
try: return mean(list_participation)
@cached_property
...
对于参与模式:
class Participation(models.Model):
person = models.ForeignKey(Person, on_delete=models.CASCADE, null=True)
team = models.ForeignKey(Team, on_delete=models.CASCADE, null=True)
year = models.ForeignKey(Period, on_delete=models.CASCADE, null=True)
start_date = models.DateField('Began', null=True)
end_date = models.DateField('Left', blank=True, null=True)
active = models.BooleanField('Active?', null=True)
yearly_points = models.FloatField(default=0, null=True)
yearly_hours_of_play = models.FloatField(default=0)
...other non-relational properties...
@cached_property
def calculated_yearly_points_per_hour(self):
try: return self.yearly_points / self.yearly_hours_of_play
except ZeroDivisionError: return 0
...other cached properties...
对于我的观点,我使用了:
class PlanReport(TemplateView):
template_name = 'pension/report/index.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
self.team = get_object_or_404(Plan, id=self.kwargs['team_id'])
self.sponsor = get_object_or_404(Company, id=self.kwargs['sponsor_id'])
self.report = get_object_or_404(Report, id=self.kwargs['plan_id'])
pp = Participation.objects.filter(plan_id=self.plan)
s = pickle.dumps(pp.query)
s2 = pickle.loads(s)
participation_list = s2.model.objects.all()
# Add in other context information
context['team'] = self.team
context['sponsor'] = self.sponsor
context['report'] = self.report
context['participation_list'] = participation_list
return context
报告模板结构为:
index.html
- section1.html
- section2-table-of-group-participants-with-stats-on-each-participant.html
...
该表的模板显示:
...other html...
{% for participation in participation_list %}
<tr>
<td>{{ participation.person }}</td>
<td>{{ participation.team }}</td>
<td>{{ participation.year }}</td>
<td>{{ participation.start_date }}</td>
<td>{{ participation.end_date }}</td>
<td>{{ participation.active }}</td>
<td>{{ participation.yearly_points }}</td>
<td>{{ participation.yearly_hours_of_play }}</td>
<td>{{ participation.calculated_yearly_points_per_hour }}</td>
...other calculated attributes...
</tr>
{% empty %}
</tbody>
</table>
<p>No data imported into the list</p>
{% endfor %}
感谢到目前为止的答复!
@Daniel Roseman:
谢谢。
正如您提到的,我将所有@cached_properies都恢复为@property(我怀疑它们会减慢速度!)
我删除了所有的酱菜材料-我听说有人试图这样做,但并不太了解它的相关性-所以我想它与缓存实际上并没有多大关系-至少在我的情况下。
我还更改了以下内容:
在团队模型中:
def _participation_queryset(self):
from .participation import Participation
return self.participation_set.all()
在create_report视图中:
participation_list = self.team.participation_set.all().select_related('team')
...
context['participation_list'] = participation_list
答案 0 :(得分:0)
您的代码有两个主要的低效率之处。
首先,您已经使用_participation_queryset
方法定义了自己的方法来吸引团队成员。这不仅是不必要的,而且会破坏 Django的内置缓存;每次调用时都会对其进行评估。删除它并参考self.participation_set.all()
。
另一个,也许甚至更重要的一点是,您无需执行任何操作即可为您的任何模型预加载任何相关数据。因此,即使您实际上已经有了团队,对{{ participation.team }}
的每次调用都会导致数据库命中。当您在视图中获取“参与”查询集时,应使用select_related
(应通过对participation_set
的相同调用来完成此操作)。
(而且我不明白您在那儿进行的腌菜转储/装载操作。您到底为什么要这样做?还要注意,没有理由将值分配为实例属性。)
所以您的视图如下:
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
team = get_object_or_404(Plan, id=self.kwargs['team_id'])
sponsor = get_object_or_404(Company, id=self.kwargs['sponsor_id'])
report = get_object_or_404(Report, id=self.kwargs['plan_id'])
participation_list = team.participation_set.all().select_related('team')
...
最后,我不认为您的cached_properties发挥了您的预期作用,并且可能使事情变得更加低效。 calculated_yearly_points_per_hour
之类的东西是两个整数的简单除法,并且计算起来很简单。根本不需要缓存它。删除大部分(如果不是全部)装饰器。