Как я могу сериализовать поле Many to Many с добавленными данными в Django Rest Framework, без дополнительных ключей в ответе?
Я использую Django 3.2 и Django Rest Framework 3.14.
У меня есть пользователи, которые должны иметь возможность следить за другими пользователями, как в социальных сетях. При сериализации полного пользователя я хотел бы получить список тех пользователей, которые следуют за ним, а также дополнительные данные, такие как время следования. Однако я хотел бы, чтобы ответ оставался "плоским", например, таким:
{
"username":"admin",
"followers":[
{
"username":"testuser",
--additional user fields--
"follow_date":"2023-02-08 01:00:02"
},
--additional followers--
],
--additional user fields--
}
Я могу пройти "через" мою модель join только с помощью дополнительного сериализатора, и в итоге получаю следующее:
{
"username":"admin",
"followers":[
{
"user":{
"username":"testuser",
--additional user fields--
},
"follow_date":"2023-02-08 01:00:02"
},
--additional followers--
],
--additional user fields--
}
Обратите внимание, что есть дополнительная клавиша user
"user":{
"username":"testuser",
--additional user fields--
},
Я не хочу, чтобы это было там!
Моя модель выглядит примерно так:
class Follower(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.RESTRICT, related_name="followers")
follower = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.RESTRICT, related_name="following")
follow_date = models.DateTimeField(auto_now_add=True)
Мои сериализаторы выглядят следующим образом (лишние поля обрезаны для краткости):
class UserSnippetSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ['username']
class FollowerSerializer(serializers.ModelSerializer):
user = UserSnippetSerializer(source='follower')
class Meta:
model = Follower
fields = ['user', 'follow_date']
class FullUserSerializer(serializers.ModelSerializer):
followers = FollowerSerializer(source='user.followers', many=True)
following = FollowerSerializer(source='user.following', many=True)
class Meta:
model = Profile
fields = ['username', 'followers', 'following']
Учитывая это, я понимаю, почему он делает то, что делает. Но я не могу найти способ пропустить дополнительный ключ user
и при этом включить информацию о пользователе и follow_date
.
Я пробовал играть с прокси-моделями на User, но это, похоже, не помогло. Я подозреваю, что дело не в конфигурации, хотя мне бы хотелось, чтобы это было так, и что мне нужно переопределить какую-то внутреннюю функцию. Но я не могу найти, что это может быть.
Какой лучший (и, надеюсь, самый простой!) способ достичь этого?
Один из подходов заключается в использовании поля метода сериализатора на FollowerSerializer
следующим образом:
class FollowerSerializer(serializers.ModelSerializer):
username = serializers.SerializerMethodField()
class Meta:
model = Follower
fields = ['username', 'follow_date']
def get_username(self, obj):
return obj.username
или если у вас много полей для отображения у пользователя, вы также можете переопределить to_representation
следующим образом:
class FollowerSerializer(serializers.ModelSerializer):
user = UserSnippetSerializer(source='follower')
class Meta:
model = Follower
fields = ['user', 'follow_date']
def to_representation(self, instance):
data = super().to_representation(instance)
user_data = data.pop("user")
# flatten the follower data with the user data
return {
**data,
**user_data,
}
Обратите внимание, что это также повлияет на FullUserSerializer.following