Мне нужно было расширить пользовательскую модель, чтобы добавить такие вещи, как адрес, счет, другие user_types и т. Д. Есть 2 возможных способа добиться этого, расширить пользовательскую модель или создать новую модель, которая будет связана с целевым пользователем с помощью OneToOneField
. Я решил пойти с новой моделью, потому что она казалась проще и рекомендуется в этом вопросе переполнения стека. Но теперь я не могу создать Serializer без вложенного поля профиля, которое, кроме того, недокументировано, потому что генератор документации rest_framwork по умолчанию не может генерировать документацию для вложенных сериализаторов.
Мой UserSerializer
выглядит так:
class UserSerializer(serializers.ModelSerializer):
# This creates a nested profile field
profile = ProfileSerializer(required=True)
def create(self, validated_data):
profile_data = validated_data.pop('profile')
user = User.objects.create_user(**validate_data)
profile, created = Profile.objects.upodate_or_creeate(user=user, defaults=profile_data)
return user
class Meta:
model = User
fields = ('id', 'username', 'email', 'password', 'buckelists', 'profile')
read_only_fields = ('id',)
extra_kwargs = {'password':{'write_only': True}}
Этот сериализатор принимает следующий формат JSON:
{
'name': ...,
'email': ...,
'password': ...,
'profile': {
'address': ...,
'score': ...,
'user_type': ...,
'achievements': ...,
'country': ...,
'trusted': ...,
}
Это выглядит странно, а документация, сгенерированная с помощью rest_framework.documentation.include_docs_urls
, показывает следующее:
{
'username': ...,
'email': ...,
'password': ...,
'field': ...,
}
Так что не понятно, что следует включать в поле профиля. Я хотел бы создать сериализатор, который бы принял следующий формат:
{
'name': ...,
'email': ...,
'password': ...,
'address': ...,
'score': ...,
'user_type': ...,
'achievements': ...,
'country': ...,
'trusted': ...,
}
Возможно ли это без создания собственного сериализатора с нуля? Или, по крайней мере, можно создать документацию для вложенных сериализаторов.
PS: я использую python3.6 и Django 2.1
EDIT:
Вот соответствующая часть моего models.py:
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
trusted = models.BooleanField(default=False)
address = models.CharField(max_length=100, default="")
COUNTRIES = (
('CZ', 'Czech Republic'),
('EN', 'England'),
)
country = models.CharField(max_length=2, choices=COUNTRIES, default="CZ")
score = models.BigIntegerField(default=0)
achievements = models.ManyToManyField(Achievement, blank=True)
USER_TYPES = (
('N', 'Normal'),
('C', 'Contributor'),
('A', 'Admin'),
)
user_type = models.CharField(max_length=1, choices=USER_TYPES, default='N')
@receiver(post_save, sender=settings.AUTH_USER_MODEL)
def create_auth_token(sender, instance=None, created=False, **kwargs):
if created:
Token.objects.create(user=instance)
@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created=False, **kwargs):
if created:
profile, created = Profile.objects.get_or_create(user=instance)
profile.save()
EDIT:
Ответы Мохаммеда Али решают это для GET, но я также хотел бы использовать методы POST, UPDATE и PATCH. Я обнаружил, что должен использовать параметр source
, но это относительно сериализатора. Я не знаю, как ссылаться на профиль без поля профиля.