2013-01-21 2 views
3

formset을 사용하여 추가 필드를 생성하지만 formset에서 생성 된 추가 필드의 레이블을 변경하는 방법을 모르겠습니다.Django : formset extra를 사용하여 레이블을 변경하는 방법?

내 코드 :

class GetMachine(forms.Form): 
    Number_of_Lines = forms.IntegerField(max_value=4) 

class GetLine(forms.Form): 
    beamline_name = forms.CharField(max_length=15, label='Name of Beamline-%i') 

def install(request): 
    MachineFormSet = formset_factory(GetMachine, extra=1) 
    formset = MachineFormSet() 
    if request.method == 'POST': 
#  formset = MachineFormSet(request.POST) 
#  if formset.is_valid(): # All validation rules pass 
     line_no = request.POST['form-0-Number_of_Lines'] 
     GetLineFormSet = formset_factory(GetLine, extra=int(line_no)) 
     formset = GetLineFormSet() 
     return render_to_response('install.html', { 'formset': formset, 'action': 'step1'}) 
    return render_to_response('install.html', { 'formset': formset, })  

install.html 템플릿 다음 "NUMBER_OF_LINES"= 2, 그때 내가 레이블 다음 양식을 기대 예를 들어

{% for form in formset.forms %} 
{% for field in form %} 
    <tr> 
     <td>{{ field.label_tag }}</td> <td>{{ field }}</td><td>{{ field.errors }}</td> 
    </tr> 
{% endfor %} 
{% endfor %} 

,

Name of Beamline-1: 
Name of Beamline-2: 

답변

4

같은 일을 할, 당신은 Django form wizards로 볼 수도 있습니다. 그러나 여기 간단한, 비 폼 마법사 (그리고 아마도 덜 이상적인/유지 보수) 방법은 폼 라벨 * 수정하려면 해당 formset의 __init__ 방법을 활용, 그것을 할 :


forms.py :

# File: forms.py 
from django import forms 
from django.forms.formsets import BaseFormSet 


# What you've called 'GetMachine' 
class MachineForm(forms.Form): 
    no_of_lines = forms.IntegerField(max_value=4) 


# What you've called 'GetLine' 
class LineForm(forms.Form): 
    beamline_name = forms.CharField(max_length=15, label='Name of Beamline') 


# Create a custom formset and override __init__ 
class BaseLineFormSet(BaseFormSet): 
    def __init__(self, *args, **kwargs): 
     super(BaseLineFormSet, self).__init__(*args, **kwargs) 
     no_of_forms = len(self) 
     for i in range(0, no_of_forms): 
      self[i].fields['beamline_name'].label += "-%d" % (i + 1) 

views.py :

# File: views.py 
from django.forms.formsets import formset_factory 
from django.shortcuts import render_to_response 
from django.template import RequestContext 
from django.http import HttpResponseRedirect 
from django.core.urlresolvers import reverse 
from forms import MachineForm, LineForm, BaseLineFormSet 


def get_no_of_lines(request): 
    if request.method == 'POST': 
     machine_form = MachineForm(request.POST) 
     if machine_form.is_valid(): 
      # At this point, form fields have already been 
      # converted to Python data types :) 
      # so no need to convert `line_no` to an integer 
      no_of_lines = machine_form.cleaned_data['no_of_lines'] 
      return HttpResponseRedirect(reverse('line_form', kwargs={'no_of_lines': no_of_lines})) 
    else: 
     # It looks to me like you probably don't mean to 
     # use formsets here (but a form instead) 
     machine_form = MachineForm() 

    c = RequestContext(request, { 
     'machine_form': machine_form, 
    }) 
    return render_to_response('get_no_of_lines.html', c) 


def line_form(request, no_of_lines): 
    # You probably should validate this number (again). 
    # In fact, you probably need to validate first form (MachineForm). 
    # ...But I'm assuming it'll be valid in this example. 
    no_of_lines = int(no_of_lines) 
    LineFormSet = formset_factory(LineForm, extra=no_of_lines, formset=BaseLineFormSet) 
    if request.method == "POST": 
     formset = LineFormSet(request.POST, request.FILES) 
     if formset.is_valid(): 
      pass 
      # Do stuff with form submission 
      # Redirect 

    else: 
     formset = LineFormSet() 

    c = RequestContext(request, { 
     'formset': formset, 
    }) 
    return render_to_response('line_form.html', c) 

urls.py :

from django.conf.urls import url, patterns 
from views import get_no_of_lines, line_form 


urlpatterns = patterns('', 
    url(r'^$', get_no_of_lines, name='get_no_of_lines'), 
    url(r'^line_form/(?P<no_of_lines>\d{1})$', line_form, name='line_form'), 
) 

get_no_of_lines.html :

<form method="POST"> 
{% csrf_token %} 
{{ machine_form }} 
</form> 

line_form.html : 유효성을 검사하기 때문에

<form method="POST"> 
{% csrf_token %} 
{{ formset.as_p }} 

나는이 방법은 아마 이렇게하는 가장 좋은 방법이 아니라고 이유는 no_of_linesline_form보기로 전달됩니다 (4보다 클 수 있으므로 여기에서 유효성 검사를 수행하고 양식 대신에 유효성 검사 논리를 도입해야합니다). 첫 번째 양식에 새 필드를 추가해야하는 경우 코드를 수정해야 할 수 있습니다. 그래서 나는 왜 form wizards을 조사 할 것을 권하고 싶습니다.


0

내가 생각할 수있는 유일한 방법은이 동작을 수행하기 전에 바로보기에서 FormSet을 조정하는 것입니다. 귀하의 템플릿에 엉덩이.

다른 양식과 레이블을 반복하고 그에 따라 값을 변경할 수 있습니다.

다른 해결책은 기본 레이블을 "빔라인 이름"으로 설정하는 것입니다. 그리고 템플릿에 난 당신이 필드와 두 번째의 자신의 레이블 수를 결정하는 첫 번째 양식의 결과를 원하는 있으리라 믿고있어

{% for field in form %} 
    <td>{{ field.label_tag }}{{ forloop.counter1 }}</td> 
{% endfor %} 
+0

카운터를 사용하면 카운터 1,1을 사용하는 경우에는 아무 것도 일어나지 않습니다. counter0을 사용하면 두 레이블 모두에 0,0이 표시됩니다. 나는 왜 이런 일이 일어나는 지 이해하지 못한다! – Thiru

관련 문제