如何提高Django / Python的处理速度

时间:2019-06-02 13:04:25

标签: python django python-2.x

我需要提高这段代码的处理速度:

    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'

问题在于它可以访问许多表,并且这些表并不总是在外键上链接,而是通过提供一个引用其他模型中的记录的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')

1 个答案:

答案 0 :(得分:1)

这将我正在处理的示例数据的时间减少了4

for f in score_forms: #and ensure each score is at least 0
            insts = Instrument_Forms.objects.filter(instrument=study_obj.instrument, scoring_category__in=f.category.split(';'))
            insts_IDs = []
            for inst in insts: insts_IDs.append(inst.itemID)
            if f.kind == 'count' : 
                scoring_dict[f.title] = administration_data.objects.filter(administration_id=administration_id, value__in=f.measure.split(';'), item_ID__in=insts_IDs).count()
            else : 
                items = administration_data.objects.filter(administration_id=administration_id, item_ID__in=insts_IDs)
                scoring_dict[f.title] = ''
                for item in items :
                    scoring_dict[f.title] +=  item.value + '\n'