набор форм и ввод текста для каждого внешнего ключа

#django #input #initialization #foreign-keys #formset

#django #ввод #инициализация #внешние ключи #набор форм

Вопрос:

В моем django formset я пытаюсь отобразить foreign key поле с input вместо select :

 class MinAttend(models.Model):
    act = models.ForeignKey(Act)
    country = models.ForeignKey(Country)
    verbatim = models.ForeignKey(Verbatim)
    def __unicode__(self):
        return u"%s" % self.verbatim

class MinAttendForm(forms.ModelForm):
    country=forms.ModelChoiceField(queryset=Country.objects.all(), empty_label="Select a country")
    status=forms.ModelChoiceField(queryset=Status.objects.values_list('status', flat = True).distinct(), empty_label="Select a status")
    verbatim=forms.CharField(max_length=300)

    class Meta:
        model=MinAttend
        #fields used for the validation and order
        fields = ('country', 'status', 'verbatim')
  

Для поля verbatim у меня есть поле ввода вместо select, но когда я хочу обновить набор форм, у меня есть идентификатор verbatim вместо соответствующего текста:

введите описание изображения здесь

Вот как я инициализирую форму:

 class MinAttendUpdate(UpdateView):
    object=None
    model = MinAttend
    form_class=MinAttendForm
    nb_extra_forms=3

    def post(self, request, *args, **kwargs):
        attendances=MinAttend.objects.filter(...)
        #set the number of forms to the number of ministers   3 extra form to fill if needed
        MinAttendFormSet = modelformset_factory(self.model, form=self.form_class, extra=len(attendances), max_num=len(attendances) self.nb_extra_forms, can_delete=True)
        formset=MinAttendFormSet(queryset=attendances)
  

Я попробовал две вещи:

Вместо последней строки у меня есть следующий код:

 initials=[]
#display text of verbatim instead of id
for index in range(len(attendances)):
    initials.append({"verbatim": attendances[index].verbatim.verbatim})
print "initials", initials
formset=MinAttendFormSet(queryset=attendances, initial=initials)
  

Я переопределил init метод формы:

 #~ #verbatim text instead of id for the verbatim field
def __init__(self, *args, **kwargs):
    super(MinAttendForm, self).__init__(*args, **kwargs)
    instance = kwargs.get("instance", None)
    if instance!=None:
        print "instance", instance.verbatim.verbatim
        self.fields["verbatim"].initial = instance.verbatim.verbatim
  

Ни один из этих методов не работает, я по-прежнему получаю цифры вместо текста! Любопытно то, что я вижу текст для поля verbatim, но только для трех дополнительных форм. Нормально?

РЕДАКТИРОВАТЬ — из комментария Бернда Джерзины

В моей форме:

 from django.forms.models import BaseModelFormSet

class MinAttendFormSet(BaseModelFormSet):
    def __init__(self, *args, **kwargs):
        super(MinAttendFormSet, self).__init__(*args, **kwargs)
        for form in self.forms:
            #skip extra forms
            if not form.empty_permitted:
                form.fields['verbatim'].initial= form.instance.verbatim
                print "verbatim MinAttendFormSet", form.instance.verbatim
  

На мой взгляд:

 from forms import MinAttendForm, MinAttendFormSet
my_formset = modelformset_factory(self.model, form=self.form_class, formset=MinAttendFormSet)
formset = my_formset(request.POST, queryset=attendances)
  

Когда я печатаю текст каждого дословного текста, я вижу, что отображается правильный текст. Тем не менее, я все еще вижу числа (идентификаторы первичного ключа) в виде моей веб-страницы;(.

Что не так?

Ответ №1:

Я думаю, что что-то вроде этого должно сработать:

Реализуйте метод init вашего набора форм следующим образом

 def __init__(self, *args, **kwargs):
...
super(MinAttendFormSet, self).__init__(*args, **kwargs)

for form in self.forms:
     form.fields['verbatim'].initial= form.instance.verbatim
  

Для этого также потребуется, чтобы ваша дословная модель имела что-то вроде:

 def __unicode__(self):
    return u'%s' % (self.name)
  

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

1. Я не думаю, что это может сработать, поскольку init метод объявлен внутри моей формы ( class MinAttendForm(forms.ModelForm): ), что означает, что он видит только одну форму за раз. Когда я использую ваш код, я получаю ошибку: 'MinAttendForm' object has no attribute 'forms' . Что мне делать дальше?

2. Да, это правильно. Вот почему я предложил реализовать это в наборе форм … 🙂

3. Я обновил свой первый пост в соответствии с вашим последним комментарием. Это все еще не работает : (.

Ответ №2:

Это мое понимание этого…

В качестве виджета выбора отображается дословный текст с __unicode__ результатами, но значением «за кадром» является PK / verbatim-id, т.Е. HTML <option> -тег имеет значение и ‘label’. Когда вы меняете его на виджет ввода текста, он ожидает, что вы введете PK, следовательно, почему вы видите цифры.

Что касается решения, я не уверен. Вы могли бы написать какой-нибудь код, чтобы принимать дословный текст, а не pk / verbatim-id. Проблема с этим, однако, заключается в том, что если текст написан не точно, django не найдет соответствия. Кроме того, если более 1 дословного текста содержат один и тот же текст, django не будет знать, какой из них использовать (если вы не установили unique=true в поле model для текста). Вы также могли бы установить дословный текст в качестве PK.

Возможно, использование чего-то вроде Django-Select2 даст вам желаемый пользовательский интерфейс?

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

1. Как реализовать ваше решение? Моя проблема заключается не в том, чтобы записать дословно в поле ввода, а в том, чтобы отобразить дословно.