I got a little problem which I thought must me quite common. Here's the problem described very generic:
class Ownable(models.Model):
user = models.ForeignKey(django.contrib.auth.models.User)
class Meta:
abstract = True
class Bowl(Ownable):
pass
class Pea(Ownable):
bowl = models.ForeignKey(bowl)
Relationships are: User [1:n] Bowl
,
User [1:n] Pea
Bowl [1:n] Pea
Now when I want to create a new Pea
I also need to assign it to a Bowl
like so:
def create_new_pea(request):
PeaFrom = inlineformset_factory(django.contrib.auth.models.User, Pea)
return render(request, 'app/pea/create.html', {'formset': PeaFrom()})
How in this process would I be able to pass a QuerySet
to the bowl
-field as I what the user to be only able to put bean inside his own bowls.
I'd be very glad for suggestions. I tried creating a custom form for the formset-factory, but I need the request
instance to know the current user.
One simple way is to do it after instantiating the formset.
def create_new_pea(request):
PeaFormset = inlineformset_factory(django.contrib.auth.models.User, Pea)
formset = PeaFormset(instance=request.user)
for form in formset:
form.fields['bowl'].queryset = request.user.bowl_set.all()
return render(request, 'app/pea/create.html', {'formset': formset}
I think it's possible to build this behavior into a custom Formset
class, overriding the _construct_forms
method:
class UserLimitedFormset(BaseInlineFormset):
def _construct_forms(self):
super(UserLimitedFormset, self)._construct_forms()
for form in self:
form.fields['bowl'].queryset = self.instance.bowl_set.all()
PeaFormset = inlineformset_factory(django.contrib.auth.models.User, Pea, formset=UserLimitedFormset)
To use the callback, I think you'd need a closure or a functools.partial
to record the user before creating the formset. Possibly this, although it's untested and I'm rusty on closures:
def create_new_pea(request):
user = request.user
def set_queryset(f, **kwargs):
formfield = f.formfield(**kwargs)
if f.name == 'bowl':
formfield.queryset = user.bowl_set.all()
return formfield
PeaFormset = inlineformset_factory(django.contrib.auth.models.User, Pea, formfield_callback=set_queryset)