Используя DRF, у меня есть модель пользователя, которая включает поле адреса, которое является текстовым полем. Когда я просматриваю конечную точку UserList в браузере API, адрес выглядит так:
"address": "<django.db.models.fields.TextField>",
Из документации я подумал, что мне нужно это в моем сериализаторе:
address = serializers.CharField(
max_length=1000,
style = {'base_template': 'textarea.html'},
)
... но это не решило проблему. То же самое происходит и с полями типа PhoneNumberField:
"phone_number": "<phonenumber_field.modelfields.PhoneNumberField>",
Я переопределил их в своем сериализаторе как CharField.
ОБНОВИТЬ:
Мои модели и сериализаторы немного сложнее, чем обычно, потому что я разбиваю поля «Адрес», «Страна» и три поля телефона на отдельные классы, чтобы их можно было включить в несколько разных моделей.
Мои пользовательские модели:
class User(AbstractUser, AddressPhoneModelMixin):
objects = UserProfileManager()
USERNAME_FIELD = 'email'
type = models.CharField(
max_length=25,
)
title = models.CharField(
max_length=100,
blank=True,
null=True,
)
timezone = models.CharField(
max_length=50,
)
birthdate = models.DateTimeField(
blank=True,
null=True,
)
is_verified = models.BooleanField(
default=False,
)
email = models.EmailField(
unique=True,
db_index=True,
)
Это класс модели для полей Address и Phone:
class AddressPhoneModelMixin(object):
address = models.TextField(
blank=True,
null=True,
)
country = models.ForeignKey(
Country,
on_delete=models.SET_NULL,
blank=True,
null=True,
)
phone_number = PhoneNumberField(
blank=True,
null=True,
)
mobile_number = PhoneNumberField(
blank=True,
null=True,
)
fax_number = PhoneNumberField(
blank=True,
null=True,
)
class Meta:
abstract = True
Пользовательский сериализатор:
class UserSerializer(AddressPhoneSerializerMixin, serializers.ModelSerializer):
permission_classes = (permissions.IsAuthenticated,)
url = serializers.HyperlinkedIdentityField(view_name = "users:user-detail")
class Meta:
model = User
fields = (
'url',
'id',
'type',
'username',
'first_name',
'last_name',
'full_name',
'email',
'address',
'country',
'phone_number',
'mobile_number',
'fax_number',
'is_superuser',
'is_staff',
'is_active',
'is_verified',
'date_joined',
'last_login',
)
Сериализатор полей Address и Phone:
class AddressPhoneSerializerMixin(serializers.Serializer):
address = serializers.CharField(
max_length=1000,
style = {'base_template': 'textarea.html'},
)
country = serializers.HyperlinkedIdentityField(
view_name='countries:country-detail'
)
phone_number = serializers.CharField(
max_length=31,
)
mobile_number = serializers.CharField(
max_length=31,
)
fax_number = serializers.CharField(
max_length=31,
)
class Meta:
abstract = True
И, наконец, Пользователь просматривает:
class UserList(ListCreateAPIView):
permission_classes = (permissions.IsAuthenticated,)
queryset = User.objects.all()
serializer_class = UserSerializer
class UserDetail(RetrieveUpdateAPIView):
permission_classes = (permissions.IsAuthenticated,)
queryset = User.objects.all()
serializer_class = UserSerializer
Я включу пример из браузера API, который включает все рассматриваемые поля. Обратите внимание, что Country отображается так, как ожидалось.
"email": "[email protected]",
"address": "<django.db.models.fields.TextField>",
"country": "http://virticl.api/countries/1/",
"phone_number": "<phonenumber_field.modelfields.PhoneNumberField>",
"mobile_number": "<phonenumber_field.modelfields.PhoneNumberField>",
"fax_number": "<phonenumber_field.modelfields.PhoneNumberField>",
Ваш миксин абстрактной модели должен быть подклассом models.Model
:
class AddressPhoneModelMixin(models.Model):
...
Вам также нужно поместить его слева в порядке базовых классов для вашей пользовательской модели, поскольку наследование обрабатывается справа налево:
class User(AddressPhoneModelMixin, AbstractUser):
...
ПРИМЕЧАНИЕ: для указать поля сериализатора вы можете использовать fields = '__all__'
вместо того, чтобы перечислять их по отдельности. Если не хватает только одного или двух, вы можете вместо этого использовать exclude
.
Это помогло. Спасибо. Re: используя «все» для полей, это не вопрос необходимости исключения каких-либо полей, а скорее добавление одного. Если я укажу «все», как мне добавить поле с гиперссылкой «url», которое не является фактическим полем базы данных?
__all__
не относится к полям базы данных. Это относится к полям сериализатора. ModelSerializer
сопоставляет поля модели с полями сериализатора, но это просто означает, что ваши поля сериализатора — это все поля вашей модели плюс все, что вы явно определяете в сериализаторе.
В качестве примечания: я только что заметил, что вы определили permission_classes
в своем сериализаторе, но это атрибут представления. Я не думаю, что это имеет какой-либо эффект в сериализаторе (если вы не используете его где-то самостоятельно).
Вы можете добавить свои представления, а также сериализатор?]