I'm new in Django realm but see there is a lot of "magic" there. I'm using Django REST Framework and creating app that will allow free user registration. My user needs some additional fields that are not available in Django user. So I googled for extending User. There is an idea that this should be done by creating something like this
class MyUser(models.Model): user = models.ForeignKey(User, unique=True) city = models.CharField(max_length=50, blank=True, default='')
This is fine but I have this serializer
class UserSerializer(serializers.ModelSerializer): class Meta: model = MyUser fields = ('id', 'username', 'password', 'first_name', 'last_name', 'email', 'city')
So, the problem is that this serializer does some "magic" here. It tries to figure out what field should model have ... I want to have user with fields listed here, and these are fields are in User and 'city' is new custom field. Serializer doesn't get that it should look inside User model.
What am I missing here? How to tell this serializer that I want some fields inside User? I need to be able to crete user too.
It's highly recommended to set up a custom User model when starting a new Django project. Without it, you will need to create another model (like UserProfile ) and link it to the Django User model with a OneToOneField if you want to add new fields to the User model.
So apparently I don't have enough reputation to post a comment under an answer. But to elaborate on what Kevin Stone described, if you model is something like the following:
class AppUser(models.Model): user = models.OneToOneField(User) ban_status = models.BooleanField(default=False)
You can do something like this to create both the custom user and django user:
class AppUserSerializer(serializers.ModelSerializer): username = serializers.CharField(source='user.username') email = serializers.CharField(source='user.email') password = serializers.CharField(source='user.password') ban_status = serializers.Field(source='ban_status') class Meta: model = AppUser fields = ('id', 'username', 'email', 'password', 'ban_status') def restore_object(self, attrs, instance=None): """ Given a dictionary of deserialized field values, either update an existing model instance, or create a new model instance. """ if instance is not None: instance.user.email = attrs.get('user.email', instance.user.email) instance.ban_status = attrs.get('ban_status', instance.ban_status) instance.user.password = attrs.get('user.password', instance.user.password) return instance user = User.objects.create_user(username=attrs.get('user.username'), email= attrs.get('user.email'), password=attrs.get('user.password')) return AppUser(user=user)
Okay, a couple of things. You want to create a OneToOneField
for your user model extension.
class MyUser(models.Model): user = models.OneToOneField(User) city = models.CharField(max_length=50, blank=True, default='')
Now, the power of Django Rest Framework, is you can build your serializer, to take data from both of these models when serializing.
class UserSerializer(serializers.ModelSerializer): city = serializers.CharField(source='myuser.city') class Meta: model = User fields = ('id', 'username', 'password', 'first_name', 'last_name', 'email', 'city')
Finally, where you're creating the user, since you're using custom fields, you need to implement your own restore_object()
that builds both models from the input data.
Also, creating Users in Django is a bit different, you need to call create_user()
and supply a password that is hashed, so its not as simple as storing fields from a serializer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With