【发布时间】:2019-10-18 07:09:56
【问题描述】:
我需要提高这段代码的处理速度:
score_forms = InstrumentScore.objects.filter(instrument=study_obj.instrument)
for administration_data_item in administration_data.objects.filter(administration_id=administration_id):
inst = Instrument_Forms.objects.get(instrument=study_obj.instrument,itemID=administration_data_item.item_ID)
scoring_category = inst.scoring_category if inst.scoring_category else inst.item_type
for f in score_forms: #items can be counted under multiple Titles check category against all categories
if f.kind == "count" :
if scoring_category in f.category.split(';'):
if administration_data_item.value in f.measure.split(';'): #and check all values to see if we increment
scoring_dict[f.title] += 1
else :
if scoring_category in f.category.split(';'):
scoring_dict[f.title] += administration_data_item.value + '\n'
问题在于它访问许多表,并且这些表并不总是链接到 ForeignKey,而是通过提供引用另一个模型中的记录的 CharField 来链接它们。如何在不更改数据库结构的情况下改进此处理?
型号
class administration_data(models.Model):
administration = models.ForeignKey("administration") # Associated administration
item_ID = models.CharField(max_length = 101) # ID associated for each CDI item
value = models.CharField(max_length=200) # Response given by participant to this particular item
class Meta:
unique_together = ('administration', 'item_ID') # Each administation_data object must have a unique combination of administration ID and item ID.
def __unicode__(self):
return '%s %s' % (self.administration, self.item_ID)
class Instrument_Forms(models.Model):
instrument = models.ForeignKey('researcher_UI.instrument', db_index=True)
itemID = models.CharField(max_length = 101, db_index=True) # ID number for identification
item = models.CharField(max_length = 101) # string variable name
item_type = models.CharField(max_length = 101) # type of variable (word, phrase, etc.)
category = models.CharField(max_length = 101) # if word, the subcategory for item (animals, sounds, etc.)
choices = models.ForeignKey('Choices', null=True, on_delete=models.deletion.PROTECT)
definition = models.CharField(max_length = 1001, null=True, blank=True) # item listed in plaintext. This is what is displayed to test-takers along with possible choices
gloss = models.CharField(max_length = 1001, null=True, blank=True) # English translation for item. At the moment, we only have English instruments so definition and gloss are identical
complexity_category = models.CharField(max_length = 101, null=True, blank=True) # category for complexity item. Currently blank.
uni_lemma = models.CharField(max_length= 101, null=True, blank=True) # ID for matching terms across languages. Currently unused.
item_order = models.IntegerField(validators=[MinValueValidator(1)])
scoring_category = models.CharField(max_length = 101, null=True, blank=True) # used to provide scoring granulatity - uses item_type if blank
def __unicode__(self):
return "%s (%s, %s)" % (self.definition, self.instrument.verbose_name, self.itemID)
class Meta:
unique_together = ('instrument', 'itemID') # Each instrument in the database must have a unique combination of instrument and itemID
class InstrumentScore(models.Model):
'''
Class to store the instrument scoring mechanisms loaded from json files held in
/cdi_forms/form_data/scoring/
'''
instrument = models.ForeignKey(instrument, on_delete=models.CASCADE)
title = models.CharField(max_length=101)
category = models.CharField(max_length=101)
measure = models.CharField(max_length=101)
order = models.IntegerField(default=999)
kind = models.CharField(max_length=5, default="count", choices=KIND_OPTIONS)
def __unicode__(self):
return '%s: %s' % (self.instrument, self.title)
class Meta:
ordering = ['instrument', 'order']
class instrument(models.Model):
name = models.CharField(max_length = 51, primary_key=True) # Instrument short name
verbose_name = models.CharField(max_length = 51, blank = True) # Instrument official title
language = models.CharField(max_length = 51) # Instrument's language. For 'English Words & Sentences' this would be 'English'
form = models.CharField(max_length = 51) # Instrument's form type abbreviation. For 'English Words & Sentences' this would be 'WS'
min_age = models.IntegerField(verbose_name = "Minimum age") # Minimum age in months that instrument was built for
max_age = models.IntegerField(verbose_name = "Maximum age") # Maximum age in months that instrument was built for
def __unicode__(self):
return "%s (%s %s)" % (self.verbose_name, self.language, self.form)
def __str__(self):
return unicode(self).encode('utf-8')
class Meta:
unique_together = ('language', 'form') # Each instrument in the database must have a unique combination of language and form type
class study(models.Model):
researcher = models.ForeignKey("auth.user") # Researcher's name
name = models.CharField(max_length = 51) # Study name
instrument = models.ForeignKey("instrument") # Instrument associated with study
waiver = models.TextField(blank = True) # IRB Waiver of documentation for study or any additional instructions provided to participant
study_group = models.CharField(max_length = 51, blank = True) # Study group
anon_collection = models.BooleanField(default=False) # Whether participants in study will all be anonymous
subject_cap = models.IntegerField(blank = True, null=True) # Subject cap to limit number of completed administrations
confirm_completion = models.BooleanField(default=False) # Whether to have participant confirm child's age and that test was completed to best of ability at end of study
allow_payment = models.BooleanField(default=False) # Whether to reward participants with gift card codes upon completion
allow_sharing = models.BooleanField(default=False) # Whether to allow participants to share results via Facebook
test_period = models.IntegerField(default=14, validators = [MinValueValidator(1), MaxValueValidator(28)]) # Number of days after test creation that a participant may work on and complete administration
prefilled_data = models.IntegerField(default=0)
min_age = models.IntegerField(verbose_name = "Minimum age", blank = True, null=True) # Minimum age in months for study
max_age = models.IntegerField(verbose_name = "Maximum age", blank = True, null=True) # Maximum age in months for study
birth_weight_units = models.CharField(max_length = 5, default="lb")
show_feedback = models.BooleanField(default=True)
active = models.BooleanField(default=True)
def __unicode__(self):
return self.name
def __str__(self):
return unicode(self).encode('utf-8')
【问题讨论】:
-
创建minimal reproducible example 并具体说明。这里的任何人都不太可能花时间分析和分析您的代码。您究竟想在哪里加速您的代码?看起来您的第一个代码块可能会被单个数据库查询替换。但为什么它首先以这种方式实施呢?例如,为什么不直接使用外键?
-
我不知道为什么最初没有使用外键,但它没有
-
发生了。 :) 但是由于我们也不知道这一点,因此提出适当的解决方案变得更加困难。在我看来这里的逻辑过于复杂并且是重构的候选者。如果这不是一个选项,我也会考虑只用原始 SQL 编写查询。 docs.djangoproject.com/en/2.2/topics/db/sql。它肯定会比当前的解决方案更快。
标签: python django python-2.x