以经典的 foo bar 为例:
在 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')
在我的表单中,我尝试使用原始查询将 foreignkey
to Foo
的选择限制为 Foo
的子集。
在 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)
是一个返回表的数据库过程。它搜索多个关系并以优化的方式处理结果的过滤和排序。它有效,我宁愿不必在 Django 代码中再次编写代码。
我收到以下错误:“'RawQuerySet' 对象没有属性 'all'”
。
如果我改用普通的 Bar.objects.filter()
,该表单就可以工作。
我应该如何将我的 RawQuerySet
转换为普通的 QuerySet
?
我应该使用 self.fields['line_stop'].choice
选项吗?
最佳答案
我遇到了类似的问题并提出了那个棘手的解决方案:
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
我知道它并不完美,子类化 ModelChoiceField 会更好。
关于Django:使用原始查询来限制 ModelForm 中的外键选择字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11989742/