[PYTHON] 장고 관리자의 종속 인라인의 유효성 검사
PYTHON장고 관리자의 종속 인라인의 유효성 검사
Django 1.4를 사용하고 있으며 서로 다른 인라인 값을 비교하는 유효성 검사 규칙을 설정하려고합니다.
나에게는 세 가지 간단한 수업이있다.
models.py에서 :
class Shopping(models.Model):
shop_name = models.CharField(max_length=200)
class Item(models.Model):
item_name = models.CharField(max_length=200)
cost = models.IntegerField()
item_shop = models.ForeignKey(Shopping)
class Buyer(models.Model):
buyer_name = models.CharField(max_length=200)
amount = models.IntegerField()
buyer_shop = models.ForeignKey(Shopping)
admin.py :
class ItemInline(admin.TabularInline):
model = Item
class BuyerInline(admin.TabularInline):
model = Buyer
class ShoppingAdmin(admin.ModelAdmin):
inlines = (ItemInline, BuyerInline)
예를 들어 10 $의 럼주 한 병과 8 $의 보드카 한 병을 구입할 수 있습니다. Mike는 15 달러를, Tom은 3 달러를 지불합니다.
목표는 사용자가 일치하지 않는 인스턴스를 저장하지 못하도록하는 것입니다. 지불 된 항목은 항목 비용의 합계 (예 : 10 + 8 = 15 + 3)와 같아야합니다.
나는 시도했다 :
이 문제에 대한 해결책이 있습니까? 클라이언트 측 (javascript / ajax) 유효성 검사가 가장 간단합니까?
해결법
-
==============================
1.원하는 것을 얻기 위해 인라인 formset을 재정의 할 수 있습니다. formset의 정리 메소드에서 'instance'멤버를 통해 Shopping 인스턴스에 액세스 할 수 있습니다. 따라서 Shopping 모델을 사용하여 계산 된 총계를 임시로 저장하고 서식 세트를 통신 할 수 있습니다. models.py에서 :
원하는 것을 얻기 위해 인라인 formset을 재정의 할 수 있습니다. formset의 정리 메소드에서 'instance'멤버를 통해 Shopping 인스턴스에 액세스 할 수 있습니다. 따라서 Shopping 모델을 사용하여 계산 된 총계를 임시로 저장하고 서식 세트를 통신 할 수 있습니다. models.py에서 :
class Shopping(models.Model): shop_name = models.CharField(max_length=200) def __init__(self, *args, **kwargs) super(Shopping, self).__init__(*args, **kwargs) self.__total__ = None
admin.py :
from django.forms.models import BaseInlineFormSet class ItemInlineFormSet(BaseInlineFormSet): def clean(self): super(ItemInlineFormSet, self).clean() total = 0 for form in self.forms: if not form.is_valid(): return #other errors exist, so don't bother if form.cleaned_data and not form.cleaned_data.get('DELETE'): total += form.cleaned_data['cost'] self.instance.__total__ = total class BuyerInlineFormSet(BaseInlineFormSet): def clean(self): super(BuyerInlineFormSet, self).clean() total = 0 for form in self.forms: if not form.is_valid(): return #other errors exist, so don't bother if form.cleaned_data and not form.cleaned_data.get('DELETE'): total += form.cleaned_data['cost'] #compare only if Item inline forms were clean as well if self.instance.__total__ is not None and self.instance.__total__ != total: raise ValidationError('Oops!') class ItemInline(admin.TabularInline): model = Item formset = ItemInlineFormSet class BuyerInline(admin.TabularInline): model = Buyer formset = BuyerInlineFormSet
이것은 당신이 그것을 할 수있는 유일한 깨끗한 방법입니다 (제 지식의 최상). 그리고 모든 것이 그것이 있어야하는 곳에 위치합니다.
편집 : form.cleaned_data * check 양식에 빈 인라인이 포함되어 있기 때문에 *를 추가했습니다. 이것이 어떻게 효과가 있는지 알려주세요!
EDIT2 : 주석에 정확하게 지적한 바와 같이, 삭제 될 양식에 대한 점검을 추가했습니다. 이 양식들은 계산에 참여해서는 안됩니다.
-
==============================
2.좋아, 나는 해결책이있다. 그것은 장고 관리자의 코드를 편집이 포함됩니다.
좋아, 나는 해결책이있다. 그것은 장고 관리자의 코드를 편집이 포함됩니다.
django / contrib / admin / options.py의 add_view (924 줄) 및 change_view (1012 줄) 메소드에서 다음 부분을 찾으십시오.
[...] if all_valid(formsets) and form_validated: self.save_model(request, new_object, form, True) [...]
그것을
if not hasattr(self, 'clean_formsets') or self.clean_formsets(form, formsets): if all_valid(formsets) and form_validated: self.save_model(request, new_object, form, True)
이제 ModelAdmin에서 다음과 같이 할 수 있습니다.
class ShoppingAdmin(admin.ModelAdmin): inlines = (ItemInline, BuyerInline) def clean_formsets(self, form, formsets): items_total = 0 buyers_total = 0 for formset in formsets: if formset.is_valid(): if issubclass(formset.model, Item): items_total += formset.cleaned_data[0]['cost'] if issubclass(formset.model, Buyer): buyers_total += formset.cleaned_data[0]['amount'] if items_total != buyers_total: # This is the most ugly part :( if not form._errors.has_key(forms.forms.NON_FIELD_ERRORS): form._errors[forms.forms.NON_FIELD_ERRORS] = [] form._errors[forms.forms.NON_FIELD_ERRORS].append('The totals don\'t match!') return False return True
이것은 적절한 해결책보다 더 해킹입니다. 어떤 개선 제안? 아무도 이것이 장고에 대한 기능 요청이어야한다고 생각합니까?
from https://stackoverflow.com/questions/13526792/validation-of-dependant-inlines-in-django-admin by cc-by-sa and MIT license
'PYTHON' 카테고리의 다른 글
[PYTHON] iterable을 스트림으로 변환하는 방법? (0) | 2018.11.25 |
---|---|
[PYTHON] 파이썬에서 길이 인코딩 실행 (0) | 2018.11.25 |
[PYTHON] 숫자를 고정 길이로 이진으로 변환 (0) | 2018.11.25 |
[PYTHON] 파이썬 3.2 람다 구문 오류 [중복] (0) | 2018.11.25 |
[PYTHON] HTTPError : HTTP 오류 403 : 금지됨 (0) | 2018.11.25 |