我正在寻找一种有效的Django查询集,以阻止许多攻击我的数据库

时间:2019-04-05 04:35:12

标签: python django python-3.x django-queryset

我正在寻找一种高效的查询集,因为我的代码正试图点燃我的数据库。正如您在下面的代码中看到的那样,这些效率太低。但是我不知道如何通过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)

我需要在该详细信息模板中制作一些图表。 因此,我为每个字段值创建了许多上下文并将其发送到模板。但是由于这些代码,我的数据库正在燃烧。

有什么好主意可以提高效率?

1 个答案:

答案 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')