2009-07-18 4 views
7

장고 양식 처리에 대한 대안이 상용구입니까?

뷰에서 폼을 처리하기위한 suggested 패턴은 지나치게 복잡하고 비 DRY 인 것처럼 보입니다 :

def contact(request): 
    if request.method == 'POST': # If the form has been submitted... 
     form = ContactForm(request.POST) # A form bound to the POST data 
     if form.is_valid(): # All validation rules pass 
      # Process the data in form.cleaned_data 
      # ... 
      return HttpResponseRedirect('/thanks/') # Redirect after POST 
    else: 
     form = ContactForm() # An unbound form 

    return render_to_response('contact.html', { 
     'form': form, 
    }) 

이는 많은 조건문이며 ContactForm() 구조를 반복하며 모든 블록이 어디에서나 반복됩니다 보기는 양식을 처리해야합니다. 그것을하는 더 좋은 방법이 있습니까?

+0

장고는 수년 전부터 일반 뷰를 보유하고 있습니다. 이 질문과 내가 보는 모든 대답은 구식입니다. 참조 : https://docs.djangoproject.com/ko/1.9/ref/class-based-views/generic-editing/ – guettli

답변

10

물론 반복을 피할 수 있습니다. 대부분의 경우, 사용할 양식 및 템플리트 이름 클래스, 유효한 양식이 제출 될 때 정리 된 데이터를 처리 할 수있는 호출자 및 이러한 처리 후 경로 재 지정을위한 대상을 인수로 전달해야합니다. 게다가 폼 클래스를 한 번 호출하여 바인딩 된 폼이나 언 바운드 폼을 생성하고 올바르게 처리하는 데 약간의 추가 코드가 필요합니다. 즉 :

def process_any_form(request, 
        form_class, template_file_name, 
        process_data_callable, redirect_destination): 

    form = form_class(request.POST if request.method == 'POST' else None) 

    if form.is_bound and form.is_valid(): 
     process_data_callable(form.cleaned_data) 
     return HttpResponseRedirect(redirect_destination) 

    return render_to_response(template_file_name, {'form': form}) 
+2

이것은 작동합니다. 템플릿이 단순한 'form'이상을 원한다면, 예를 들어 값 해시를 포함하도록 인수 목록을 넓혀야합니다. –

+0

s/hash/dict /하지만 그래, 좋은 생각 : 컨텍스트에 대해 미리 미리 채워진 dict d를 전달하고 dict (d, form = form)을 렌더링 컨텍스트로 사용하면 솔루션은 더욱 일반적입니다. –

2

폼을 처리하는 일반적인 방법은 결과를 편집하고 처리하기위한 양식 제시입니다. 이것을 두 개의 메소드로 분할 할 수 있는데, 이는 동일한 render_to_response() 호출 형태로 일부 중복을 도입합니다. 당신이 그것을 리팩토링 할 때까지, 은 위의 단일 메서드 양식보다 읽기 쉬운 것이 될 수 있습니다.

보일러 플레이트 방법을 보면 복제가 표시되지 않습니다. ContactForm()의 두 가지 용도는 분명히 다릅니다. 두 조건은 양식 처리와 관련된 상태 전환을 공정하게 보여주는 것 (공백 양식 제시, 유효한 제출, 프로세스 및 리디렉션).

0

모든 양식에 대한 조건부를 처리하는 함수를 작성할 수 있습니다. 당신은 같은 "is_valid"후 해당 양식에 함수의 특정을 전달하여이 작업을 수행 할 수 있습니다 :

def FormHandler(request, CleaningFunction, redirecturl): 
    if request.method = 'POST': 
     if request.method == 'POST': # If the form has been submitted... 
      form = ContactForm(request.POST) # A form bound to the POST data 
      if form.is_valid(): # All validation rules pass 
       CleaningFunction(form) # Process the data in form.cleaned_data 
       return HttpResponseRedirect('/thanks/') # Redirect after POST 
    else: 
     form = ContactForm() # An unbound form 
    return form 

그런 다음 당신은 당신의보기에서 FormHandler를 부를 것이다. 테스트되지 않았으므로 오류가있을 수 있습니다.

1

알렉스의 일반적인 핸들러는 나를 이길 수 있지만 FWIW 우리는 그의 제안의 낮은 일반 버전으로 경향 post_data가 없음이없는 경우

def contact(request): 
    post_data = request.POST if request.method == 'POST' else None 
    form = ContactForm(post_data) 
    if request.method == 'POST': 
     # perform normal validation checking, etc 

    return render_to_response('contact.html', { 
     'form': form, 
     }) 

, 다음 양식이있는 것으로 인스턴스화 무제한. 그렇지 않으면 바인딩 처리가 정상적으로 계속됩니다. 그것은 ContactForm의 중복 된 생성을 피하지만, 나는 Dave의 답변에 동의합니다. 왜냐하면 복제 구성이 생성 매개 변수가 다르기 때문에 복제본이 정확하게 복제되는 것을 방해하지 않는다는 것입니다.

1

나는 이것을 처리하는데 자신의 일반적인 견해를 썼다. 그 과정에서 django가 폼 처리를 위해 already has underdocumented generic views이라는 것을 발견했습니다. 그들은 문서화 된 일반 뷰의 상당히 직접적인 유사점이지만 양식을 승인하고 기본적으로 예제에서 사용한 것과 동일한 템플리트를 따릅니다. 궁극적으로, 나는 너무 유연하고 내 용도에 어리 석다는 것을 알았다. (나는 create_or_update 뷰를 원하지 않는다. 나는 두 가지 액션을 따로 다루지 않을 것이다.)

편집 : 당신은 Fragsworth의 대답을 좋아하지 않았다. 내가 말하는 것과 똑같은, 나는 너도 내가 좋아할 것 같아. 어떻게 작동하는지 예제가 있습니다.

# in urls.py 
urlpatterns += patterns("", 
    (u'^...$', 'django.views.generic.create_update.update', { 
     'form_class': ContactForm }) 
) 

ContactForm

은 폼 처리 로직이가는 save() 방법, 그리고 그게 전부가 있어야합니다.

0

당신은 django의 폼 모듈을 우회하여 그냥 옛날 방식으로 할 수 있습니다. 너무 많은 손실없이 더 많은 유연성을 얻을 수 있습니다.

장고 양식을 마지막으로 살펴본 것은 상당히 오래 전 일이 바뀌 었는지는 모르지만 예를 들어 아약스 스타일의 양식을 만들 수는 없다는 것을 알 수 있습니다. 적어도 쉽게는.

6

당신은 더 나은 될 수 맞아, 여기 (하지만 계속 읽기) 더 나은 대안이다 :

def contact(request): 
    form = ContactForm(request.POST or None) # A form bound to the POST data 
    if form.is_valid(): # All validation rules pass 
     # Process the data in form.cleaned_data 
     # ... 
     return HttpResponseRedirect('/thanks/') # Redirect after POST 

    return render_to_response('contact.html', { 
     'form': form, 
    }) 

이 조각은 DjangoCon11에서 Advanced Django Form Usage라는 말에서 비롯됩니다.

모든 필드가 선택 사항이고 CSRF 보호 기능을 사용하지 않는 경우이 옵션은 유효한 양식 (제출 전이라도)으로 처리됩니다. 위험을 제거하려면 다음을 사용하십시오.

def contact(request): 
    form = ContactForm(request.POST or None) # A form bound to the POST data 
    if request.method == 'POST' and form.is_valid(): # All validation rules pass 
     # Process the data in form.cleaned_data 
     # ... 
     return HttpResponseRedirect('/thanks/') # Redirect after POST 

    return render_to_response('contact.html', { 
     'form': form, 
    })