I
I
Ilya Chichak2017-07-18 17:27:51
Django
Ilya Chichak, 2017-07-18 17:27:51

How to make a formset for multiple db objects?

There is a model with which one more model is connected by a foreign key.

class Obj(Model):
    some_field = CharField(...)

class ForeignObj(Model):
    obj = ForeignKey(Obj, related_name="foreign_obj")
    some_data = IntegerField()

At some point there are Obj objects, but not all of them have ForeignObj objects.
There is a model form for ForeignObj:
class ForeignObjForm(ModelForm):
    obj = ModelChoiceField(
        queryset=Obj.objects.all(),
        widget=forms.HiddenInput()
    )

    def __init__(self, *args, **kwargs):
        self.obj = kwargs.pop('obj')
        super(ForeignObjForm, self).__init__(*args, **kwargs)
        self.fields['obj '].initial = self.obj

    class Meta:
        model = ForeignObj
        fields = '__all__'

For one object, everything works, which does not raise questions.
Now let's say there are several Obj objects for which there is no ForeignObj.
You need to create a form to batch create ForeignObj objects. How to implement this?
The simplest solution "on the forehead":
in the template, manually sort through the entire QuerySet with Obj objects and create the markup created by the FormSet yourself, but it seems to me that this is not the most correct option.
Possible solutions:
1) create forms for each Obj yourself and somehow (how?) combine them and batch process them.
2) pass Obj objects to the form_set_factory QuerySet so that it will sort through it and create all the forms itself, passing each element of the QuerySet into them one by one
Solutions - what came to mind, but I can not figure out how to do it ...

Answer the question

In order to leave comments, you need to log in

1 answer(s)
I
Ilya Chichak, 2017-07-18
@ilya_chch

I found a solution, maybe it will be useful for someone:

class ForeignObjFormSet:
    def get_form_kwargs(self, index):
        kwargs = super(ForeignObjFormSet, self).get_form_kwargs(index)
        kwargs['obj'] = self.form_kwargs['obj'][index]
        return kwargs

# Во вьюхе
def view(request):
    target_objects = Obj.objects.filter(foreign_obj__isnull=True)
    FormSet = formset_factory(forms.ForeignObjForm, formset=ForeignObjFormSet, extra=target_objects.count())
    form_set = FormSet(form_kwargs={'obj': list(target_objects)})
# ...

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question