2

I've read tons of stack overflow posts about how to register a user with email instead of username but none of them seem to work, so I'm resetting to my defaults. I tried this and this but I still get 'username is required' back from the API when I try to register user.

I think the problem might be that I couldn't find a post that's explicit to Django 3 and uses Django Rest Framework.

Below are my models, serializers and views.

# models
class User(AbstractUser): 
    ROLES = (
        ('d', 'Doctor'),
        ('s', 'Secretary'),
        ('p', 'Patient'),
    )
    role = models.CharField(
        max_length=1, choices=ROLES, blank=True, default='p', help_text='Role')

class Doctor(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    clinic = models.ManyToManyField(
        Clinic, related_name="doctors", blank=True)
    appointment_duration = models.IntegerField(default=20, blank=True)

# serializer
User = get_user_model()
class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ('id', 'username', 'password', 'role', 'first_name', 'last_name', 'email', 'phone')
        extra_kwargs = {'password': {'write_only': True, 'required': True}

# viewset
class UserViewSet(viewsets.ModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    permission_classes = (AllowAny,)

So, how could I register with email instead of username?

  • Set the `username` to the `email` and keep them in sync. In model `User` `def save(self, *args, **kwargs): self.username = self.email; return super().save(*args, **kwargs)` – Ross Rogers Oct 01 '20 at 15:29
  • Must though tutorial on this : https://simpleisbetterthancomplex.com/tutorial/2016/07/22/how-to-extend-django-user-model.html – michjnich Oct 01 '20 at 15:34
  • @RossRogers this error shows: ```line 23, in save self.username = self.email "AttributeError: 'UserSerializer' object has no attribute 'email'"``` –  Oct 01 '20 at 16:05
  • 1
    Not in the `UserSerializer`. In the `User` model itself. – Ross Rogers Oct 01 '20 at 16:09
  • It worked! Are you aware of any limitations/problems I might encounter down the line because of doing it this way? –  Oct 01 '20 at 16:17
  • That's what I've done for years and haven't hit limitations. – Ross Rogers Oct 01 '20 at 16:33
  • would you like to add it as the answer? –  Oct 01 '20 at 17:04

2 Answers2

0

The username field in the Django can be used to store any string with such restrictions:

150 characters or fewer. Letters, digits and @/./+/-/_ only.

So it is possible to use username as an email too without any restrictions. You can override the Auth mechanism of the DRF to validate email in the provided username and validate the password. Check this link for details.

Also, you can find several approaches to extend the Django User model. Details are in this discussion.

fanni
  • 1,149
  • 8
  • 11
0

Set the username to the email every time you save to keep them in sync. In model User:

class User(AbstractUser): 
    def save(self, *args, **kwargs): 
        self.username = self.email
        return super().save(*args, **kwargs)
    [...]
Ross Rogers
  • 23,523
  • 27
  • 108
  • 164