User
を2つの異なるモデルUserProfile
とUser
に保存しました。 APIの観点からは、これら2つが異なることを誰も気にしません。
だからここに私は持っています:
class UserSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = User
fields = ('url', 'username', 'first_name', 'last_name', 'email')
そして
class UserPSerializer(serializers.HyperlinkedModelSerializer):
full_name = Field(source='full_name')
class Meta:
model = UserProfile
fields = ('url', 'mobile', 'user','favourite_locations')
したがって、UserPSerializer
のフィールドuser
は、そのリソースへのリンクにすぎません。しかし、ユーザーの観点から見ると、彼がUser
について知っている理由はまったくありません。
それらを一緒にマッシュしてユーザーに1つのモデルとして提示できるいくつかのトリックはありますか、それとも手動でこれを何らかの方法で行う必要がありますか?.
POSTおよびPUT @ kahloのアプローチ でPUTすることもできますが、シリアライザのcreateおよびupdateメソッドもオーバーライドする場合に限ります。
次のようなプロファイルモデルがあるとします。
class Profile(models.Model):
user = models.OneToOneField(User)
avatar_url = models.URLField(default='', blank=True) # e.g.
以下は、追加のプロファイルフィールドの読み取りと書き込みの両方を行うユーザーシリアライザーです。
class UserSerializer(serializers.HyperlinkedModelSerializer):
# A field from the user's profile:
avatar_url = serializers.URLField(source='profile.avatar_url', allow_blank=True)
class Meta:
model = User
fields = ('url', 'username', 'avatar_url')
def create(self, validated_data):
profile_data = validated_data.pop('profile', None)
user = super(UserSerializer, self).create(validated_data)
self.update_or_create_profile(user, profile_data)
return user
def update(self, instance, validated_data):
profile_data = validated_data.pop('profile', None)
self.update_or_create_profile(instance, profile_data)
return super(UserSerializer, self).update(instance, validated_data)
def update_or_create_profile(self, user, profile_data):
# This always creates a Profile if the User is missing one;
# change the logic here if that's not right for your app
Profile.objects.update_or_create(user=user, defaults=profile_data)
結果のAPIは、必要に応じてフラットなユーザーリソースを提供します。
GET /users/5/
{
"url": "http://localhost:9090/users/5/",
"username": "test",
"avatar_url": "http://example.com/avatar.jpg"
}
また、POSTとPUTリクエストの両方にプロファイルのavatar_url
フィールドを含めることができます(ユーザーリソースのDELETEを実行すると、Djangoの通常の削除カスケードであるにもかかわらず、プロファイルモデルも削除されます。 )
ここでのロジックは、alwaysが欠落している場合(更新時に)、ユーザーのプロファイルモデルを作成します。ユーザーとプロファイルでは、おそらくそれが必要です。他の関係の場合はそうではない可能性があり、更新または作成ロジックを変更する必要があります。 (これがDRF ネストされた関係を介して自動的に書き込まれない理由です を使用します。)
私はこれに出くわしました。特にUser
およびUserProfile
モデルに書き戻すための良い解決策はまだ見つけていません。現在、SerializerMethodField
を使用して手動でシリアライザをフラット化していますが、これは非常に苛立たしいことですが、機能します。
class UserSerializer(serializers.HyperlinkedModelSerializer):
mobile = serializers.SerializerMethodField('get_mobile')
favourite_locations = serializers.SerializerMethodField('get_favourite_locations')
class Meta:
model = User
fields = ('url', 'username', 'first_name', 'last_name', 'email', 'mobile', 'favourite_locations')
def get_mobile(self, obj):
return obj.get_profile().mobile
def get_favourite_locations(self, obj):
return obj.get_profile().favourite_locations
これは恐ろしく手動ですが、最終的には次のようになります。
{
"url": "http://example.com/api/users/1",
"username": "jondoe",
"first_name": "Jon",
"last_name": "Doe",
"email": "[email protected]",
"mobile": "701-680-3095",
"favourite_locations": [
"Paris",
"London",
"Tokyo"
]
}
それはあなたが探しているものだと思います。
フィールドが大きくならないので、UserPSerializer
に変更を実装します。
class UserSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = User
fields = ('url', 'username', 'first_name', 'last_name', 'email')
class UserPSerializer(serializers.HyperlinkedModelSerializer):
url = serializers.CharField(source='user.url')
username = serializers.CharField(source='user.username')
first_name = serializers.CharField(source='user.first_name')
last_name = serializers.CharField(source='user.last_name')
email = serializers.CharField(source='user.email')
class Meta:
model = UserProfile
fields = ('mobile', 'favourite_locations',
'url', 'username', 'first_name', 'last_name', 'email')