3

古典的なfoobarの例を見てみましょう:

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ましたFooFoo

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)テーブルを返すDBプロシージャです。複数のリレーションを検索し、結果のフィルタリングと並べ替えを最適化された方法で処理します。それは機能し、Djangoコードで再度コーディングする必要はありません。

次のエラーが発生します:"'RawQuerySet' object has no attribute 'all'"Bar.objects.filter()代わりに法線を使用すると、フォームは機能します。

どうすればRawQuerySet普通に変身できQuerySetますか?オプションを使用する必要がありself.fields['line_stop'].choiceますか?

4

1 に答える 1

1

私は同様の問題を抱えていましたが、そのトリッキーな解決策がありました:

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 をサブクラス化する方が良いでしょう。

于 2012-08-16T15:03:31.710 に答える