2013-08-26 39 views
0

我有一個Item對象與另一個對象Option有許多關係。我像這樣從Item對象創建一個模型表單;如何覆蓋django模型以實現自定義行爲

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。我如何重寫表單來實現這樣的行爲。例如,如果沒有表單,我可以通過它的id呈現Items自己的Optionsitem = Item.objects.get(pk=id)

+0

你能澄清你的問題嗎?你想動態地實現一個用戶想要的選項定義的表單嗎?或者只在用戶定義的模型中放置一個特定的選項? – agconti

+0

我認爲這個問題很好@conconti,當創建一個Item時,我還指定了屬於那個Item的'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文檔here

0

嘗試覆蓋表單的init方法並將Item pk作爲附加參數傳入。這裏的技巧是在調用父初始化之前彈出參數。

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) 

然後,在你看來,創建表單,如:

form = ItemOptionsForm(item_id=item_id) 

關於這樣做的好處是,你可以提高ValidationErrors會的形式顯示出來。

請注意,這並不妨礙某人將選項ID發佈到不屬於該項目的表單中,因此您可能希望重寫ModelForm.clean()以驗證選項。

0

從鏈接學習django: How to limit field choices in formset?由@jingo提供,我首先通過創建動態表單來解決問題,就像這樣;

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)) 
相關問題