Django中的ModelForms,底层模型依赖于另一个模型(通过OneToOneField)

我的Django应用程序中有两个模型,用于存储用于某些同源搜索程序的搜索参数:

# models.py
class Search(models.Model):
    """A class to represent search runs."""

    program = models.CharField(max_length=20)
    results_file = models.FileField(
        upload_to=(SEARCH_RESULTS_DIR)
    )
    timestamp = models.DateTimeField()

    def __unicode__(self):
        return u'%s %s' % (self.program, self.timestamp)


class FastaRun(models.Model):

    search = models.OneToOneField('Search', primary_key=True)
    # the user-input FASTA formatted protein sequence
    query_seq = models.TextField()
    # -b "Number of sequence scores to be shown on output."
    number_sequences = models.PositiveIntegerField(blank=True)
    # -E "Limit the number of scores and alignments shown based on the
    # expected number of scores." Overrides the expectation value.
    highest_e_value = models.FloatField(default=10.0,
            blank=True)
    # -F "Limit the number of scores and alignments shown based on the
    # expected number of scores." Sets the highest E-value shown.
    lowest_e_value = models.FloatField(blank=True)
    mfoptions = [
            ('P250', 'PAM250'),
            ('P120', 'PAM120'),
            ('BL50', 'BLOSUM50'),
            ('BL62', 'BLOSUM62'),
            ('BL80', 'BLOSUM80')
    ]
    matrix_file = models.CharField(
            max_length=4,
            choices=mfoptions,
            default='BL50'
    )
    database_option = models.CharField(
            max_length=25,
            choices=BLAST_DBS,
            default=INITIAL_DB_CHOICE
    )
    ktupoptions = [(1, 1), (2, 2)]
    ktup = models.PositiveIntegerField(
            choices=ktupoptions,
            default=2,
            blank=True
    )

请注意,FastaRun是一种搜索. FastaRun扩展了搜索,因为为FastaRun定义了更多参数. FastaRun必须具有与其链接的Search实例,并且此Search实例是FastaRun的主键.

我有一个FastaRun类的ModelForm.

# views.py
class FastaForm(forms.ModelForm):

    class Meta:
        model = models.FastaRun

我有一个视图函数,我需要使用它来填充FastaForm并根据用户提交的表单保存一个新的Search实例和一个新的FastaRun实例.表单不包括选择搜索实例的选项.这是不可能的,因为只有在用户实际提交此搜索后,搜索实例才能存在.

以下是该功能需要做的概述:

# also in views.py
def fasta(request, ...):
    # populate a FastaForm from the information POSTed by the user--but
    # how to do this when there's no Search information coming in from
    # the user's request. We need to create that Search instance, too,
    # but we also have to...

    # validate the FastaForm
    # ... before we can ...

    # create a Search instance and save() it

    # use this saved Search instance and give it to the FastaForm [how?]

    # save() the FastaForm [save the world]

    pass

因为Search和FastaRun(以及FastaForm)是
交织在一起,我觉得我正在进入一个Catch-22.我需要
保存一个Search实例,其参数存储在POST中
请求,但必须使用FastaForm验证其参数
验证.但是,我认为FastaForm直到无法实例化
我已经实例化了一个Search实例.然而,我无法实例化
搜索实例,直到我使用FastaForm验证…你得到
这个想法.

我在这里错过了什么?必须有一个相当干净的方法来做到这一点,但是
我看不清楚.

另外,如果我错了,请纠正我,但是只要你在模型之间存在某种关系(例如,对于ForeignKey和ManyToMany字段),也会出现同样的依赖情况.因此,有人肯定会想到这一点.

最佳答案 这是我将使用继承来处理这个问题的情况:

# models.py
class Search(models.Model):
    """A class to represent search runs."""
    ...

class FastaRun(Search):
    # one-to-one field has been removed
    ....

现在,根据定义实例化FastaRun也会实例化搜索. Django也通过为FastaRun设置一个单独的表并使用密钥进入搜索来正确处理数据库方面.您的验证应该与表单一起按预期工作.如果要对Search对象进行任何查询,您可能想要添加的唯一事情是向Search添加一个类型字段,该字段被所有子类覆盖,因此您可以过滤掉这些结果.

点赞