2013-07-21 100 views
1

我正在編寫Django應用程序,需要使用AJAX請求更新模型,該請求僅包含模型字段的子集作爲鍵。所以,如果我有模型使用ModelForm更新Django模型的某些字段

class TheModel(models.Model): 
    a = models.CharField(max_length=16) 
    b = models.IntegerField() 
    c = models.TextField() 
    d = models.ManyToManyField(AnotherModel) 

然後我能得到請求像

id=7&a=Hello 
id=7&a=Test&b=123 
id=13&b=14&c=Description&d=6&d=10 

是,我總是會得到ID字段,但其他的任何子集。

我不能找到一個「好」的方式做到這一點在Django 1.5:首先我想

instance = get_instance_or_404(request["id"]) 
data = django.forms.models.model_to_dict(instance) 
data.update(request.POST) 
form = TheModelForm(data, instance=instance) 
if form.is_valid(): 
    form.save() 
    ... 
else: 
    ... 

,但這似乎並沒有與M2M領域很好地工作,而且model_to_dict感覺令我難以置信的醜陋。所以我也沒有

instance = get_instance_or_404(request["id"]) 
for k in TheModel._meta.fields: 
    if k in request: 
     setattr(instance, k, request[k]) 
try: 
    instance.full_clean() 
except ValidationError as e: 
    ... 
instance.save() 

但我不完全明白如何處理這裏的m2m領域。

在Django中有這樣做的習慣嗎?在此先感謝您的幫助。

+0

m2m字段由'model.m2m_field.add()'和'model.m2m_field.remove()'更新,這兩個函數都帶有一個arg,它是要添加或刪除的項目的實例。 –

+0

感謝您提供有用的提示,但是我真的很想找到一種方法來做到這一點,這與使用ModelForm中的所有數據創建模型實例一樣好,並且可以立即識別。如果沒有別的,我希望能夠通過主鍵添加到m2m_field,而不是通過實例來保存大量的樣板。 – Actorclavilis

回答

1

首先,GET請求不應該更新數據。他們只應該閱讀和顯示數據。您需要使用的HTTP方法是POSTThis answer值得一讀。

現在這樣做了,實現你想要的最好的方法是使用通用的UpdateView。下面是一些示例代碼:

# urls.py 
from views import UpdateTheModelView 

urlpatterns = patterns('', 
         url(r'^update-TheModel/(?P<pk>\d+)/?', 
         UpdateTheModelView.as_view(), 
         name='update_the_model'), 
) 


# forms.py 
from django import forms 
from models import TheModel 

class TheModelForm(forms.ModelForm): 
    class Meta: 
     model = TheModel 
     fields = ('a', 'b', 'c', 'd',) 


# views.py 
from django.core.urlresolvers import reverse 
from django.views.generic import UpdateView 
from models import TheModel 
from forms import TheModelForm 

class UpdateTheModelView(UpdateView): 
    model = TheModel 
    form_class = TheModelForm 
    template_name = 'themodel_form.html' 

    def get_success_url(self): 
     """ 
     Just here to redirect back to the update page when the form is posted 
     """ 
     return reverse('update_the_model', args=[self.object.id, ]) 

和一個簡單的例子模板在yourapp/templates/themodel_form.html顯示形式:所以現在,如果你有保存的1一個id TheModel實例

<form action="." method="post"> 
    {% csrf_token %} 
    {{ form.as_p }} 
    <input type="submit" value="Update" /> 
</form> 

,您可以查看通過登錄http://your-website.co.uk/update-TheModel/1/加載初始數據的更新表單,您可以通過點擊Update或向此頁面的URL發送POST請求(以及)來更新它,這可以通過jQuery或vanilla Javascript在後臺輕鬆完成。

+0

謝謝,但這不是我所需要的。具體來說,這種形式從不向任何用戶顯示(事實上,它甚至不是以HTML呈現的;這是服務器和客戶端應用程序之間的HTTP接口)。此外,如果我只向POST發佈一些字段,那麼表單驗證失敗,而我希望它使用數據庫中已有的值。 – Actorclavilis

+0

這不完全是你所需要的,不。不過稍微調整一下就可以了。您可以覆蓋UpdateView上的'get'方法,以便不返回HTML get,您還可以更改'ModelForm'以使某些字段可選。 – Matt