I have been learning Django for a week, In order to implement authentication system, I have created models.py file as tutorials.
from django.db import models
from django.contrib.auth.models import AbstractBaseUser
class User(AbstractBaseUser):
username = models.CharField('username', max_length = 10, unique = True, db_index = True)
email = models.EmailField('email address', unique = True)
joined = models.DateTimeField(auto_now_add = True)
is_active = models.BoolenField(default = True)
is_admin = models.BoolenField(default = False)
USERNAME_FIELD = 'username'
def __unicode__(self):
return self.username
I understand what username, email, joined, is_active, is_admin means, but I can't understand why I use USERNAME_FIELD.
Is username created by models.CharField equal to the 'username' in USERNAME_FIELD?
Why do I have to create USERNAME_FIELD?
What does def __unicode__(self): function mean?
According to the docs, USERNAME_FIELD is:
A string describing the name of the field on the user model that is used as the unique identifier. This will usually be a username of some kind, but it can also be an email address, or any other unique identifier. The field must be unique (i.e., have unique=True set in its definition), unless you use a custom authentication backend that can support non-unique usernames.
So, USERNAME_FIELD specifies which model field is going to be used as the username. If your application uses an email address instead of a username, you would configure that using USERNAME_FIELD.
The __unicode__(self) method returns a string representation of the object. Without it, any time you try to display an object it will look like: <User: User object>. As you have it now, displaying a User object will instead show the User's username. In the Django tutorial part 2 they use the __str__ method in conjunction with the #python_2_unicode_compatible decorator to make it work with Python 2. In Python 3 __str__ is the equivalent of __unicode__ in Python 2.
Check the documentation for your version of Django:
USERNAME_FIELD
A string describing the name of the field on the User model that is used as the unique identifier. This will usually be a username of
some kind, but it can also be an email address, or any other unique
identifier. The field must be unique (i.e., have unique=True set in
its definition).
USERNAME_FIELD defaults to "username" so you can skip setting it in your custom user model if the default works for you.
You can read about __str__() and __unicode__() methods here.
Related
My requirement is to create AUTH system which uses email as AUTH token and some extra fields like name, phone etc and get rid of username field:
I can achieve this using both the abstract classes ! But confused on which to use
I can just use AbstractUser and make "username=None" and then add usernanager !
Or should i use AbstractBaseUser and redo everything ?
This answer exaplains it better which one to use. However it depends on a lot of things. In short :
Django uses authentication using username field by default. If you
want to use an email address as your authentication instead of a
username, then it is better to extend AbstractBaseUser. But, if you
are happy with how django handle authentication but need some extra
information on User model, then you can extend AbstractUser.
You also can check the documentation Using a custom user model when starting a project .
according to [Django Docs]:
If you’re entirely happy with Django’s User model, but you want to add some additional profile information, you could subclass django.contrib.auth.models.AbstractUser and add your custom profile fields, although we’d recommend a separate model as described in the “Model design considerations” note of Specifying a custom user model. AbstractUser provides the full implementation of the default User as an abstract model.
So i think you are not happy with AbstractUser and you want something different. so just use AbstractBaseUser and extend it as you wish.
Basically, you better use "AbstractUser" class instead of "AbstractBaseUser" class. Actually, using "AbstractUser" class or "AbstractBaseUser" class, you can do the same things such as adding and removing fields and so on. And actually, "AbstractUser" class is the subclass of "AbstractBaseUser" class and "AbstractUser" class has 11 fields which you will basically use as shown below:
id
password
last_login
is_superuser
username
first_name
last_name
email
is_staff
is_active
date_joined
But "AbstractBaseUser" class which is the superclass of "AbstractUser" class only has 3 fields which you will basically use as shown below:
id
password
last_login
So, when you create "CustomUser" class with "AbstractUser" class, you can write much less code defining less fields because "AbstractUser" class already has 8 more fields which you will basically use than "AbstractBaseUser" class.
For example, you want to log in with "email" and "password" instead of "username" and "password" so you create 2 "CustomUser" classes with "AbstractUser" class and "AbstractBaseUser" class as shown below:
<"AbstractUser" class>
# "models.py"
from django.db import models
from django.contrib.auth.models import AbstractUser
from .managers import CustomUserManager
class CustomUser(AbstractUser):
username = None # Remove "username"
email = models.EmailField('email address', unique=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
objects = CustomUserManager()
class Meta:
verbose_name = "custom user"
verbose_name_plural = "custom users"
<"AbstractBaseUser" class>
# "models.py"
from django.db import models
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin
from django.utils import timezone
from .managers import CustomUserManager
class CustomUser(AbstractBaseUser, PermissionsMixin):
first_name = models.CharField("first name", max_length=150, blank=True)
last_name = models.CharField("last name", max_length=150, blank=True)
email = models.EmailField('email address', unique=True)
is_staff = models.BooleanField(
"staff status",
default=False,
help_text="Designates whether the user can log into this admin site.",
)
is_active = models.BooleanField(
"active",
default=True,
help_text=
"Designates whether this user should be treated as active. "
"Unselect this instead of deleting accounts."
,
)
date_joined = models.DateTimeField("date joined", default=timezone.now)
USERNAME_FIELD = 'email'
objects = CustomUserManager() # Here
As you can see above, "CustomUser" class with "AbstractUser" class has much less code than the one with "AbstractBaseUser" class. That's why basically, you better use "AbstractUser" class instead of "AbstractBaseUser" class.
#models.py
class Mymodel(models.Model):
name = models.CharField(max_length=100,null=False,blank=False)
email = models.EmailField(max_length=100,null=False,blank=False)
password = models.CharField(max_length=120,null=False,blank=False)
email_notification = models.BooleanField()
#views.py
obj=MyModel.objects.create(name="ok",password="dsfdsfdsfdsfsfds",email_notification=1)
even if email was required field,then also object was created when I see in the admin panel.What can be the issue,Why object got created,even if email field was mandatory?
Also if I go in admin panel and open that object and click save then it raises that email is required
Note: You don't to have provide null=False,blank=False in your fields because those are the values used by default.(See the Django Field __int__ signature.).
def __init__(self, verbose_name=None, name=None, primary_key=False,
max_length=None, unique=False, blank=False, null=False,
db_index=False, rel=None, default=NOT_PROVIDED, editable=True,
serialize=True, unique_for_date=None, unique_for_month=None,
unique_for_year=None, choices=None, help_text='', db_column=None,
db_tablespace=None, auto_created=False, validators=(),
error_messages=None):
By default all the fields in database are created with NOT NULL constraint. If you set null=True for a particular field, then django sets NULL on the column in your DB. It’s the database equivalent of Python’s None keyword.
Example with null argument
Assume that I have the following Mymodel in my my_app and I set email field to null=True.
class MyModel(models.Model):
name = models.CharField(max_length=100)
email = models.EmailField(max_length=100, null=True)
password = models.CharField(max_length=120)
email_notification = models.BooleanField()
In Shell,
>> from my_app.models import MyModel
>> new = MyModel.objects.create(name="ok",
password="dsfdsfdsfdsfsfds",
email_notification=1)
>> new.email == None
>> True # As you can see Django sets db value
# as NULL and when we query the data it converts back to Python `None` object.
Example without null argument
Assume that I have the following Mymodel in my my_app.(remember null will be False by default)
class MyModel(models.Model):
name = models.CharField(max_length=100)
email = models.EmailField(max_length=100)
password = models.CharField(max_length=120)
email_notification = models.BooleanField()
In Shell,
>> from my_app.models import MyModel
>> new_obj = MyModel.objects.create(name="test",
password="test",
email_notification=1)
>> new_obj.email == ''
>> True
Ie,Django CharField and TextField the default values are stored in the DB as an empty string (''). In other words, if you create an object without providing values for a CharField(or a TextField) under the hood Django invokes the get_default method and returns '' (only in this case). This value will be stored in the database.
The following is the source code of get_default method.
def get_default(self):
"""Return the default value for this field."""
return self._get_default()
#cached_property
def _get_default(self):
if self.has_default():
if callable(self.default):
return self.default
return lambda: self.default
if not self.empty_strings_allowed or self.null and not connection.features.interprets_empty_strings_as_nulls:
return return_None
return str # return empty string
Let's answer your question:
Why object got created,even if email field was mandatory?
The answer is EmailField is an instance of CharField Hence default value '' will be used while creating an object in database. That is why you are not getting django.db.utils.IntegrityError.
>> new_obj = Mymodel.objects.create(name='tes1t', password='test1', email_notification=1)
>>> new_obj.email
''
Also if I go to the admin panel and open that object and click save then
it raises an error indicating that email is required
Remember blank is different from null. null is purely database-related, whereas blank is validation-related. So when you create an object directly in Python code, or execute raw SQL yourself, you are actually bypassing all of Django’s input validation. But in admin, Django is validating the input through the model form. Since in your case blank is set to False(blank not allowed), model form will raise Email is required Error.
Here is the relevant Django documentation for blank argument.
Field.blank
If True, the field is allowed to be blank. Default is False. Note
that this is different than null. null is purely database-related,
whereas blank is validation-related. If a field has blank=True, form
validation will allow entry of an empty value. If a field has
blank=False, the field will be required.
Additional resources
Django tips: the difference between ‘blank’ and ‘null’
differentiate null=True, blank=True in django
There is no issue with django you will have to create proper Django Model Form validation so that the empty string isn't ignored and it will raise an error for the blank field.
I got suddenly an integrity error: "Duplicate entry 'qw' for key 'username'
from this model. 1062,
from django.template.defaultfilters import slugify
from django.contrib.auth.models import User
class Customer(User):
slug=models.SlugField(unique=True)
description=models.TextField(null=True)
phone=models.IntegerField(null=True)
id_verified=models.NullBooleanField()
picture=models.ImageField(upload_to='media/customer', null=True)
isWorker=models.BooleanField()
def save(self,*args,**kwargs):
self.slug=slugify(self.username)
super(Customer,self).save(*args, **kwargs)
def __unicode__(self):
return self.username
What's wrong here?
From the docs, about specifying a custom user model:
You must then provide some key implementation details:
USERNAME_FIELD
A string describing the name of the field on the User
model that is used as the unique identifier. This will usually be a
username of some kind, but it can also be an email address, or any
other unique identifier. The field must be unique (i.e., have
unique=True set in its definition).
So username seems to be unique, at least until you set a custom username field.
Read the docs
https://docs.djangoproject.com/en/dev/topics/auth/customizing/#specifying-a-custom-user-model
i'm building a web application with Django 1.5. I'm using a custom User model with a custom UserManager.
I followed the instructions and examples of the official Django documentation.
Now, when i'm trying to create a new user via UserManager.create_user(...) i'm getting a NoneType error: It seems the UserManager's attribute models is of type None.
I think i'm setting up the UserManager correctly in the User model ( objects = UserManager() )
I really don't know where i'm making a mistake. Booth my coding partners and i are new to Django. Maybe you can help us out.
Here is the code:
class UserManager(BaseUserManager):
"""
create a new user
#param username: the name for the new user
#param password: the password for the new user. if none is provided a random password is generated
#param person: the corresponding person object for this user
"""
def create_user(self, username, person, password=None):
if not username:
raise ValueError('User must have a valid username')
user = self.model(username=username, created=datetime.now(), must_change_password=True, deleted=False, person=person)
user.set_password(password)
user.save(using=self._db)
return user
class User(AbstractBaseUser):
## the id of the user. unique through the application
user_id = models.AutoField(primary_key=True)
## the name of the user. unique through the application
username = models.CharField(max_length=32, unique=True)
## the date when the user was created
created = models.DateTimeField()
## iff this is true the user must set a new password at next login
must_change_password = models.BooleanField(default=True)
## iff true the user is marked as deleted and can not login
deleted = models.BooleanField(default=False)
## iff true the user is admin and has all permissions. use with care!
is_admin = models.BooleanField(default=False)
## reference to the person entity that is linked to this specific user
person = models.ForeignKey(Person)
## indicates if the user is active or not
active = models.BooleanField(default=True)
## define the user manager class for User
objects = UserManager()
# necessary to use the django authentication framework: this field is used as username
USERNAME_FIELD = 'username'
I'm getting the NoneType Error at line user = self.model(..) in the create_user() method in the UserManager
To create new user you shouldn't call UserManager.create_user(...). Instead you should use :
from django.contrib.auth import get_user_model
get_user_model().objects.create_user(...)
This is how django managers work. You can read docs here
I also had problems saving the custom user model and it took me while to figure it our
I think the important line in your code is:
objects = UserManager()
within the User class, so in order to save the new user you need to call
new_user=User.objects.create_user(args, args, args, etc)
the "objects" is the item that calls the UserManager class and is called a manager in django
Important caveat to update the solutions...
If you're facing this kind of problem, you've probably tried various solutions around the web telling you to add AUTH_USER_MODEL = users.CustomUser to settings.py and then to add the following code to views.py forms.py and any other file that calls User:
from django.contrib.auth import get_user_model
User = get_user_model()
And then you scratch your head when you get the error:
Manager isn't available; 'auth.User' has been swapped for 'users.User'
Anytime your code references User such as:
User.objects.get()
Cause you know you already put objects = UserManager() in your custom user class (UserManager being the name of your custom manager that extends BaseUserManager).
Well as it turns out (thank you to #Aldarund) doing:
User = get_user_model() # somewhere at the top of your .py file
# followed by
User.objects.get() # in a function/method of that same file
Is NOT equivalent to:
get_user_model().objects.get() # without the need for User = get_user_model() anywhere
Perhaps not intuitive, but it turns out that that in python, executing User = get_user_model() once at the time of import does not then result in User being defined across subsequent calls (i.e. it does not turn User into a "constant" of sorts which you might expect if you're coming from a C/C++ background; meaning that the execution of User = get_user_model() occurs at the time of imports, but is then de-referenced before subsequent called to class or function/method in that file).
So to sum up, in all files that reference the User class (e.g. calling functions or variables such as User.objects.get() User.objects.all() User.DoesNotExist etc...):
# Add the following import line
from django.contrib.auth import get_user_model
# Replace all references to User with get_user_model() such as...
user = get_user_model().objects.get(pk=uid)
# instead of user = User.objects.get(pk=uid)
# or
queryset = get_user_model().objects.all()
# instead of queryset = User.objects.all()
# etc...
Hope this helps save others some time...
I had to add an answer as I don't have enough rep to comment. But the link in #Aldarund's answer does not describe the use of get_user_model() at all. However, this link should help...
In my case if you got "manager_method" missing 1 required positional argument: 'self' django err you should notice that
unlike model.Manager the UserManager need to set as blow
from django.contrib.auth.models import AbstractUser, UserManager
from django.db.models import Q
class CostumUserManager(UserManager ):
def authors(self):
return self.filter(Q(is_author=True) | Q(is_superuser=True))
class User(AbstractUser):
is_author = models.BooleanField(default=False, )
objects = CostumUserManager() # Use () in end of it
I'm working on a project in django which calls for having separate groups of users in their own username namespace.
So for example, I might have multiple "organizations", and username should only have to be unique within that organization.
I know I can do this by using another model that contains a username/organization id, but that still leaves this useless (and required) field on the defualt django auth User that I would have to populate with something.
I've already written by own auth backend that authenticates a user against LDAP. However, as I mentioned before, I am still stuck with the problem of how to populate / ignore the username field on the default django user.
Is there a way to drop the uniqueness constraint for the username for Django auth users?
I'm not sure if this is exactly what you're looking for, but I think you could use a hack similar to what is in this answer.
The following code works, as long as it is in a place that gets executed when Django loads your models.
from django.contrib.auth.models import User
User._meta.get_field('username')._unique = False
Note that this won't change the database unique constraint on the auth_user table if it has been already been created. Therefore you need to make this change before you run syncdb. Alternatively, if you don't want to recreate your auth_user table, you could make this change and then manually alter the database table to remove the constraint.
What you can do is extend the User model. For the User table, generate a username (e.g. A_123, A_345) that will not be displayed at all in the site.
Then create a new model that extends User.
class AppUser(User):
username = models.CharField...
organization = models.CharField...
You then create a custom authentication backend that use AppUser instead of the User object.
I have not personally been required to find a solution to this, but one way to tackle this (from an SAAS perspective) would be to prefix the username with an organizational identifier (presuming unique organizations). For example: subdomain.yoursite.com would equate to a user with the username: subdomain_username. You would just have to code some business logic on login to a subdomain to tack that onto the username.
I also suffered with this problem. I was doing a project where I had to use email and mobile no. as login fields but none of them should be unique because their were different types of users and a user can have more than one user entity and also the project required only one auth user table (Hectic right!).
So I extended AbstractBaseUser class where I could change the USERNAME_FIELD attribute. Here's how :-
from django.contrib.auth.models import AbstractUser
from django.contrib.auth.models import PermissionsMixin
# Custom model for User
class User(AbstractBaseUser, PermissionsMixin):
first_name = models.CharField(max_length=100, blank=False)
last_name = models.CharField(max_length=100, blank=True)
password = models.CharField(max_length=255, blank=False)
email = models.EmailField(max_length=255, blank=False)
mobile = models.CharField(max_length=12)
user_type = models.ForeignKey(UserTypes, on_delete=models.DO_NOTHING)
is_approved = models.BooleanField(default=False)
objects = UserManager()
# Here's the Catch
USERNAME_FIELD = 'id'
def get_full_name(self):
'''
Returns the first_name plus the last_name, with a space in between.
'''
full_name = '%s %s' % (self.first_name, self.last_name)
return full_name.strip()
def get_short_name(self):
'''
Returns the short name for the user.
'''
return self.first_name
def email_user(self, subject, message, from_email=None, **kwargs):
'''
Sends an email to this User.
'''
send_mail(subject, message, from_email, [self.email], **kwargs)
class Meta:
db_table = 'user'
Yes exactly, surprised? USERNAME_FIELD should be a unique field that's the constraint of this attribute. I couldn't use email or mobile no. as unique field.
Then I created a custom manager to remove the username field (reference = https://simpleisbetterthancomplex.com/tutorial/2016/07/22/how-to-extend-django-user-model.html#abstractbaseuser)
from django.contrib.auth.base_user import BaseUserManager
class UserManager(BaseUserManager):
use_in_migrations = True
def _create_user(self, email, password, **extra_fields):
"""
Creates and saves a User with the given email and password.
"""
if not email:
raise ValueError('The given email must be set')
email = self.normalize_email(email)
user = self.model(email=email, **extra_fields)
user.set_password(password)
user.save(using=self._db)
return user
def create_user(self, email, password=None, **extra_fields):
extra_fields.setdefault('is_superuser', False)
return self._create_user(email, password, **extra_fields)
def create_superuser(self, email, password, **extra_fields):
extra_fields.setdefault('is_superuser', True)
if extra_fields.get('is_superuser') is not True:
raise ValueError('Superuser must have is_superuser=True.')
return self._create_user(email, password, **extra_fields)
This will do the trick.
I'm facing the exact same problem and I've been reading a lot (about how to solve that problem in 1.5) and I just thought of a much simpler solution. What if you just add a fixed-length prefix with the organization id to store the username?
I.e. Organization id = 115, chosen username = "john" and a fixed length of 6. So in the data base you store as username "000115_john".
When you do the login you just join the two parameters and try to authenticate with what Django provides. I'm not sure if the fixed length is strictly necessary but could avoid undesirable results if a user chooses a username with only numbers.