我正在寻找一种高效的查询集,因为我的代码正试图点燃我的数据库。正如您在下面的代码中看到的那样,这些效率太低。但是我不知道如何通过select_related和prefetch_related将它们有效地更改为小行代码。
框架:Django 2.2
------- models.py --------
class ProjectModel(models.Model):
project_name = models.CharField(max_length=100)
start_date = models.DateField(blank=True)
end_date = models.DateField(blank=True)
code = models.CharField(max_length=100, unique=True)
get_pharm = models.ForeignKey(UserProfile, on_delete=models.CASCADE, blank=True, related_name='get_pharm')
get_hospitals = models.ManyToManyField(UserProfile, blank=True)
drugs = models.ForeignKey(DrugModels, on_delete=models.CASCADE, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
status = models.CharField(choices=STATUS, max_length=3, default='on')
class SubjectModel(models.Model):
project = models.ForeignKey(ProjectModel, on_delete=models.CASCADE)
sex = models.CharField(choices=SEX, max_length=1, blank=True)
hospital = models.ForeignKey(UserProfile, on_delete=models.CASCADE)
age = models.CharField(blank=True, max_length=10)
status = models.CharField(choices=STATUS, max_length=3, default='on')
class SubjectDateModel(models.Model):
whose = models.ForeignKey(SubjectModel, on_delete=models.CASCADE)
will_visit_date = models.DateField(blank=True, null=True)
visited_date = models.DateField(blank=True, null=True)
visit_check = models.BooleanField(default=False)
FEELING = (
(1, 'sobad'),
(2, 'bad'),
(3, 'normal'),
(4, 'good'),
(5, 'verygood'),
)
FLAG = (
('device', 'DEVICE'),
('drug', 'DRUG'),
('side', 'SIDEEFFECT'),
('feel', 'FEELING'),
('pain', 'PAIN'),
)
DRUG = (
('yes', 'ATE'),
('no', 'NO'),
)
class DataModel(models.Model):
user_id = models.ForeignKey(SubjectModel, on_delete=models.CASCADE)
beacon_info = models.CharField(max_length=100, blank=True, null=True)
drug = models.CharField(choices=DRUG, max_length=3, blank=True, null=True)
side_effect = models.CharField(max_length=50, blank=True, null=True)
side_effect_more = models.CharField(max_length=255, blank=True, null=True)
feeling = models.PositiveSmallIntegerField(choices=FEELING, blank=True, null=True)
pain = models.PositiveSmallIntegerField(blank=True, null=True)
date = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
flag = models.CharField(choices=FLAG, max_length=6)
------- views.py --------
def subject_detail(request, pk):
details = get_object_or_404(SubjectModel.objects.select_related('hospital__whose').select_related('project'), pk=pk, status='on')
dates = SubjectDateModel.objects.filter(whose=details)
drug_percent = details.project.drugs.when
count = 0
for i in drug_percent:
count = count + 1
# for chart1
date_count = details.project.end_date - details.project.start_date
should_eat = count * date_count.days
real_eat = details.datamodel_set.filter(flag='drug').count()
if real_eat:
percent = round(real_eat / should_eat * 100)
else:
percent = 0
# for bar chart
get_feel_1 = len(details.datamodel_set.filter(feeling=1))
get_feel_2 = len(details.datamodel_set.filter(feeling=2))
get_feel_3 = len(details.datamodel_set.filter(feeling=3))
get_feel_4 = len(details.datamodel_set.filter(feeling=4))
get_feel_5 = len(details.datamodel_set.filter(feeling=5))
# for another bar chart
pain0 = len(details.datamodel_set.filter(flag='pain', pain=0))
pain1 = len(details.datamodel_set.filter(flag='pain', pain=1))
pain2 = len(details.datamodel_set.filter(flag='pain', pain=2))
pain3 = len(details.datamodel_set.filter(flag='pain', pain=3))
pain4 = len(details.datamodel_set.filter(flag='pain', pain=4))
pain5 = len(details.datamodel_set.filter(flag='pain', pain=5))
pain6 = len(details.datamodel_set.filter(flag='pain', pain=6))
pain7 = len(details.datamodel_set.filter(flag='pain', pain=7))
pain8 = len(details.datamodel_set.filter(flag='pain', pain=8))
pain9 = len(details.datamodel_set.filter(flag='pain', pain=9))
pain10 = len(details.datamodel_set.filter(flag='pain', pain=10))
context = {
'details': details,
'dates': dates,
'percent': percent,
'get_feel_1': get_feel_1,
'get_feel_2': get_feel_2,
'get_feel_3': get_feel_3,
'get_feel_4': get_feel_4,
'get_feel_5': get_feel_5,
'pain0': pain0,
'pain1': pain1,
'pain2': pain2,
'pain3': pain3,
'pain4': pain4,
'pain5': pain5,
'pain6': pain6,
'pain7': pain7,
'pain8': pain8,
'pain9': pain9,
'pain10': pain10,
}
return render(request, 'subject_app/subject_detail.html', context)
我需要在该详细信息模板中制作一些图表。 因此,我为每个字段值创建了许多上下文并将其发送到模板。但是由于这些代码,我的数据库正在燃烧。
有什么好主意可以提高效率?
答案 0 :(得分:1)
也许您可以使用Conditional Aggregation这样尝试:
from django.db.models import Count, Case, When, IntegerField
pains = details.datamodel_set.annotate(
pain0=Count(Case(
When(pain=0, then=1),
output_field=IntegerField(),
))
).annotate(
pain1=Count(Case(
When(pain=1, then=1),
output_field=IntegerField(),
))
) # and so on
pains.values('pain0', 'pain1')