2014-02-13 1 views
1

inlineformset_factory 사용 단일 고객과 관련된 전화 번호를 추가/제거 할 수 있습니다. 문제는 각 고객에게 적어도 하나의 유효한 전화 번호가 필요하다는 것입니다. 이 꽤 정직하고, 그래서inlineformset_factory 최소 필요

class CustomerForm(ModelForm): 
    class Meta: 
     model = Customer 
     fields = ['name'] 

class PhoneNumberForm(ModelForm): 
    class Meta: 
     model = PhoneNumber 
     fields = ['number'] 

확인 :

모델 :

class Customer(models.Model): 
    name = models.CharField(max_length=255) 

class PhoneNumber(models.Model): 
    customer = models.ForeignKey(Customer) 
    number = models.CharField(max_length=10) 

양식 여기

몇 가지 데모 코드입니다. 그럼 내보기에 :

class Create(View): 
    template_name = 'path_to_template' 
    CustomerForm = forms.CustomerForm 
    PhoneNumberFormSet = inlineformset_factory (
     parent_model = Customer, 
     model = PhoneNumber, 
     form = PhoneNumberForm, 
     extra = 1, 
    ) 

    def get(self, request): 
     # Return empty forms 
     context = { 
      'customer_form': self.CustomerForm, 
      'phone_number_formset': self.PhoneNumberFormSet 
     } 
     render(request, self.template_name, context) 

    def post(self, request): 
     this_customer_form = self.CustomerForm(request.POST) 

     if this_customer_form.is_valid(): 
      new_customer.save(commit=False) 
      this_phone_number_formset = self.PhoneNumberFormSet(request.POST, instance=new_customer) 

      if this_phone_number_formset.is_valid(): 
       new_customer.save() 
       this_phone_number_formset.save() 
       return HttpResponseRedirect(reverse_lazy('customer-detail', kwargs={'pk': new_customer.pk})) 

     # Something is not right, show the forms again 
     this_phone_number_formset = self.PhoneNumberFormSet(request.POST) 
     context = { 
      'customer_form': this_customer_form, 
      'phone_number_formset': this_phone_number_formset 
     } 
     render(request, self.template_name, context) 

당신은 내가 생각하는 점을 얻는다. 고객의 편집/업데이트보기에서도 마찬가지입니다. 그런 다음에 만 양식이 미리 채워집니다.

이 시점에서 고객 당 적어도 하나의 유효한 PhoneNumber를 요구하는 방법이 필요합니다. https://stackoverflow.com/questions/2406537/django-formsets-make-first-required 에서

class RequiredFormSet(BaseFormSet): 
    def __init__(self, *args, **kwargs): 
     super(RequiredFormSet, self).__init__(*args, **kwargs) 
     for form in self.forms: 
      form.empty_permitted = False 

하지만 난 BaseInlineFormSet 클래스에 적용 할 때 작동하는 것 나던 : 내가 좋아하는 뭔가를 발견했다.

Django 1.7

어떤 아이디어 .. 지금까지 InlineModelFormSet 내 소원에 대답하는 것 같다,하지만?

+0

그냥 수 없습니다 내가 BaseInlineFormset를 서브 클래 싱하여 solution을 발견 보인다 PhoneNumber 클래스의 숫자 필드는 필수 필드입니까? – professorDante

+0

@professorDante blank = True로 모델 필드를 지정하지 않으면 기본적으로 필요합니다. [Django 문서] (https://docs.djangoproject.com/en/dev/ref/models/fields/#blank) –

답변

0

감사합니다. kezabella (django irc).

class RequiredFormSet(BaseInlineFormSet): 
    def clean(self): 
     for form in self.initial_forms: 
      if not form.is_valid() or not (self.can_delete and form.cleaned_data.get('DELETE')): 
       return 
     for form in self.extra_forms: 
      if form.has_changed(): 
       return 
     raise ValidationError("No initial or changed extra forms") 

, BTW 이러한 유효성 검사 오류가 {{formset.error}}에 표시되지 않지만에서 :

{{ formset.non_form_errors }}