I. Introduction
Designing a good user system is often not that easy. Django provides a user system that allows for quick implementation of basic functionality and can continue to expand upon it to meet our needs.
Let's first look at what Django's user system offers:
- Provision of User Model
- Privilege validation (add delete modify privileges of existing modules by default)
- User Groups and Group Permissions Functions
- User authentication and login functions
- Some functions and decoration methods related to user login authentication
If you configure Django's user system, you only need to call a few functions provided by Django to realize user login, logout, permission verification and other functions. For example, the following scenario
1.Login
# some_view.py from import authenticate, login def login(request): username = ['username'] password = ['password'] # Django provides the authenticate function to verify that the username and password match in the database user = authenticate(username=username, password=password) if user is not None: # Django provides a login function that saves the currently logged in user information to the session key login(request, user) # Perform a successful login, redirect somewhere, etc. ... else: # Return username and password error messages ...
2. Write-offs
# some_view.py from import logout def logout(request): The # logout function clears the information saved in the session by the current user logout(request)
3. Verify that you are logged in
# some_view.py def some_fuction(request): user = if user.is_authenticated: # Logged in users, you can proceed to the next step else: # Return request for login information
4. Verify that you have permission
# some_view.py def some_fuction(request): user = if user.has_perm('myapp.change_bar'): # With permission to proceed down the line else: # Returns information on denial of access, etc.
II. User modules
Django's user module class is defined in the auth application. To use Django's user class directly, add a line to INSTALLAPP in the setting configuration file.
This allows you to create a user directly in the code with the User class:.
from import User user = .create_user('john', 'lennon@', 'johnpassword') user.last_name = 'Lennon' ()
Take a look at Django's source code for the User class to see what properties are defined:
class User(AbstractUser): """ Users within the Django authentication system are represented by this model. Username, password and email are required. Other fields are optional. """ class Meta(): swappable = 'AUTH_USER_MODEL'
...and nothing?
Notice that the User class inherits from the AbstractUser class, and the username and password information are defined in the parent class. So let's look at the definition of the AbstractUser class again, and for the sake of space, we'll only list part of it./django/django/blob/master/django/contrib/auth/
class AbstractUser(AbstractBaseUser, PermissionsMixin): username = ( _('username'), max_length=150, unique=True, help_text=_('Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.'), validators=[username_validator], error_messages={ 'unique': _("A user with that username already exists."), }, ) first_name = (_('first name'), max_length=30, blank=True) last_name = (_('last name'), max_length=30, blank=True) email = (_('email address'), blank=True) date_joined = (_('date joined'), default=) ....
You can see that the AbstractUser class defines the username field, in addition to email, first_name, last_name, etc. AbstractUser class also inherits AbstractBaseUser and PermissionsMixin class, AbstractBaseUser class provides the password field and will encrypt the password to save the relevant methods. AbstractBaseUser class provides a password field and will encrypt the password to save the relevant methods , PermissionsMixin class to provide the User class permissions authentication function .
In a nutshell, a User class, defines the following fields:
- username: username
- password: password
- first_name: Name
- last_name: Name
- email: email
- groups: Group class many-to-many relational object manager
- user_permissions: Permission class many-to-many relationship object manager
- is_staff: whether staff
- is_active: whether active
- is_superuser: whether administrator
- last_login: Last login time
- date_joined: Registration time
Alternatively, to generate a User instance, the following properties can be used:
- is_authenticated: read-only, used to determine if the user exists. Only the AnonymousUser class has this attribute as False.
- is_anonymous: is used to distinguish between User and AnonymousUser objects.
The User class provides a number of methods to perform various operations:
- set_password(raw_password): you can convert password to hash value, remember to call() again to save it.
- check_password(raw_password): Instead, compare the raw password with the password of the hash value stored in the database (direct comparison is definitely not the same).
- has_perm(perm, obj=None), has_perms(perm_list, obj=None): verify that the user has a certain permission or list of permissions
- get_all_permissions(obj=None): Returns all the permissions this user has
III Authenticating and logging in users
Validating the username and password seems simple enough, just compare the submitted username and password to the ones saved in the database.
As:
# some_view.py def some_fuction(request): username = ['username'] password = ['password'] try: user = (username=username, password=password) except ObjectNotExists: # Username and password do not match a user ...
Because the password has been saved after the hash, the above code must first submit the password value first hash and then go to the database to search, always have to write some more code. Django has taken this into account, providing an authenticate function to verify the existence of the user, as in the introductory example code:
# some_view.py from import authenticate, login def login(request): username = ['username'] password = ['password'] user = authenticate(username=username, password=password) if user is not None: login(request, user) ... else: ...
The authenticate and login functions are highlighted here.
(**credentials)
Pass in the parameters to be authenticated, the default is username and password, it will call the system configuration of each authentication backend for authentication, authentication through the return of a User instance, otherwise return None.
Each authentication backend refers to an authentication backend, and the AUTHENTICATION_BACKENDS variable configured in the default is [''], which can be added as a customized authentication backend or provided by a third party.The authenticate function calls each of them sequentially for authentication, and if the first one fails, it will use the second one for authentication until all authentication backends have failed before returning None.
Take a look at how this ModelBackend class returns authenticated users (again, the source code is reduced):
class ModelBackend(object): def authenticate(self, request, username=None, password=None, **kwargs): if username is None: username = (UserModel.USERNAME_FIELD) try: user = UserModel._default_manager.get_by_natural_key(username) except : UserModel().set_password(password) else: if user.check_password(password) and self.user_can_authenticate(user): return user # ...
The authenticate function actually calls the authenticate method of each authentication backend class. The ModelBackend class is slightly different from our previous authentication method in that it first takes a User instance corresponding to username from the database user table, then verifies that the password is correct through the User's check_password method to verify that the password is correct and return the User instance.
(request, user, backend=None)
Receive an HttpRequest object and a User object. The login function will save the current user information into the session cookie, so to use all the features of the Django user system, you also have to install the Django default session APP.
Look at what the login function does:
def login(request, user, backend=None): # (clear current session information) # ... [SESSION_KEY] = user._meta.pk.value_to_string(user) [BACKEND_SESSION_KEY] = backend [HASH_SESSION_KEY] = session_auth_hash if hasattr(request, 'user'): = user rotate_token(request) user_logged_in.send(sender=user.__class__, request=request, user=user)
The login function stores a unique identifier for the current user in the SESSION_KEY, and the next time you request it, you can get the currently logged-in user object from the session cookie.
If you require a logged in user to access the corresponding View, you can write it like this:
from import settings from import redirect def my_view(request): if not .is_authenticated: return redirect('%s?next=%s' % (settings.LOGIN_URL, ))
The login function allows you to save the user's information in the session, and before the next request reaches the view, Django's session middleware takes the user object from the session cookie and assigns it. In this way, logged-in users.is_authenticated value is True and can be manipulated accordingly. Unlogged-in users return an AnonymousUser object, whose is_authenticated property value is always False, then to redirect this request to the login page.
These two lines of code can be realized by adding a decorator to the view function, as in
@login_required def my_view(request): ...
Decorator login_required(redirect_field_name='next', login_url=None), can be passed the login_url parameter to set the address to which requests from non-logged-in users will be redirected, otherwise it redirects to settings.LOGIN_URL.
IV. Authorization
The User model has two many-to-many fields: groups and user_permissions, which are related to the Pemission model.User and Pemission, User and Permission, and Group and Permission are all many-to-many relationships, and Permission defines specific Permission defines specific permissions and has the following fields:
class Permission(): name = (_('name'), max_length=255) # Name of authority (for display) content_type = ( # Content Types: Each model has a content type that can be used to locate the specified model. ContentType, , verbose_name=_('content type'), ) codename = (_('codename'), max_length=100) # The code name of the permission, used in e.g. has_permission function parameter
Adding and removing permissions for a user is simple: myuser.user_permissions.set([permission_list]) myuser.user_permissions.add(permission, permission, ...) myuser.user_permissions.remove(permission, permission, ...) myuser.user_permissions.clear()
where permission is the specific permission object. It is also possible to add corresponding permissions by the group the user is in: ([permission_list]) (permission, permission, ...) (permission, permission, ...) ()
As long as this user joins the group also has group permissions. You can get a list of all permissions (character list) for this user through the get_all_permissions(obj=None) method of the User object, or you can get a list of the corresponding group permissions through get_group_permissions(obj=None).
We more often have to do is to perform operations in the view before the user to verify whether the specified permissions, this is generally used in the User object has_perm (perm, obj = None) method or has_perms (perm_list, obj = None) judgment.
The method `has_perm(perm, obj=None)` has a "." format permission string, and the method returns True if it has that permission. similarly, the `has_perms(perm_list, obj=None)` method has perm_list as a "." format list of permission strings.
As with the login_required decorator, there is a corresponding permission_required decorator for permissions.
permission_required(perm, login_url=None, raise_exception=False)
If raise_exception=True, the PermissionDenied exception is thrown if the permission is not authenticated, and the default 403 page is returned.
This is the entire content of this article.