シリアライザーを使用してDjango RestフレームワークでAPIを作成するときに混乱します。save()、create()、update()メソッドの正確な違いを教えてください。私のコードサンプルは次のとおりです。
View.py
class AddUser(views.APIView):
serializer_class = UserForAdminSerializer
def post(self, request, *args, **kwargs):
serializer = UserForAdminSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
serializers.py
class UserForAdminSerializer(serializers.ModelSerializer):
first_name = serializers.CharField(max_length=30)
last_name = serializers.CharField(max_length=30)
name = serializers.CharField(max_length=30)
password = serializers.CharField(max_length=20, style={'input_type': 'password'})
class Meta:
model = User
fields = ('id', 'url', 'first_name', 'last_name', 'name', 'username', 'email', 'password',
'total_exp_year', 'total_exp_month', 'voteup_count', 'is_featured',
'is_active', 'headline', 'description', 'profile_picture', )
def create(self, validated_data):
password = validated_data.pop('password', None)
instance = self.Meta.model(**validated_data)
if password is not None:
instance.set_password(password)
instance.save()
return instance
上記のview.pyファイルのコードでは、save()メソッドとserializers.pyを使用してsave()またはupdate()メソッドを使用しているので、その動作を説明し、save()とcreate()の混乱を解消してください。
通常、コードをよく理解するための最良の方法は、実際にコードを読むことです。そこで、 source を見てみましょう。
_class BaseSerializer(Field):
...
def update(self, instance, validated_data):
raise NotImplementedError('`update()` must be implemented.')
def create(self, validated_data):
raise NotImplementedError('`create()` must be implemented.')
def save(self, **kwargs):
...
... a lot of assertions and safety checks ...
...
validated_data = dict(
list(self.validated_data.items()) +
list(kwargs.items())
)
if self.instance is not None:
self.instance = self.update(self.instance, validated_data)
....
else:
self.instance = self.create(validated_data)
...
return self.instance
_
さて、この基本クラスのメソッドでは、update
とcreate
は実装される具体的なサブクラスに任されています(詳細はListSerializer
やModelSerializer
などのシリアライザーによって異なるため)。
ただし、save
isが実装されており、基本的にはオブジェクトが新規か既存か(_if self.instance is not None
_)をチェックし、それぞれupdate
またはcreate
を呼び出します。 このコードは、他のすべてのシリアライザーで呼び出されます。
具体的なサブクラスを見てみましょう。
_def create(self, validated_data):
...
... some stuff happening
...
try:
# Here is the important part! Creating new object!
instance = ModelClass.objects.create(**validated_data)
except TypeError:
raise TypeError(msg)
# Save many-to-many relationships after the instance is created.
if many_to_many:
for field_name, value in many_to_many.items():
set_many(instance, field_name, value)
return instance
def update(self, instance, validated_data):
raise_errors_on_nested_writes('update', self, validated_data)
info = model_meta.get_field_info(instance)
# Simply set each attribute on the instance, and then save it.
# Note that unlike `.create()` we don't need to treat many-to-many
# relationships as being a special case. During updates we already
# have an instance pk for the relationships to be associated with.
for attr, value in validated_data.items():
if attr in info.relations and info.relations[attr].to_many:
set_many(instance, attr, value)
else:
setattr(instance, attr, value)
instance.save()
return instance
_
ご覧のとおり、create
とupdate
の両方を呼び出して、set_many(instance, attr, value)
を呼び出してオブジェクト属性の値を設定します。ただし、create
は、ModelClass.objects.create(**validated_data)
の前に1つのcritical呼び出しを実行します。これにより、実際に新しいインスタンスが作成されます。
これで少しクリアになるといいのですが。
Django Rest Framework documentation では、saveメソッドをオーバーライドするタイミングとcreateメソッドをいつオーバーライドするかを非常に明確に説明しました。
私はあなたの便宜のために彼らの説明をここに投稿しています
場合によっては、.create()および.update()メソッド名が意味をなさないことがあります。たとえば、お問い合わせフォームでは、新しいインスタンスを作成するのではなく、メールやその他のメッセージを送信する場合があります。このような場合は、読みやすく意味のあるものとして、代わりに.save()を直接オーバーライドすることを選択できます。
例:-
class ContactForm(serializers.Serializer):
email = serializers.EmailField()
message = serializers.CharField()
def save(self):
email = self.validated_data['email']
message = self.validated_data['message']
send_email(from=email, message=message)