2013-08-26 3 views
0

다른 객체에 manytomany 관계가있는 Item 객체가 있습니다. Option. Item 객체에서 modelform을 생성합니다. 내가 템플릿에서 폼을 렌더링 할 때django modelform을 오버라이드하여 사용자 정의 동작을 얻는 방법

class Item(models.Model): 
    category = models.ForeignKey(Category) 
    name = models.CharField(max_length=200) 
    price = models.DecimalField(max_digits=9, decimal_places=2, blank=True, null=True) 
    options = models.ManyToManyField(Option) 
class OptionForm(ModelForm): 
    options = forms.ChoiceField(widget=forms.RadioSelect()) 
    class Meta: 
     model = Item 
     fields = ('options',) 

은 심지어 특정 항목에 의해 생성하는하지 Item 객체 (예상되는 동작)에 사용할 수있는 모든 options를 렌더링합니다. 나는 사용자가 선택한 특정 항목에 의해 정의 된 options을로드 할 수 있기를 원합니다. 어떻게해야합니까 양식과 같은 동작을 달성하기 위해 양식을 재정의하십시오. 나는 Items 자신의 Options 해당 ID를 렌더링 할 수있는 양식없이 예를 들어. item = Item.objects.get(pk=id)

+0

질문을 명확하게 할 수 있습니까? 사용자가 원하는 옵션으로 정의 된 양식을 동적으로 구현 하시겠습니까? 또는 사용자가 정의한대로 특정 선택 세트 만 모델에 넣을 수 있습니까? – agconti

+0

나는 질문이 괜찮다고 생각한다. @ agconti, 아이템을 만들 때, 그 아이템에 속한'options'도 지정한다. –

+0

왜 옵션을 제한 하시겠습니까? – agconti

답변

0

ModelForm은 모델의 구조와 밀접하게 연결되어 있으므로 즉시 정의 할 수 있습니다. 그럼에도 불구하고 원하는 효과를 얻기 위해 영리한 템플릿 제어 흐름과 렌더링 렌더링을 사용할 수 있습니다. 이것은 테스트되지 않았으므로 이것과 병합 할 수 있습니다.

<form method="post" action=""> 
    {{ formset.management_form }} 
    {% for form in formset %} 
     {{ form.id }} 
     <ul> 
    {% if user_option.category %} 
      <li>{{ form.caregory }}</li> 
    {% endif %} 
    {% if user_option.name %} 
      <li>{{ form.name }}</li> 
    {% endif %} 
    {% if user_option.p_opt %} 
      <li>{{ form.price }}</li> 
      <li>{{ form.options }}</li> 
    {% endif %} 
     </ul> 
    {% endfor %} 
</form> 

Djano docs here에서.

0

양식의 init 메소드를 재정의하고 Item pk를 추가 인수로 전달하십시오. 여기에있는 속임수는 부모 init을 호출하기 전에 인수를 팝하는 것입니다. 이것에 대해 좋은 점은 양식에 표시됩니다 ValidationErrors를 제기 할 수 있다는 것입니다

form = ItemOptionsForm(item_id=item_id) 

:

class ItemOptionsForm(forms.ModelForm): 
    class Meta: 
     model = Item 

    def __init__(self, *args, **kwargs): 
     # pop 'item_id' as parent's init is not expecting it 
     item_id = kwargs.pop('item_id', None) 

     # now it's safe to call the parent init 
     super(ItemOptionsForm, self).__init__(*args, **kwargs) 

     # Limit options to only the item's options 
     if item_id: 
      try: 
       item = Item.objects.get(id=item_id) 
      except: 
       raise ValidationError('No item found!') 

      self.fields['options'] = forms.ChoiceField(item.options) 

그런 다음보기에서 같은 양식을 만들 수 있습니다.

이것은 사용자가 항목에 속하지 않는 양식에 옵션 ID를 게시하는 것을 방지하지 않으므로 옵션 유효성을 검사하기 위해 ModelForm.clean()을 재정의하려는 것이 좋습니다.

0

@jingo가 제공 한 django: How to limit field choices in formset? 링크에서 학습하면, 나는 먼저 이와 같이 동적 인 형태를 만드는 것으로 문제를 해결했습니다.

def partial_order_item_form(item): 
    """dynamic form limiting optional_items to their items""" 
    class PartialOrderItemform(forms.Form): 
     quantity = forms.IntegerField(widget=forms.TextInput(attrs={'size':'2', 'class':'quantity','maxlength':'5'})) 
     option = forms.ModelChoiceField(queryset=OptionalItems.objects.filter(item=item),widget= forms.RadioSelect()) 

    return PartialOrderItemform 

그런 다음 유효 형식을 확인하십시오.

def show_item(request,id): 
    option = get_object_or_404(Item,pk=id) 
    if request.method == 'POST': 
     form = partial_order_item_form(option) 
     #bound form to POST data, 
     final_form = form(request.POST) 
     # check validation of posted data 
     if final_form.is_valid(): 
      order.add_to_order(request) 
      url =urlresolvers.reverse('order_index',kwargs={'id':a.id}) 
      # redirect to order page 
      return HttpResponseRedirect(url) 
    else: 
     form = partial_order_item_form(item=id) 
    context={ 
     'form':form, 
    } 
    return render_to_response('item.html',context,context_instance=RequestContext(request)) 
관련 문제