ModelForms в Django, где базовая модель зависит от другой модели (через OneToOneField) - PullRequest
4 голосов
/ 06 мая 2009

В моем приложении 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 является разновидностью Search. 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

Потому что Search и FastaRun (и, следовательно, FastaForm) переплетаясь, я чувствую, что попадаю в Catch-22. Мне необходимо сохранить экземпляр Search, параметры которого хранятся в POST запрос, но чьи параметры должны быть проверены с помощью FastaForm Проверка. Тем не менее, я думаю, что FastaForm не может быть создан до Я создал экземпляр Search. Тем не менее, я не могу создать экземпляр Search экземпляр, пока я не проверил, используя FastaForm ... Вы получаете идея.

Что мне здесь не хватает? Должен быть достаточно чистый способ сделать это, но Мне не хватает ясности, чтобы увидеть это.

Кроме того, исправьте меня, если я ошибаюсь, но такая же ситуация зависимости может возникнуть в любой момент, когда у вас есть какая-то связь между моделями (например, также для полей ForeignKey и ManyToMany). Таким образом, кто-то наверняка понял это.

1 Ответ

2 голосов
/ 08 мая 2009

Это тот случай, когда я бы позаботился о наследовании:

# 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, которое переопределяется всеми подклассами, чтобы вы могли отфильтровать эти результаты.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...