Hi guys, I'm new here.
This is the Manager. This is mostly identical to what BaseUserManager does except for some quirks. I haven't included the generate_identifier method because it's not relevant:
And finally the auth backend, although this should only come into play when trying to log in, so it isn't involved in the problem (at least for now):
Please let me know if you need more info and thank you for reading this. I hope someone can walk me out of this conundrum... :P
-- I customised the User model of my project by inheriting from AbstractBaseUser, I've also made a custom Manager through BaseUserManager and added an auth backend to login through email instead of username.
The reason I did this is to let users register and login using their email but still have a username, that doesn't have to be unique (they're differentiated through a discriminator not unlike the one Discord uses, if you know it, like brzrkr#0001 and brzrkr#2342 may exist at the same time and both be known as brzrkr).
The problem is, when I create a user with `manage.py createsuperuser`, the database saves the email in the "username" field and the username in the "email" field, even though I set all overridden variables to the correct fields (see below for code).
NOTE: I have also posted a question about this on stackoverflow but it's been ignored for some days now, so I've looked for a place where people may be more familiar with Django in particular. Here is the link to it: https://stackoverflow.com/q/50104202/8599834
Now here's the code of the User model not including irrelevant methods:
class User(AbstractBaseUser, PermissionsMixin): """Override of the Django class to handle user authentication.""" # ==Identification== # To allow for multiple users with the same username, users are publicly identified with username#identifier. # Internally, only the couple username + identifier must be unique, but either can be duplicate on their own. username = models.CharField(max_length=150, db_column="user_username") # The identifier is stored as a string of digits including trailing zeroes. # It is assigned at creation and modification of a user's nick using the first value that doesn't conflict. identifier = models.CharField(max_length=settings.IDENTIFIER_DIGITS)
email = models.EmailField(unique=True, db_column="user_email")
objects = UserManagerOverride() # Override the default manager to customise user creation.
is_superuser = models.BooleanField(default=False) is_staff = models.BooleanField(default=False) is_active = models.BooleanField(default=True)
USERNAME_FIELD = "email" EMAIL_FIELD = "email" REQUIRED_FIELDS = ["username"]
class Meta: unique_together = ("username", "identifier")This is the Manager. This is mostly identical to what BaseUserManager does except for some quirks. I haven't included the generate_identifier method because it's not relevant:
class UserManagerOverride(BaseUserManager): """Override of the default Django user manager."""
def _create_user(self, email, username, password, **extra_fields): """Override the parent function to create a user and save it in the database.""" if not email: raise ValueError('An email is required.')
# Prepare the data to be stored into the database. email = self.normalize_email(email) username = self.model.normalize_username(username) identifier = self.generate_identifier(username)
# Make the user instance. user = self.model(username=username, email=email, identifier=identifier, **extra_fields)
# Add the password after encrypting. user.set_password(password)
try: # Save to database. user.save(using=self._db) except Exception: # If there was an error, scratch the user row to preserve integrity with User and UserData primary keys. user.delete() raise else: # Create a UserData record for this user. # Thanks to the try-else, we only do this if the code raised no exceptions. UserData.objects.create(user=user)
return user
def create_user(self, email, username, password=None, **extra_fields): """Override parent function to create a regular user account.""" extra_fields.setdefault('is_staff', False) extra_fields.setdefault('is_superuser', False) return self._create_user(email, username, password, **extra_fields)
def create_superuser(self, email, username, password, **extra_fields): """Override parent function to create a superuser account.""" extra_fields.setdefault('is_staff', True) extra_fields.setdefault('is_superuser', True)
if extra_fields.get('is_staff') is not True: raise ValueError('Superuser must have is_staff=True.') if extra_fields.get('is_superuser') is not True: raise ValueError('Superuser must have is_superuser=True.')
return self._create_user(username, email, password, **extra_fields)And finally the auth backend, although this should only come into play when trying to log in, so it isn't involved in the problem (at least for now):
class EmailBackend(ModelBackend): """Allow authentication using email instead of username.""" def authenticate(self, username=None, password=None, **kwargs): user_model = get_user_model() try: user = user_model.objects.get(email=username) except user_model.DoesNotExist: return None else: if user.check_password(password): return user return NonePlease let me know if you need more info and thank you for reading this. I hope someone can walk me out of this conundrum... :P
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscribe@googlegroups.com.
To post to this group, send email to django-users@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/ef29e0ef-9d60-49d3-8a65-5e80aee7691d%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
No comments:
Post a Comment