Mat
Mat

Reputation: 23

Django modelformset with customized model initialization

I have the following models in django:

class tag(models.Model):
    ...
    user = models.ForeignKey(user)
    shop = models.ForeignKey(shop)
    name = models.CharField()
    ...

class user(models.Model):
    ...
    name = models.CharField()
    ...

class shop(models.Model):
    ...
    user = models.ForeignKey(user)
    name = models.CharField()
    ...

Now I need to create a modelformset of tag model that will allow me to store bunch of different tags per user. What I am looking for is a way to initialize such formset with a shop field filtered out for a given user.

This way my forms would have a selection of shops that are assigned to the user.

Any ideas are very welcome! Thanks

Upvotes: 0

Views: 75

Answers (1)

Iain Shelvington
Iain Shelvington

Reputation: 32244

You can use inlineformset_factory to create a formset for related models. To create a formset for your tag and user model you can do the following:

tag_formset = inlineformset_factory(user, tag, fields=['shop', 'name'])
formset = tag_formset(instance=request.user)

To filter the queryset for the shop field you can either create a form dynamically or pass formfield_callback to the factory function.

If you use formfield_callback, this callback can be used to return a custom field for your form

def cb(field, **kwargs):
    if field.name == 'shop':
        kwargs['queryset'] = shop.objects.filter(user=request.user)
    return field.formfield(**kwargs)

tag_formset = inlineformset_factory(user, tag, fields=['shop', 'name'], formfield_callback=cb)
formset = tag_formset(instance=request.user)

Or you can define a form class dynamically in your view

class TagForm(forms.ModelForm):
    shop = forms.ModelChoiceField(shop.objects.filter(user=request.user))
    class Meta:
        fields = ['shop', 'name']

tag_formset = forms.inlineformset_factory(user, tag, form=TagForm)
formset = tag_formset(instance=request.user)

Upvotes: 1

Related Questions