【问题标题】:ModelForms in Django where the underlying model depends on another model (via OneToOneField)Django 中的 ModelForms,其中底层模型依赖于另一个模型(通过 OneToOneField)
【发布时间】:2010-10-24 07:16:39
【问题描述】:

我的 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
    )

注意这里FastaRunSearch的一种。 FastaRun 扩展了搜索,因为为 FastaRun 定义了更多参数。一个FastaRun 必须有一个与之链接的Search 实例,而这个Search 实例是FastaRun 的主键。

我有一个 ModelForm 用于 FastaRun 类。

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

    class Meta:
        model = models.FastaRun

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

下面是函数需要做什么的概要:

# 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

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

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

另外,如果我错了,请纠正我,但只要模型之间存在某种关系(例如,ForeignKeyManyToMany 字段),任何时候都可能发生同样的依赖情况。因此,肯定有人想到了这一点。

【问题讨论】:

    标签: django django-models django-forms dependencies


    【解决方案1】:

    在这种情况下,我会使用继承来解决这个问题:

    # models.py
    class Search(models.Model):
        """A class to represent search runs."""
        ...
    
    class FastaRun(Search):
        # one-to-one field has been removed
        ....
    

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

    【讨论】:

    • program 是一个 CharField,用于标识为执行搜索而运行的程序(例如,“fasta35”或“ssearch35”或“blast”)。 'fasta35' 和 'ssearch35' 必须保存为 FastaRun 实例。这应该足以作为过滤器,对吗?有没有办法从 Search 实例转到其对应的 FastaRun 实例(我们可以假设它有一个)?
    • 是的,这似乎是一个足够好的过滤器,尽管您似乎只想使用它来排除子类项目。 (对于那些,您会想要使用子类,例如 FastaRun.objects.filter(...)。)如果您确实需要从 Search 对象 s 转到 FastaRun(或任何其他子类),您总是可以做 FastaRun.objects.get(id=s.id)。
    • 太棒了。感谢您的帮助!
    猜你喜欢
    • 2019-03-11
    • 2017-12-20
    • 1970-01-01
    • 2012-05-20
    • 1970-01-01
    • 2019-02-16
    • 1970-01-01
    • 2014-06-26
    • 1970-01-01
    相关资源
    最近更新 更多