2011-09-15 3 views
4

MultiWidgets 및 MultiValueFields를 서브 클래 싱하여 양식을 작성하는 방법을 이해하려고합니다.MultiWidget 및 MultiValueField를 사용하여 양식 모델 저장

class Address(models.Model): 
    user = models.ForeignKey(User) 
    city = models.CharField(max_length=255) 
    state = models.CharField(choices = settings.STATES, max_length=50) 
    postal = models.CharField(max_length=10) 
    address = models.TextField() 

    class Meta: 
     verbose_name_plural = 'Addresses' 

class AddressFieldWidget(forms.MultiWidget): 
    def decompress(self,value): 
     if value: 
      return [value[0],value[1],value[2]] 
     return '' 

    def format_output(self, rendered_widgets): 
     str = '' 
     line_1 = '<td class="align_left"><label for="contact_phone">Address Line 1</label></td>' 

     for field in rendered_widgets: 
      str += '<tr>' + line_1 
      str += '<td class="align_right">%s</td></tr>' % field 
     return '<tr>' + str + '</tr>' 

    def value_from_datadict(self,data,files,name): 
     line_list = [widget.value_from_datadict(data,files,name+'_%s' %i) for i,widget in enumerate(self.widgets)] 
     try: 
      return line_list[0] + ' ' + line_list[1] + ' ' + line_list[2]  
     except: 
      return '' 

class AddressField(forms.MultiValueField): 
    def __init__(self,*args,**kwargs): 
     fields = (
      forms.CharField(widget=forms.TextInput(attrs={'class':'big'})), 
      forms.CharField(widget=forms.TextInput(attrs={'class':'big'})), 
      forms.CharField(widget=forms.TextInput(attrs={'class':'big'})), 
     ) 
     super(AddressField,self).__init__(*args,**kwargs) 
     self.widget = AddressFieldWidget(widgets=[fields[0].widget, fields[1].widget, fields[2].widget]) 

    def compress(self, data_list): 
     return data_list[0] + ' ' + data_list[1] + ' ' + data_list[2] 


class AddressFormNew(forms.ModelForm): 
    postal = forms.CharField(widget=forms.TextInput(attrs={'class':'small'})) 
    address = AddressField() 
    city = forms.CharField(widget=forms.TextInput(attrs={'class':'big'})) 

    class Meta: 
     model = Address 

그럼 내가보기에이 양식을 사용하는 방법을 알아낼 수 없습니다 : 나는 간단한 주소 모델과 관련된 형태를 가지고있다. 내가 할 노력하고있어 :

@login_required 
def render_addresses(request): 
    address_form = AddressFormNew() 
    if request.method == 'POST': 
     address_form = AddressFormNew(request.POST) 
     if address_form.is_valid(): 
      address_form.save() 
      return HttpResponse('ok') 
     else: 
      return HttpResponse(address_form.errors['address']) 

    return render_to_response('profile/addresses.html',context_instance=RequestContext(request,{'address_form':address_form})) 

을 결과, 장고 나에게이 오류 준다 : 나는 request.POST.items()를 인쇄 할 때 또한

Enter a list of values.

를, 그것은 주소 응답을 제공합니다 3 개의 분리 된 데이터로.

저는 여기서 분실했습니다. 한 줄에 주소 데이터를 가져와야합니다. 양식을 저장하면 어떻게하면됩니까?

누군가가 나에게 명확한 설명을 주시면 정말로 감사하겠습니다.

답변

0

난 당신이 또한 압축 해제 방법이 필요하다고 생각하고, __init__

+0

내가 decompress 방법을 가지고, 내가 생각하는 value_from_datadict 문제가 발생하지만 난 그것을 사용하는 방법을 몰라? – iva123

-1

의 장고의 소스 파일은 종종 영감의 좋은 소스가 될 수 밖에 필드 = (...)해야한다. (Pun은 의도하지 않음) 예를 들어 django.forms.fields.SplitDateTimeField을 확인할 수 있습니다.이 예제는 비슷한 작업을 수행하는 방법을 보여줍니다.

초기화 할 때 (super(AddressField,self).__init__()) self.widget을 설정하는 중 일부 오류가 발생할 수 있으므로이 필드는 표준 위젯 만 사용합니다. 그리고 fields__init__과 함께 보내지 않았습니다. 나는 솔직히 아주 당신이 뭘하려고했는지 이해하지 못하기 때문에

class AddressField(forms.MultiValueField): 
    widget = MultiValueWidget(widgets=(forms.TextInput, forms.TextInput, forms.TextInput) 
    def __init__(self, *args, **kwargs): 
     fields = (
      forms.CharField(widget=forms.TextInput(attrs={'class':'big'})), 
      forms.CharField(widget=forms.TextInput(attrs={'class':'big'})), 
      forms.CharField(widget=forms.TextInput(attrs={'class':'big'})), 
     ) 
     super(AddressField,self).__init__(fields, *args, **kwargs) 

    def compress(self, data_list): 
     return "%s %s %s" % data_list[0:2] 

이것은 당신이 AddressFieldWidget에 있었다 모든 미신적 점보를 제외 :)

: 여기 당신이 AddressField을 할 수 있다고 생각하는 방법의 빠른 초안입니다
4

다음은 코드에서 해결해야하는 문제입니다.

(1). 주소록 메서드에서 수퍼 클래스의 을 호출 할 때는 필드을 인수로 전달해야합니다.

class AddressField(forms.MultiValueField): 
    def __init__(self,*args,**kwargs): 
     fields = (
      forms.CharField(widget=forms.TextInput(attrs={'class':'big'})), 
      forms.CharField(widget=forms.TextInput(attrs={'class':'big'})), 
      forms.CharField(widget=forms.TextInput(attrs={'class':'big'})), 
     ) 
     self.widget = AddressFieldWidget(widgets=[fields[0].widget, fields[1].widget, fields[2].widget]) 
     super(AddressField,self).__init__(fields=fields,*args,**kwargs) 

(2). 당신이 맞습니다, 귀하의 value_from_datadict가 올바르지 않습니다. 요점은 MultiValueField를 사용하여 위젯이 채워지는 것입니다. 그래서 위젯이 AddressField

에서 해당 서브 필드에 값 목록을 반환해야하는 것은

당신은 방금 value_from_datadict하여 슈퍼 클래스의 호출 할 수 있습니다 그리고 그 일을 할, 또는 내가 생각하는이 (사용합니다 동일) :

def value_from_datadict(self,data,files,name): 
    res = [] 
    for i, widget in enumerate(self.widgets): 
     res.append(widget.value_from_datadict(data, files, name + '_%s' % i)) 
    return res 

기본 개념을 이해하는 것이 중요합니다. 이 위젯을 CharField와 함께 사용할 수도있었습니다. 이 경우 value_from_datadict는 문자열을 반환해야합니다. 그러나 MultiValueField를 사용하고 있으므로 반환 유형은 목록이어야합니다.그것이 "값 목록을 오류로"입력하게 된 바로 그 이유입니다.

저장된 값으로 주소 1, 2 및 3을 다시 작성할 계획이라면 단락 기호로 공백을 사용하지 마십시오. 데이터베이스에서 양식으로. 그렇지 않다면 모두 좋다 :)

문서 나 인터넷에서 MultiValueField 및 MultiWidget에 대한 좋은 예는 찾지 못했지만 프로젝트 중 하나에서 사용했기 때문에 직접 파고 들어야했다. 희망이 도움 :)