2011-12-14 6 views
3

TabularInlineモデルのデフォルトのformsetをオーバーライドするためにforms.models.BaseInlineFormSetを作成しました。一部のグループは範囲(0,20)内に数値を書き込む必要があるため、フォームセット検証(clean)でユーザーのグループを評価する必要があります。django admin - BaseInlineFormSetのrequest.userをアクセス

私はインターフェイスを自動生成するためにdjango adminを使用しています。

メソッドのkwargsからリクエストとユーザーを取得しようとしましたが、参照を取得できませんでした。

これは私が今持っているものです。

class OrderInlineFormset(forms.models.BaseInlineFormSet): 
    def __init__(self, *args, **kwargs): 
     self.user = kwargs.pop('user') 
     super(OrderInlineFormset, self).__init__(*args, **kwargs) 

    def clean(self): 
     # get forms that actually have valid data 
     count = 0 
     for form in self.forms: 
      try: 
       if form.cleaned_data: 
        count += 1 
        if self.user.groups.filter(name='Seller').count() == 1: 
         if form.cleaned_data['discount'] > 20: 
          raise forms.ValidationError('Not authorized to specify a discount greater than 20%') 
      except AttributeError: 
       # annoyingly, if a subform is invalid Django explicity raises 
       # an AttributeError for cleaned_data 
       pass 
     if count < 1: 
      raise forms.ValidationError('You need to specify at least one item') 

class OrderItemInline(admin.TabularInline): 
    model = OrderItem 
    formset = OrderInlineFormset 

は、その後、私は私のModelAdminの中01​​として使用します。

不幸にもself.userは常にNoneです。したがって、ユーザーグループを比較することができず、フィルタは適用されません。私はそれをフィルタリングする必要があります。これは、他のグループが割引率を指定できる必要があるからです。

どうすればいいですか? ModelAdminコードが必要な場合は、公開します(混乱を避けるために、コード全体をコピーするのは避けました)。

答えて

7

私はあなたの質問に自分のコードを認識しているので、私はそれを試してみるとよいでしょう。しかし、まず、スニペットは実際にフォームセット内のフォームの最小数を検証するためだけであると言うでしょう。あなたのユースケースは異なっています - あなたは各フォーム内の何かをチェックしたいと思います。フォームセットではなくフォームのレベルで検証する必要があります。

しかし、問題は実際にあなたが投稿したコードではなく、それがその一部に過ぎないという事実と関係しています。フォームまたはフォームセットの初期化時にkwargsからユーザーを取得する場合は、ユーザーが実際にその初期化に渡されていることを確認する必要があります。デフォルトではそうではありません。

残念ながら、Djangoの管理者は、実際には初期化自体を傍受するための適切なフックを与えません。しかし、あなたはget_form関数をオーバーライドして、リクエスト引数でフォームクラスをラップするfunctools.partialを使用してごまかすことができます(このコードは合理的にテストされていないが、動作するはずです):

from functools import partial 

class OrderForm(forms.ModelForm): 
    def __init__(self, *args, **kwargs): 
     self.user = kwargs.pop('user') 
     super(OrderForm, self).__init__(*args, **kwargs) 

    def clean(self) 
     if self.user.groups.filter(name='Seller').count() == 1: 
      if self.cleaned_data['discount'] > 20: 
       raise forms.ValidationError('Not authorized to specify a discount greater than 20%') 
     return self.cleaned_data 

class MyAdmin(admin.ModelAdmin): 
    form = OrderForm 

    def get_form(self, request, obj=None, **kwargs): 
     form_class = super(MyAdmin, self).get_form(request, obj, **kwargs) 
     return functools.partial(form_class, user=request.user) 
+1

、このような古いポストを掘るために申し訳ありませんが、Iこの解決策に遭遇し、私が実装するとき、 'functools.partial'オブジェクトには属性 'base_fields'がありません。 – Matthew

関連する問題