问题
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
回答1:
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
回答2:
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
回答3:
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...
回答4:
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...
来源:https://stackoverflow.com/questions/16606312/django-custom-user-model-and-usermanager