Reputation: 59
I am having trouble making a ModelChoiceField queryset in a ModelForm. The related model.objects manager has been overridden to filter the results in order to get only instances created by the actual user. Here are my models :
class Bloc(ModelPrive):
TYPE_BLOC = (
('pleinchamps', 'plein champs'),
('tunnel', 'tunnel'),
('pepiniere', 'pépinière'),
('autre', 'autre'),
)
nb_planche = models.IntegerField(null=True)
caracteristique = models.CharField(max_length=200, null= True, blank=True)
geom = models.PolygonField(srid=4326)
type_bloc = models.CharField(max_length=200, blank=True, choices=TYPE_BLOC)
nom = models.CharField(max_length=200, null=True, unique= True)
class ModelPrive(models.Model):
created_by = models.ForeignKey(User, blank=True, null=True, on_delete=models.SET_NULL, editable=False)
class Meta:
abstract = True
objects = ModelPriveManager()
class ModelPriveManager(models.Manager):
def get_queryset(self):
user = get_current_user()
return super().get_queryset().filter(created_by=user)
In my manager the get_current_user() returns the actual user that has been intercepted by a custom middleware.
Here is my form :
class BlocFormList(ModelForm):
choix_bloc = forms.ModelChoiceField(queryset = Bloc.objects.all().order_by('nom'), required=True)
class Meta:
model = Bloc
fields = ['choix_bloc']
Here is my view :
def planification(request):
form_bloc = BlocFormList()
if request.method == 'POST':
# some other code
return render(request, 'planification.html', locals())
The problem is, when I do a Bloc.objects.all() in views I get the expected answer (Bloc.objects.filter(created_by=user)) but when it is done inside the queryset of the modelform, it returns nothing (as if there were no active user).
After some checks, I have found that the model form queryset doesn't even go into the manager.
If someone knows how to correct this, I have no more ideas.
Upvotes: 3
Views: 1376
Reputation: 59
Seeing this post Django ModelForm overriding __init__, I finally found my solution by overriding the init of my ModelForm :
class BlocFormList(ModelForm):
blocs = None
choix_bloc = forms.ModelChoiceField(label='Blocs', queryset=blocs, required=True)
def __init__(self, *args, **kwargs):
self.blocs = Bloc.objects.all()
super(BlocFormList, self).__init__(*args, **kwargs)
self.fields['choix_bloc'].queryset = self.blocs
class Meta:
model = Bloc
fields = ['choix_bloc']
This works fine.
Upvotes: 2