I want to know how do I create users in Django. I can use User.objects.create_user() but I can only store username, email, password, first name, last name. I see that django.contrib.auth.forms is depreciated so I cannot UserCreationForm.
What if I want to store more fields. Can anyone help me with it?
You should make a custom user model and manager.
Check this tutorial; it will explain all that you need.
Related
Actually, I'm working on a project where I need to save some details like name, username, password, age, gender etc of every user.
In that website, any user can login to their account, edit information.
So should I use the default users model or create a new model
I suggest you subclass AbstractUser. This option is suitable if you're fine with Django's User fields, but need extra fields. Django documentation also recommends to do this anyway.
If you’re starting a new project, it’s highly recommended to set up a
custom user model, even if the default User model is sufficient for
you. This model behaves identically to the default user model, but
you’ll be able to customize it in the future if the need arises:
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
pass or additional fields here ...
You also have to point to this model before creating or running any migration in the settings:
AUTH_USER_MODEL = 'yourapp.User'
Default user model in Django save some limited fields about one user. fields are
first_name, last_name, email, password, groups, user_permissions, is_staff, is_active, is_superuser, last_login, date_joined
If you want to save other information of user like birthday, expertise, gender you have to write userprofile model which must be linked one to one with user.
Example:
from django.contrib.auth.models import User
class UserProfile(models.Model):
user = models.OnetoOneField(User)
birthday = models.DateTimeField(default=datetime.datetime.now)
skills = models.CharField(max_length=128)
Actually, If you want to create a custom user model for user, It's mentioned in the Django's Official documentation. For achieving that you have to first inherit your custom user model with AbstractUser class and then pointing that custom user in your settings file by mentioning
AUTH_USER_MODEL = 'mycustom_user_app.MyCustomUser'.
Now django internally knows which model is the User model for the project, and you can access all model managers(e.g. create_user, etc. ) for your custom user. In that way you can use the current models fields and also can add more fields into it. That's the legit way to go with and to customize your User Model as mentioned in the documentation
Is there a simple way to force unique email address's during registration with website built with Django?
I've seen some "addons?" like HMAC, but it seems a bit too complicated for what I am trying to achieve.
Also, would it be possible to accept registration only from a list of domains? (such as only emails from "#google.com")
I had the same problem and solved it by extending the AbstractUser class to my own class MyUser and changing the defaults.
Then by making the this class MyUser as a default model class for all my users I could apply this property(unique E-Mail) to all my users on my web app.
Create an app myuser. There in models.py:
from django.contrib.auth.models import AbstractUser
#create your own user class.
class MyUser(AbstractUser):
def __init__(self, *args, **kwargs):
self._meta.get_field('email').blank = False
self._meta.get_field('email')._unique = True
super(MyUser, self).__init__(*args, **kwargs)
#Changed the defaults above.
#Give any additional field you want to associate your user with.
NOTE: AbstractUser already has all the basic fields you would want a User Model to have. For example: username, password, email etc. Check all of them here.
The last thing you would want to do is add the following in your setting.py
AUTH_USER_MODEL = 'myuser.MyUser'
This will make sure that the default user is associated with your web app is the extended(modified) MyUser class. This will provide you with all the basic functionalities that django provides for a User.
login
logout
in your views: you can get user instance in: request.user
etc.
I would like to suggest that you may need some additional code(in forms.py and views.py) to create a user through this type of class. I hope you will manage that. This should be enough to guide you in the right direction.
Maybe a library would have helped but since you needed an authentication for emails' domains as well, I think this should do the trick. In my humble opinion, you can't always depend on the 3rd party libraries for every other functionality.
Lastly, as you asked to authenticate a user coming only from a domain like #gmail.com or #outlook.com, a simple check in your django forms' clean method would do the trick. I hope you know how to handle django forms. If not, then you can learn about them in the official docs. They are an essential part of Django.
You can check the E-Mail with this logic:
email = self.cleaned_data['email']
email_source = email.split('#')[-1]
#email_source will now have values like: gmail.com, outlook.com etc
#you can now validate email_source now like:
permitted_sources = ['gmail.com' , 'outlook.com' , ]
if email_source in permitted_sources:
return cleaned_data
else:
raise forms.ValidationError('Error Message')
#Note: This logic should be kept in your clean method.
I hope this guides you. Thanks.
I need to add a BooleanField and a ManyToManyField to my users. I'm using django-social-auth. It seems I could use 'CustomUser'. I guess that's what it's for, but how do I take it into use?
I would need to know:
where to define these new fields
How to add them to the new user when the user is created (ie logs in)
How the query the fields afterwards (ie User.myBooleanField?)
Thanks!
Create a model called CustomUser or UserProfile, whatever you want, with these fields.
In settings.py add a setting AUTH_PROFILE_MODULE = "account.UserProfile", with what you named your model.
In the signals for social_auth, make sure the user has a profile, and if not create it for them when the user is created.
Now anywhere in the site you can call user.get_profile() and you'll have access to these fields.
Okay, this one is pretty obvious to everyone who use Django and frequently asked by newbies, but I'd like to make it clear and discuss if there are any other ways to do it. The most widespread and convenient approach now is to store email in username field as Django 1.2 allows "#", "_" and "-" characters, but this way has following issues:
The worst one: username field is restricted by max_length=30 property, which is ridiculously small for emails. Even if you override form validation, DB will have varchar(30) instead of EmailField's varchar(75) unless you alter your table manually.
You need to store your email data both in username and email field to make User.email_user() working. I think there are some other places when User.email is used.
Code readability fail. Sure, other djangonauts know about this pitfall, but treating field called 'username' (especially when there is still email field) as email obviously makes your code less understandable.
The other approach could be authentication using email field by passing it to your auth backend like so, but it still has problems:
authenticate(self, email=None, password=None)
User.email doesn't have unique=True property, which means that your DB won't have index, making your lookups by email slow like hell.
You have to deal with username field, which has unique=True, by completely removing it from your table or altering it to allow NULL and removing index.
Resuming, both ways are evil and require DB-specific code to be executed after syncdb, which is unacceptable if you need DB-independent application.
I've packaged up django-email-as-username which should pretty much do everything you need if you're looking to remove usernames, and only use emails.
The brief overview is:
Provides an email auth backend and helper functions for creating users.
Patches the Django admin to handle email based user authentication.
Overides the createsuperuser command to create users with email only.
Treats email authentication as case-insensitive.
Under the hood usernames are hashed versions of the emails, which ends up meaning we're not limited to the Django's username 30 char limit (Just the regular email 75 char limit.)
Edit: As of Django 1.5, you should look into using a custom User model instead of the 'django-email-as-username' package.
David Cramer came up with a solution to this problem that I love. I'm currently using it on a production site where the user has to be able to log in using their email OR their username. You can find it here:
Logging In With Email Addresses in Django
If the login name provided on the form is an email (contains the '#' symbol), it will attempt to authenticate with that, and will fall back on the username if it isn't an email. (Naturally, you just need to make sure your registration form captures an email for this work.)
Well, I haven't had to use emails as usernames in Django but I guess You could create a UserProfile model and aggregate fields to it, like another email field and make it unique. So you could do user.get_profile().email for your authentication.
I guess other way to go would be to inherit User and redefine the fields, but I think this still not recommended by Django developers.
Finally you could define your own custom User model and back on the django.contrib.auth.models.User for some logic.
Code to alter User table within Django:
from django.db import connection
cursor = connection.cursor()
cursor.execute("ALTER TABLE auth_user MODIFY COLUMN username varchar(75) NOT NULL")
I'm trying to learn Django and I would like feedback from anyone who has any MVC/MTV/PHP/Ruby framework experience. Does anyone find that the user model is too tightly coupled with auth?
Background: When you first implement authentication for Django, you include the module django.contrib.auth
This will bring in several models like User, Group, Message etc. Let's focus on the User model as this is the one of the most important tables in any website.
In short the User table has these fields
User
username max_length 30, unique, [letters, digits, underscores]
password max_length 75
email max_length 75
...and about 8 other useful fields like first_name, last_name, etc.
Goal:
I want to remove username and use email as the login for every user. It's a pretty simple request that many websites use these days.
I don't want to monkey patch the core code since this will make upgrading more difficult later on. This means modifying the User model is out of the question. I only want to do a few simple and basic things I expect a few frameworks to do so let me address how Django does it.
Adding new fields to the User model
Django docs says to use create another table and insert the fields there. You will have a one to one relationship between the User table and the Profile table.
eg.
If You want to add an image field to each user you add it to the profile table. A join query is made every single time. They've even specified a constant to tell the framework what table to use:
AUTH_PROFILE_MODULE = 'accounts.UserProfile'
I don't think it's the best practice to have to do a join query every time I want a field that should belong to the user table.
Another option is to use the function add_to_class.
The django community has stated it's not good to define new fields outside of the main class because other developers who add methods won't know all the data members.
Editing old fields
The auth module does a check against two fields username and the hashed password. Looking at the above table I would need to change the username model to accept these properties. Length of 75 with all the valid characters of the email. The django suggests I check against the email field.
Two problems arise if I use the email field to auth against:
I need to write a new class to be used in a constant AUTHENTICATION_BACKEND, so it checks against the email field and I have an unused field called username.
Adding new methods
In MVC/MTV a design principle is to use fat models skinny controllers. Since the model is declared in auth, I'm not sure how one is supposed to add methods that act on the user model's fields. Since django suggests using a Profile model, I suppose they will have to go there.
Extending the User class
A small annoyance would be that I can't use the name 'User' and instead must use 'Users' or 'Accounts'. A bigger one is I don't think the auth would recognize this new module. Meaning I would have to rewrite a bunch functionality that is is present. This one doesn't bother me as it's something I expect to do in other frameworks.
Any comments are appreciated. I wouldn't ask all these questions and look for solutions if I wasn't truly interested in using django.
I agree that django's incessant clinginess to the auth models is absurd. My job requires me to create ultra scalable and very high load sites which sometimes require user authentication and djano's auth model + permissions does not fit with that.
Fortunately, it's not difficult to replace.
First, create a custom User model.
class User(models.Model):
...fields...
#Define some interface methods to be compatible.
def get_and_delete_messages(self):
def is_active(self):
def is_anonymous(self):
def is_authenticated(self):
def is_staff(self):
def has_perm(self, perm_list):
Second, create your own authentication back-end.
class LocalAccount(object):
"""
This checks our local user DB for authentication
"""
def authenticate(self, username=None, password=None):
try:
user = User.objects.get(alias=username)
if user.check_password(password):
return user
except User.DoesNotExist:
return None
def get_user(self, user_id):
try:
return User.objects.select_related().get(pk=user_id)
except User.DoesNotExist:
return None
#settings.py
AUTHENTICATION_BACKENDS = (
'helpers.auth.LocalAccount',
)
That should solve most of your issues, I don't even think all of the methods you would find on django.contrib.auth.User are necessary, I recommend trying it out.
The one gotcha here is that the admin may start to bitch, fortunately that's really easy to patch using simple python inheritance as well. That's another question though :)
At the end of the day your project's auth backend needs some sort of store for auth credentials. That the default auth backend is tightly coupled to the User model is not strange in this respect. It's easy enough to substitute your own definition for the user model if you write your own auth backend, as I have in the past.
I created my Profile model and use AUTH_PROFILE_MODULE, so I have complete control over my model, I can modify fields, add methods, etc. Now I'm thinking about using cache and writing middleware that will get profile from cache if possible.
To login using email you could write very simple auth backend:
from django.contrib.auth.models import User
from django.contrib.auth.backends import ModelBackend
class EmailModelBackend(ModelBackend):
def authenticate(self, username=None, password=None):
try:
user = User.objects.get(email=username)
if user.check_password(password):
return user
except User.DoesNotExist:
return None