6

In order to create a new user model in Django 1.5.x, there are two approaches:

  1. Inherit AbstractUser class which is the default user model you get, this way you can extend it with any attributes you want. However, if you want to remove any field, it's technically possible but not recommended; even if it can be done, it is against OOP principles, I believe. So if you would like to alter the current user model, there is the second approach.
  2. Inherit AbstractBaseUser, which by looking at the code provides very basic functionality. You will miss all the goodness of permissions, profile retrieval and absolute url construction, unless you copy it from the default Django user model.

The above is my understanding of the situation. Correct me if I'm wrong, but doesn't this mean that if I want to simply remove the username field out of the model since I won't need it at all, I have to copy paste the model code provided in the framework and inherit from AbstractBaseUser and PermissionsMixin? For such a simple thing, this approach doesn't look very pretty to me, and it looks a bit odd since I'm quite certain the custom user model was introduced largely because of the popular use case of email field as the user identifier instead of username.

Your thoughts (and corrections) please.

Community
  • 1
  • 1
Aziz Alfoudari
  • 5,193
  • 7
  • 37
  • 53
  • This is not recommended in DJango. You should not remove a field from a parent Django model in an inheriting model.http://stackoverflow.com/questions/611691/django-model-inheritance-hiding-or-removing-fields – Srinivas Reddy Thatiparthy Sep 12 '13 at 16:44
  • 1
    @SrinivasReddyThatiparthy I have pointed this out already in the post. – Aziz Alfoudari Sep 12 '13 at 16:52
  • 1
    Why not just override the username class attribute in your subclass ?​ it could even return instance.email. – jpic Sep 17 '13 at 00:43

2 Answers2

5

If You look at the source code of the django.contrib.auth.models file then you will see that definition of the AbstractUser class is rather short and starts like this:

class AbstractUser(AbstractBaseUser, PermissionsMixin):
    ...

It inherits from the AbstractBaseUser and PermissionMixin. You could define your custom model and also inherit it from the mentioned classes to get permissions support. If you want all other model fields then yes, you will need to copy them, but it's also an opportunity to customize things to match your needs.

HankMoody
  • 3,077
  • 1
  • 17
  • 38
  • 5
    I'm looking at it from the reusability perspective, it's very common to use `email` as the primary user field an in order to do that you will need to do what you mentioned, which is somehow a long solution for a common problem. It's probably a better idea to generalize `AbstractUser` a bit further and allow its subclass to choose between `username` or `email` as the primary field. – Aziz Alfoudari Sep 12 '13 at 20:27
-13

Rather than using mixins and other applications which solve the problem, The best way to tackle the problem of not wanting a username is to replace the username with the email address entered by the user.

What u need to do is, go to the django source code which is usually situated in the python path. usually in the site-packeges of the python folder,

go to django folder, and into contrib folder, and into auth folder, open the models.py file which contains the definition of the User model.

On Virtualenv -> <virtualenv_name>/lib/python2.7/site-packages/django

In the models.py of auth app

Go to -> AbstractUser class replace the regex in "validators.RegexValidator" with this:

r"^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+$"

replace only the regex part inside the "validators.RegexValidator"

and in the same class, alter the username field's max_length to 254

I didnt have the reputation to post image of the code, if anybody wants a screenshot of how it looks after altering the code, ping me.

Thats it!

now go back to your app and then you can replace the username field with the email of any type in this world.

The final step : Go to your application where you are using the User model, meaning anywhere

python manage.py syncdb

python manage.py makemigrations

python manage.py migrate

if you don't see the auth model migrating then do,

python manage.py migrate auth

Now all you need to do is just replace the username with the email, during registration you can do somewhat like:

user = User.objects.create_user('email here', 'again email here', 'password here')

The best part about this is you dont have to change your authentication backend, as the email is itself the username and you can just label the username field as email.

nithin h r
  • 7
  • 1
  • 3
  • 3
    This is very bad solution in sooo many ways.. I know this post is quite old, but I'd want to warn others not to even try to do that. Editing Django source code or any other vendor library (that lives outside you own codebase, e.g. virtualenv) is never the right way to go. Just remember it, don't even try to argue. Just look at the above [linked article](https://code.djangoproject.com/wiki/ContribEmailAuth) to find better solution. – aherok Nov 11 '17 at 20:36
  • OOoooof Not even close to any of the suggested methodology., NEVER alter the Source code like this. – Ashutosh Kumar Jun 22 '20 at 16:57
  • +1 on other comments, do NOT customize Django source code, ever. Bad practice. Ideally remove this answer please – Farley Dec 06 '20 at 20:39