用過django的人應該都會知道admin,什麼,真的沒用過?汗,若是這樣的話先看看這個
https://docs.djangoproject.com/en/1.6/ref/contrib/admin/django
django自帶用戶系統,經過上面的admin,以及auth能夠方便的管理用戶。bootstrap
不過,需求是多變的,好比,你有一個變態的用戶系統,用戶可能有大中小三張頭像,
除了fisrt name ,last name外還有middle name,T^T name巴拉巴拉,django
的用戶系統可能知足不了你的需求,這時候須要用本身的用戶系統了,如何能在知足
需求的時候充分又利用到django的用戶系統?app
官方文檔以下,內有詳細說明,有英文厭煩症的能夠直接略過
https://docs.djangoproject.com/en/dev/topics/auth/customizing/less
其實步驟很簡單ide
新建一個模塊,名字隨意,假設叫作myauthui
User class繼承AbstractBaseUser,UserManager繼承BaseUserManager
重寫對應的方法,建議瀏覽下AbstractBaseUser, BaseUserManager的源碼this
User類不用說,也就是根據本身業務定義的用戶class,Manager就是django中
的Manager,作的事情你確定常常用到,obj.objects.filter(),其中的objects
就是Manager,文檔以下
https://docs.djangoproject.com/en/dev/topics/db/managers/code
codeorm
# -*- 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()
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)
添加 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/