2011-12-14 2 views
3

방금 ​​TabularInline 모델의 기본 formset을 대체하기 위해 forms.models.BaseInlineFormSet을 만들었습니다. 일부 그룹은 범위 (0,20) 안에 숫자를 써야하기 때문에 formset 유효성 검사 (clean)에서 사용자의 그룹을 평가해야합니다.django admin - BaseInlineFormSet의 request.user 액세스

나는 인터페이스를 자동 생성하기 위해 장고 관리자를 사용하고 있습니다.

메쏘드의 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에 inlines = [OrderItemInline,]로 사용합니다.

불행히도 self.user는 항상 None이므로 사용자 그룹을 비교할 수 없으며 필터가 적용되지 않습니다. 다른 그룹이 할인율을 지정할 수 있어야하므로 필터링해야합니다.

어떻게하면됩니까? ModelAdmin 코드가 필요한 경우이를 게시 할 것입니다 (혼동을 피하기 위해 전체 코드를 복사하지 않았습니다).

답변

7

글쎄, 내 질문에 귀하의 코드를 인식하고 있으므로 더 나은 시도하고 대답을 것 같아요. 그러나 나는 그 발췌 문장이 실제로 formset 내의 폼의 최소 수를 검증하는 것임을 먼저 말할 것입니다. 유스 케이스가 다르다. 각 양식에서 무언가를 확인하고 싶다. 폼셋이 아닌 폼 수준에서 유효성 검사를 수행해야합니다.

그러나 문제는 실제로 게시 한 코드와 관련이 없지만 그 코드의 일부일뿐입니다. 분명히 폼이나 폼셋이 초기화 될 때 kwargs에서 사용자를 얻으려면 사용자가 실제로 초기화에 전달되는지 확인해야합니다. 기본적으로 그렇지 않습니다.

불행히도 장고의 관리자는 초기화 자체를 가로채는 적절한 고리를 제공하지 않습니다. 하지만 당신은 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

같은 이전 게시물을 발굴해서 죄송하지만 이 솔루션을 발견하고 구현할 때 'functools.partial'객체에 'base_fields'속성이 없습니다. – Matthew