2009-11-27 4 views
1

시나리오 : 주문 양식을 작성 중입니다. 행성의 다른 모든 주문 양식과 마찬가지로, 별도의 인보이스 발송 주소가 있습니다. 방금 사용자가 시간을 절약 할 수 있도록 '청구서 수신 주소 사용'확인란을 추가했습니다.부울 필드가 설정된 경우에만 특정 필드의 유효성을 검사하십시오.

문제는 배송지가 계속 표시된다는 것입니다. 사용자가 청구서 수신 주소를 사용하려는 경우와 같이 배송 주소 데이터를 입력하지 않으면 유효성 검사가 실패합니다.

나는이 중복 필드에 대한 ModelForm 유효성 검사를 무시하고 싶습니다. 상자에 체크 표시가되어있는 경우 (유효성 검사기에서 데이터를 얻는 방법이 확실하지 않은 경우), 결제 버전을 반환합니다. 선택하지 않으면 원래 유효성 검사로 다시 전달합니다.

계획과 같은 소리가 들리지 않습니까? 나는 첫 번째 장애물에 빠졌다. 내 clean_functions이 작동하지 않습니다. 심지어 부름을받는 것처럼 보이지 않습니다. 나는 시험이야 어떻게

다음
# shipping_street is a field in my Order Model 

class OrderForm(ModelForm): 
    class Meta: 
     model = Order 

    def clean_shipping_street(self): 
     print "JUST GET ME SOME OUTPUT!!!" 
     raise forms.ValidationError('RAWRAWR') 

이야 : 난 그냥 clutz되고 있지만, 가공 한 다음 (그리고 경우

def checkout(request): 
    of = OrderForm() 
    if request.method == "POST": 
     of = OrderForm(request.POST) 
     print 'Form valid:', of.is_valid() 

    # ... 
    # return my HttpResponse with 'of' in the context. 

답변

1

마지막 답변에 몇 가지 문제가있었습니다. 복사 된 데이터는 양식으로 다시 렌더링되지 않았습니다 (원하는 작업 일 수도 있음). 조금 신뢰할 만했습니다.

다음은 현재 사용중인 것입니다.대신 clean_field_name() 정의 수십를 추가, 난 그냥 BooleanField 하나 있습니다

def clean_ship_to_billing(self): 
    if self.cleaned_data.get('ship_to_billing', False): 
     data = self.data.copy() 
     for f in ['street', 'street_2', 'post_code', 'city', 'county', 'country', ]: 
      data['shipping_%s' % f] = data['billing_%s' % f] 
     self.data = data 

를 선택하면 복사합니다 선적 필드에 청구 필드에서 원시 데이터. 필드가 모델 (또는 양식) 필드 순서의 운송 필드 앞에 있어야합니다.

POST 데이터가 변경되지 않기 때문에 self.data가 복사됩니다.

2

잘 모르겠어요 내 전체 응답 여기

는 일부 코드입니다 질문) :

클래스 OrderForm (ModelForm) : 클래스 메타 : 모델 = 주문

def clean_shipping_street(self): 
    print 'VALIDATING!!! YEY!' 
    if self.cleaned_data['ship_to_billing']: 
     return self.clean_billing_street() 
    return super(OrderForm, self).clean_shipping_street() 

하지만 내가 잘못된 방향으로 가고 있다고 생각되면 알려 주시기 바랍니다.

Nick이 아래에서 지적했듯이 cleaned_data는 보장 된 순서로 채워지지 않으므로 clean_shipping_street()을 호출하면 ship_to_billing이 존재하지 않을 수 있습니다. 이 문제를 해결하는 방법은 cleaned_data에 액세스하는 대신 clean_shipping_street() 메서드를 호출하는 것입니다.

def clean_shipping_street(self): 
    print 'VALIDATING!!! YEY!' 
    if self.clean_ship_to_billing(): 
     return self.clean_billing_street() 
    return super(OrderForm, self).clean_shipping_street() 

내가 코드를 쓸 때, 당신은 부울 필드의 많은 중복 검증을 회피 할 수 있었다 당신이 게으른 아니었다면. 이 빨리되어야합니다 (기본 필드는 필요할하지 않는 한 실행되지 않습니다 제공 - 그에 대한 확실하지 않은 자신을) :

def clean_shipping_street(self): 
    print 'VALIDATING!!! YEY!' 
    if self.cleaned_data.get('ship_to_billing', self.clean_ship_to_billing): 
     return self.clean_billing_street() 
    return super(OrderForm, self).clean_shipping_street() 

또는것보다 훨씬 더 :

def clean_shipping_street(self): 
    if not self.cleaned_data.has_key['ship_to_billing']: 
     self.cleaned_data['ship_to_billing'] = self.clean_ship_to_billing() 
    if self.cleaned_data['ship_to_billing']: 
     return self.clean_billing_street() 
    return super(OrderForm, self).clean_shipping_street() 

이것은 약간 다르지만 clean_ship_to_billing()이 이전의 노력보다 훨씬 덜 불리는 것을 의미합니다. 그러나 심각하게도 프로파일 링 세션에서 이러한 "개선 사항"을 감지 할 수 있을지 의심 스럽습니다.

+1

이것이 내가하는 방법입니다. 어쩌면 최고는 아니지만 맞춤 청소 방법이 아마도 가장 쉽습니다. –

+1

'clean_ '메소드는 특정 순서로 호출되지 않으므로 위의 경우'ship_to_billing'이'cleaned_data'에 아직 설정되지 않았을 수 있습니다. 일반적으로 여러분의 clean 메소드가 폼에있는 하나 이상의 아이템에 의존한다면, 평범한'clean' 메소드를 사용하십시오. –

+0

그 생각에 대해 닉. self.cleaned_data [ 'field_name']'을 호출하는 대신'self.clean_field_name()'을 호출한다. - 이렇게하면 사용자 정의 정리에 지저분한 순환 종속성이없는 한 결과가 보장된다. CPU에 대한 작업이 조금 더 많지만 항상 작동해야합니다. – Oli