Reputation: 453
Using DRF, I have a User model that includes an Address field, which is a TextField. When I view the UserList endpoint in the API Browser, Address looks like this:
"address": "<django.db.models.fields.TextField>",
From the documentation, I thought I needed this in my serializer:
address = serializers.CharField(
max_length=1000,
style={'base_template': 'textarea.html'},
)
...but that didn't fix the problem. The same thing is happening with PhoneNumberField type fields:
"phone_number": "<phonenumber_field.modelfields.PhoneNumberField>",
I redefined them in my serializer as CharField.
UPDATE:
My models and serializers are a bit more complex than usual because I'm splitting the Address, Country, and three phone fields out into separate classes so they can be included in several different models.
My User models:
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,
)
This is the model class for Address and Phone fields:
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
The User serializer:
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',
)
The Address and Phone fields serializer:
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
And, finally, the User views:
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
I'll include an example from the API Browser that includes all of the fields in question. Note that Country shows as expected.
"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>",
Upvotes: 1
Views: 1167
Reputation: 2830
Your abstract model mixin should be a models.Model
subclass:
class AddressPhoneModelMixin(models.Model):
...
You'll also need to put it to the left in the order of base classes for your user model as inheritance is processed from right to left:
class User(AddressPhoneModelMixin, AbstractUser):
...
NOTE: to specify serializer fields, you can use fields = '__all__'
instead of listing them individually. If there are just one or two missing, you can use exclude
instead.
Upvotes: 1