formset and input text for each foreign key

空扰寡人 提交于 2019-12-13 06:18:54

问题


In my django formset, I am trying to display a foreign key field with an input instead of a 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')

For the verbatim field, I do have an input box instead of a select but when I want to update a formset, I have the verbatim id instead of its corresponding text:

Here is how I initialize the form:

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)

I have tried two things:

Instead of the last line I have the following code:

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)

I have overridden the init method of the form:

#~ #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

None of these methods works, I still get numbers instead of text! What is curious is that I do see text for the verbatim field but only for the three extra forms. Normal?

EDIT - from Bernd Jerzyna comment

In my form:

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

In my view:

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

When I do a print of the text of each verbatim, I see the correct text displayed. However, I still see numbers (primary key ids) in the form of my web page ;(.

What's wrong?


回答1:


I think something like this should work:

Implement the init method of your formset like

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

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

That would also require your Verbatim model to have something like:

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



回答2:


This is my understanding of it...

As a select widget, the verbatim is displayed with the __unicode__ results, but the value 'behind the scenes' is the PK/verbatim-id, ie the HTML <option> tag has a value and 'label'. When you change it to a text input widget, it is expecting you to enter the PK, hence why you are seeing the numbers.

For the solution, I am not sure. You could write some code to accept the verbatim-text, rather than the pk/verbatim-id. The problem with this though, is that if the text is not written exactly, django won't find a match. Also, if more than 1 verbatim has the same text, django wouldn't know which one to use (unless you have set unique=true on the model field for text). You could also set the verbatim-text as the PK.

Perhaps using something like Django-Select2 will give you the desired UI?



来源:https://stackoverflow.com/questions/24608756/formset-and-input-text-for-each-foreign-key

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!