2011-11-21 9 views
9

POSTリクエストに1つのフィールドがパラメータとして含まれている場合、ModelFormを使用してインスタンスの1つのフィールドを更新するにはどうすればよいですか? ModelFieldは、POST要求で渡されなかったフィールドを、Noneを使用してデータを失うことでオーバーライドしようとします。DjangoはModelFormを使用して1つのフィールドを更新します

私は25個のフィールドを持つモデルを持っているが

class C(models.Model): 
    a = models.CharField(max_length=128) 
    b = models.CharField(max_length=128) 
    ... 
    x = models.IntegerField() 

を言うと、私はviews.py

で公開APIメソッドを使用してCのインスタンスを編集するために、POSTリクエストを行い、デスクトップアプリケーションを持っています私は次のようにフィールドを検証するためのModelFormを使用していますAPIメソッドで

form = CModelForm(request.POST, instance=c_instance) 
if form.is_valid(): 
    form.save() 

は(SAVE行う場合)のいずれかDjangoは他のいくつかのフィールドがO nullにすることはできませんと文句を言いr(すべてのフィールドがオプションの場合)は、Noneで上書きされます。

誰かがそれを管理する方法を知っていますか?私は次のように、これらのフィールドを指定してのModelForm内のフィールドのサブセットを使用することができます...

答えて

7

を手動ですべてのチェックを行うと、手動で更新しますが、モデルは、フィールドのように気まぐれに長いリストがあります:

class PartialAuthorForm(ModelForm): 
    class Meta: 
     model = Author 
     fields = ('name', 'title') 
ドキュメントから

あなたがフィールドを指定するかのModelFormでフォームを作成する際に除外した場合は、結果の形式ではありません その後、フィールドは フォームのsave()メソッドによって設定されることはありません。

https://docs.djangoproject.com/en/dev/topics/forms/modelforms/#using-a-subset-of-fields-on-the-form

+7

問題は、私は次のとおりです。

データを更新するために、フォームの__init__方法を変更:

class MyModelSerializer(serializers.ModelSerializer): class Meta: model = MyModel fields = '__all__' class MyModelDetail(generics.RetrieveUpdateAPIView): queryset = MyModel.objects.all() serializer_class = MyModelSerializer 

10

これは考え出しました。私がしているのは、インスタンスからの値でrequest.POST辞書を更新することです。変更されていないすべてのフィールドが自動的に表示されるようにします。これは、それを行います。

from django.forms.models import model_to_dict 
from copy import copy 

def UPOST(post, obj): 
    '''Updates request's POST dictionary with values from object, for update purposes''' 
    post = copy(post) 
    for k,v in model_to_dict(obj).iteritems(): 
     if k not in post: post[k] = v 
    return post 

、その後、あなただけの操作を行います。

form = CModelForm(UPOST(request.POST,c_instance),instance=c_instance) 
+1

kがManyToManyフィールドを表す場合、これは機能しません。 – Erik

1

DjangoのModelFormは、モデルのフィールドの任意のサブセットの部分更新を処理するように設計されていません。

APIに当てはまるデスクトップアプリケーションであるOPによって記述されたユースケースは、Django Rest Frameworkでよりよく処理されます。

具体的には、ModelSerializerを継承するシリアライザを作成し、UpdateAPIViewで使用します。 DRFのシリアライザは、Djangoのフォームに似ています。

本当に素晴らしいライブラリであるDRFに別の依存関係を追加しても構いませんが、これはおそらく独自の解決策です。

import urllib 

from django import forms 
from django.http import QueryDict 
from django.forms.models import model_to_dict 

class MyModelForm (forms.ModelForm): 
    class Meta: 
     model = MyModel 

    def __init__ (self, *args, **kwargs): 
     super(MyModelForm, self).__init__(*args, **kwargs) 

     # if form has being submitted and 
     # model instance exists, then get data 

     if self.is_bound and self.instance.pk: 

      # get current model values 
      modeldict = model_to_dict(instance) 
      modeldict.update(self.data.dict()) 

      # add instance values to data 
      urlencoded = urllib.urlencode(modeldict) 
      self.data = QueryDict(urlencoded) 
0

は、私が(多対多フィールドでは動作しない場合があります)ローマSEMKOの答えに、この類似したが、解決しました -/
関連する問題