2016-08-22 2 views
0

Каков правильный способ обработки формы Django в представлении, если вы не знаете, какую форму ожидать при вводе вида? У меня есть мнение, которое определяет тип формы рендер на основе переменной сеанса:Обработка формы Django при наличии нескольких возможностей?

# views.py 
def enter_location(request): 
    country = request.session['country'] 
    if request.method == "POST": 
     if country == 'US': 
      form = USLocationForm(request.POST) 
     elif country == 'GB': 
      form = GBLocationForm(request.POST) 
     elif country == 'CA': 
      form = CALocationForm(request.POST) 
     else: 
      form = OtherLocationForm(request.POST)  
     if form.is_valid(): 
      # do stuff... 
      pass 
    else: 
     if country == 'US': 
      form = USLocationForm(initial={'country': country}) 
     elif country == 'GB': 
      form = GBLocationForm(initial={'country': country}) 
     elif country == 'CA': 
      form = CALocationForm(initial={'country': country}) 
     else: 
      form = OtherLocationForm(initial={'country': country}) 
    context = {'form': form} 
    return render(request, template, context) 

Очевидно, что это некрасиво код и не масштабироваться как я добавить больше стран. Я пытался сохранить мой взгляд коротким путем определения типа формы с помощью вспомогательной функции:

# views.py 
from location.forms import LocationForm 
def enter_location(request): 
    country = request.session['country'] 
    if request.method == "POST": 
     form = LocationForm.get_form(country) 
     submitted_form = form(request.POST) 
     if submitted_form.is_valid(): 
      # do stuff... 
      pass 
    else: 
     form = LocationForm.get_form(country) 
    context = {'form': form} 
    return render(request, template, context) 

# location/forms.py 
class LocationForm(forms.Form): 
    country = forms.ChoiceField(choices = choices.COUNTRIES_AND_EMPTY,) 
    city = forms.CharField() 
    email = forms.EmailField() 

    @staticmethod 
    def get_form(country): 
     if country == 'US': 
      return form = USLocationForm(initial={'country': country}) 
     elif country == 'GB': 
      return form = GBLocationForm(initial={'country': country}) 
     elif country == 'CA': 
      return form = CALocationForm(initial={'country': country}) 
     else: 
      return form = OtherLocationForm(initial={'country': country}) 

Проблема заключается в том, что при запуске вид, я получаю «TypeError„объект „USLocationForm“ не вызываемая“» в строке :

submitted_form = form(request.POST) 

Это также происходит, когда страна является «GB» или «CA», и выбрана соответствующая форма. Я запустил отладчик и сделал «type (form)», используя оба представления, и атрибуты формы кажутся одинаковыми в любом случае. Есть ли что-то другое, когда вы сначала создаете экземпляр формы в блоке GET, а не создаете его снова во время POST, а затем заполняете его опубликованными данными? Каков способ Django справиться с этой ситуацией, когда можно выбрать одну из многих возможных форм?

Спасибо.

ответ

1

Для этого не существует «правильного пути», но одна вещь, которую вы можете сделать для консолидации, - это использовать сопоставление.

Пример:

form_mappings = { 
    'US': USLocationForm, 
    'GB': GBLocationForm, 
    #... 
} 

def enter_location(request): 
    country = request.session['country'] 
    country_form = form_mappings.get(country, OtherLocationForm) 

    if request.method == "POST": 
     form = country_form(request.POST) 
     #... 
    else: 
     form = country_form(initial={'country': country}) 

Таким образом, вы можете расширить код для дальнейших стран, и не должны изменять код на всех ..

+0

Спасибо за обмен этой техники! Он одинаково хорошо подходит для выбора соответствующего шаблона, который также зависит от страны. – William

Смежные вопросы