Django使用自己的用户系统

2022-06-30 20:16:39 浏览数 (1)

用过django的人应该都会知道admin,不过,需求是多变的,比如,你有一个变态的用户系统,用户可能有大中小三张头像,除了fisrt name ,last name外还有middle name,T^T name巴拉巴拉,django 的用户系统可能满足不了你的需求,这时候需要用自己的用户系统了,如何能在满足需求的时候充分又利用到django的用户系统?

django使用自己的用户系统 step-1 写自己的auth模块(定义user class) step-2 admin.py 注册到django的admin后台,并且修改一些field step-3 修改settings.py中相应配置

django使用自己的用户系统 用过django的人应该都会知道admin,什么,真的没用过?汗,如果这样的话先看看这个 https://docs.djangoproject.com/en/1.6/ref/contrib/admin/

django自带用户系统,通过上面的admin,以及auth可以方便的管理用户。

不过,需求是多变的,比如,你有一个变态的用户系统,用户可能有大中小三张头像, 除了fisrt name ,last name外还有middle name,T^T name巴拉巴拉,django 的用户系统可能满足不了你的需求,这时候需要用自己的用户系统了,如何能在满足 需求的时候充分又利用到django的用户系统?

官方文档如下,内有详细说明,有英文厌烦症的可以直接略过 https://docs.djangoproject.com/en/dev/topics/auth/customizing/

其实步骤很简单

写自己的auth模块(定义user class); admin.py 注册到django的admin后台,并且修改一些field 修改settings.py中相应配置 step-1 写自己的auth模块(定义user class) 新建一个模块,名字随意,假设叫做myauth

User class继承AbstractBaseUser,UserManager继承BaseUserManager 重写对应的方法,建议浏览下AbstractBaseUser, BaseUserManager的源码

User类不用说,也就是根据自己业务定义的用户class,Manager就是django中 的Manager,做的事情你肯定经常用到,obj.objects.filter(),其中的objects 就是Manager,文档如下 https://docs.djangoproject.com/en/dev/topics/db/managers/

code

# -*- coding: utf-8 -*- from django.db import models from django.contrib.auth.models import (BaseUserManager, AbstractBaseUser)

class UserManager(BaseUserManager):

    def create_user(self, name, email, password=None):

        if not email:             raise ValueError('Users must have an email address')

        user = self.model(             name=name,             email=UserManager.normalize_email(email),         )

        user.set_password(password)         user.save(using=self._db)         return user

    def create_superuser(self, name, email, password=None):

        user = self.create_user(name, email, password)         user.is_admin = True         user.save(using=self._db)         return user

class User(AbstractBaseUser):     '''用户表'''

    name = models.CharField(max_length=100, unique=True)     email = models.EmailField(max_length=100, unique=True)     avatar = models.URLField(blank=True)     created_at = models.DateTimeField(auto_now_add=True)     updated_at = models.DateTimeField(auto_now=True)     is_delete = models.BooleanField(default=False)     is_active = models.BooleanField(default=True)     is_admin = models.BooleanField(default=False)     access_token = models.CharField(max_length=100, blank=True)     refresh_token = models.CharField(max_length=100, blank=True)     expires_in = models.BigIntegerField(max_length=100, default=0)

    objects = UserManager()

    USERNAME_FIELD = 'name'     REQUIRED_FIELDS = ('email',)

    class Meta:         ordering = ('-created_at',)

    def __unicode__(self):         return self.name

    def get_full_name(self):         return self.email

    def get_short_name(self):         return self.name

    def has_perm(self, perm, obj=None):         return True

    def has_module_perms(self, app_label):         return True

    @property     def is_staff(self):         return self.is_admin

重写的字段看下源码就可以解释到了:

1. AbstractBaseUser已经有password, last_login,所以密码这些就不用费心了 2. 由于get_username用到了self.USERNAME_FIELD,所以需要指明哪个字段为用户名 3. get_short_name,get_full_name需要实现,否则会抛异常 4. 其他就按照自己的业务来写即可 5. UserManager重写下两个create方法

class AbstractBaseUser(models.Model):     password = models.CharField(_('password'), max_length=128)     last_login = models.DateTimeField(_('last login'), default=timezone.now)

    is_active = True

    REQUIRED_FIELDS = []

    class Meta:         abstract = True

    def get_username(self):         "Return the identifying username for this User"         return getattr(self, self.USERNAME_FIELD)

    def __str__(self):         return self.get_username()

    def natural_key(self):         return (self.get_username(),)

    def is_anonymous(self):         """         Always returns False. This is a way of comparing User objects to         anonymous users.         """         return False

    def is_authenticated(self):         """         Always return True. This is a way to tell if the user has been         authenticated in templates.         """         return True

    def set_password(self, raw_password):         self.password = make_password(raw_password)

    def check_password(self, raw_password):         """         Returns a boolean of whether the raw_password was correct. Handles         hashing formats behind the scenes.         """         def setter(raw_password):             self.set_password(raw_password)             self.save(update_fields=["password"])         return check_password(raw_password, self.password, setter)

    def set_unusable_password(self):         # Sets a value that will never be a valid hash         self.password = make_password(None)

    def has_usable_password(self):         return is_password_usable(self.password)

    def get_full_name(self):         raise NotImplementedError()

    def get_short_name(self):         raise NotImplementedError()

step-2 admin.py 注册到django的admin后台,并且修改一些field admin注册user,参考文档 https://docs.djangoproject.com/en/dev/ref/contrib/admin/ 代码如下,感觉没什么需要说明的。

myauth/admin.py

#coding: utf-8

from django import forms from django.contrib import admin from django.contrib.auth.models import Group as DjangoGroup from django.contrib.auth.admin import UserAdmin from django.contrib.auth.forms import ReadOnlyPasswordHashField

from myauth.models import User

# 新增用户表单 class UserCreateForm(forms.ModelForm):     """A form for creating new users. Includes all the required     fields, plus a repeated password."""     password1 = forms.CharField(label='Password', widget=forms.PasswordInput)     password2 = forms.CharField(         label='Password confirmation',         widget=forms.PasswordInput,     )

    class Meta:         model = User         fields = ('name', 'email')

    def clean_password2(self):         # Check that the two password entries match         password1 = self.cleaned_data.get("password1")         password2 = self.cleaned_data.get("password2")         if password1 and password2 and password1 != password2:             raise forms.ValidationError("Passwords don't match")         return password2

    def save(self, commit=True):         # Save the provided password in hashed format         user = super(UserCreateForm, self).save(commit=False)         user.set_password(self.cleaned_data["password1"])         if commit:             user.save()         return user

# 修改用户表单 class UserChangeForm(forms.ModelForm):     """A form for updating users. Includes all the fields on     the user, but replaces the password field with admin's     password hash display field.     """     password = ReadOnlyPasswordHashField()

    class Meta:         model = User

    def clean_password(self):         # Regardless of what the user provides, return the initial value.         # This is done here, rather than on the field, because the         # field does not have access to the initial value         return self.initial["password"]

# 注册用户 class MyUserAdmin(UserAdmin):

    form = UserChangeForm     add_form = UserCreateForm

    list_display = ('name', 'created_at', 'email', 'is_delete', 'is_admin')     search_fields = ('name', 'email')     list_filter = ('is_admin',)     readonly_fields = ('created_at', 'updated_at')     fieldsets = (         (None, {'fields': ('name', 'email', 'password', 'avatar',)}),         ('Personal info', {'fields': ('created_at', 'updated_at')}),         (             'Open token info',             {                 'fields': ('access_token', 'refresh_token', 'expires_in')             }         ),         ('Permissions', {'fields': ('is_delete', 'is_admin', 'is_active')}),         ('Important dates', {'fields': ('last_login',)}),     )     add_fieldsets = (         (             None,             {                 'classes': ('wide',),                 'fields': ('name', 'email', 'password1', 'password2'),             }         ),     )     ordering = ('created_at',)     filter_horizontal = ()

admin.site.register(User, MyUserAdmin)

step-3 修改settings.py中相应配置 添加 AUTH_USER_MODEL = 'myauth.User' install_app不要忘记加上myauth模块

grep django的源码可以看到,很多地方直接使用了配置AUTH_USER_MODEL

user = models.ForeignKey(settings.AUTH_USER_MODEL)

def get_user_model():     """     Returns the User model that is active in this project.     """     from django.db.models import get_model

    try:         app_label, model_name = settings.AUTH_USER_MODEL.split('.')     except ValueError:         raise ImproperlyConfigured("AUTH_USER_MODEL must be of the form 'app_label.model_name'")     user_model = get_model(app_label, model_name)     if user_model is None:         raise ImproperlyConfigured("AUTH_USER_MODEL refers to model '%s' that has not been installed" % settings.AUTH_USER_MODEL)     return user_model

ps: django admin更改主题,django admin的主题实在是太朴素了 https://riccardo.forina.me/bootstrap-your-django-admin-in-3-minutes/

0 人点赞