Django, передающий информацию при изменении набора запросов для ModelForm

#python #django #django-forms

#python #django #django-forms

Вопрос:

База данных: Документ содержит много разделов, разделы содержат много комментариев

На каждой странице документа есть форма комментария, которая позволяет выбрать раздел (используя ModelChoiceField). Проблема в том, что ModelChoiceField будет содержать ВСЕ разделы для всех документов.

Поэтому, чтобы ограничить их, я делаю это:

 class CommentForm(ModelForm):
    def __init__(self, *args, **kwargs):
        super(CommentForm, self).__init__(*args, **kwargs)
        if self.instance:
            logger.debug(self.instance.document_id) # Prints "None"
            self.fields['section'].queryset = Section.objects.filter(document=self.instance.document)
            # ^^^ Throws DoesNotExist as self.instance.document is None
  

и мое мнение просто:

 form = CommentForm()
  

Как мне передать CommentForm идентификатор документа?

Редактировать: Пытался, на мой взгляд:

 d = Document.objects.get(id=id)
c = Comment(d)
form = CommentForm(c)
  

но document_id по-прежнему отсутствует в CommentForm

Ответ №1:

Вы можете передать идентификатор документа при инициализации формы:

 class CommentForm(ModelForm):
    def __init__(self, doc_id=None, *args, **kwargs):
        if doc_id:
            self.fields['section'].queryset = Section.objects.filter(document__id=doc_id)
  

и в представлении

 def my_view(request):
    ...
    doc = Document.objects(...)
    form = CommentForm(doc_id = doc.id)
  

Редактировать

Я отредактировал вторую строку представления, которая, я думаю, касается вашего комментария? (сделать doc.id ) аргумент ключевого слова

Комментарии:

1. Последнее было бы предназначено для редактирования существующего объекта, если я не ошибаюсь? Сейчас я пинаю себя, это так очевидно! Спасибо

2. Просто мои дополнительные 2 цента… Я думаю, что немного лучше изменить набор запросов следующим образом: self.fields['section'].queryset = self.fields['section'].queryset.filter(document__id=doc_id)

3. @Beres Спасибо, это сработало хорошо. @pastylegs — Этот метод на самом деле сталкивается с проблемой, потому что, когда Django вызывает CommentForm при использовании .save(), в *args будет отсутствовать первый аргумент. Я знаю, что вокруг этого есть хаки, но, безусловно, это действительно распространенная задача в Django, которая не должна нуждаться во взломах…

4. Вы уверены? * аргументы являются позиционными аргументами, в то время как doc_id=None является аргументом ключевого слова, поэтому не имеет значения, где вы его разместили, позиционные аргументы не должны быть затронуты

5. Хммм, да, похоже, это другая проблема :/