I’ve overridden the default manager of my models in order to show only allowed items, according to the logged user (a sort of object-specific permission):
class User_manager(models.Manager):
def get_query_set(self):
""" Filter results according to logged user """
#Compose a filter dictionary with current user (stored in a middleware method)
user_filter = middleware.get_user_filter()
return super(User_manager, self).get_query_set().filter(**user_filter)
class Foo(models.Model):
objects = User_manager()
...
In this way, whenever I use Foo.objects, the current user is retrieved and a filter is applied to default queryset in order to show allowed records only.
Then, I have a model with a ForeignKey to Foo:
class Bar(models.Model):
foo = models.ForeignKey(Foo)
class BarForm(form.ModelForm):
class Meta:
model = Bar
When I compose BarForm I’m expecting to see only the filteres Foo instances but the filter is not applied. I think it is because the queryset is evaluated and cached on Django start-up, when no user is logged and no filter is applied.
Is there a method to make Django evalutate the ModelChoice queryset at run-time, without having to make it explicit in the form definition? (despite of all performance issues…)
EDIT
I’ve found where the queryset is evaluated (django\db\models\fields\related.py: 887):
def formfield(self, **kwargs):
db = kwargs.pop('using', None)
defaults = {
'form_class': forms.ModelChoiceField,
'queryset': self.rel.to._default_manager.using(db).complex_filter(self.rel.limit_choices_to),
'to_field_name': self.rel.field_name,
}
defaults.update(kwargs)
return super(ForeignKey, self).formfield(**defaults)
Any hint?
i use init of custom form: