Reputation: 73
Taking a classic foo bar example:
In models.py
:
Class Foo(models.Model):
name = models.CharField(max_length= 200)
Class Bar(models.Model):
name = models.CharField(max_length= 200)
foo = models.ForeignKey('Foo')
In my form, I tried to limit the choices of my foreignkey
to Foo
to a subset of Foo
using a raw query.
In forms.py
:
class BarForm(ModelForm):
search_field = CharField(max_length=100, required=False)
def __init__(self,*args,**kwargs):
search_str = kwargs.pop('search_str', None)
super(BarForm,self ).__init__(*args,**kwargs)
self.fields['search_field'].initial = search_str
self.fields['foo'].queryset = Bar.objects.raw("""
select f.id as id, f.name as name from bar_lookup(%s)""", [search_str])
class Meta:
model = Bar
exclude = ('foo',)
bar_lookup(%s)
is a DB procedure returning a table. It searches multiple relations and handles the filtering and sorting of the results in an optimized way. It works and I would rather not have to code it again in Django code.
I get the following error: "'RawQuerySet' object has no attribute 'all'"
.
The form works if I use a normal Bar.objects.filter()
instead.
How should I transform my RawQuerySet
into a normal QuerySet
?
Should I use the self.fields['line_stop'].choice
option?
Upvotes: 3
Views: 1355
Reputation: 1298
I had a similar problem and come with that tricky solution:
class BarForm(ModelForm):
search_field = CharField(max_length=100, required=False)
def __init__(self,*args,**kwargs):
search_str = kwargs.pop('search_str', None)
super(BarForm,self ).__init__(*args,**kwargs)
self.fields['search_field'].initial = search_str
self.foo_choices = Bar.objects.raw("""
select f.id as id, f.name as name from bar_lookup(%s)""", [search_str])
self.fields['foo'].choices = [(x.id, x) for x in self.foo_choices]
def clean_foo(self):
foo = self.cleaned_data['foo']
if foo not in self.foo_choices:
raise forms.ValidationError("Some error!")
return foo
class Meta:
model = Bar
An I know it is not perfect, and subclassing ModelChoiceField would be better.
Upvotes: 1