如何自定义django 中的authentication?
描述:自己的UserProfile表往往要自己写验证函数等,如何利用上django自带的authenation?
官方解决方法:https://docs.djangoproject.com/en/1.11/topics/auth/customizing/
一般方法:
自定义一个用户权限表:
1 class UserProfile(AbstractBaseUser,PermissionsMixin): 2 '''账号表 3 其中继承的PermissionsMixin是用到了其中权限和组 4 ''' 5 6 email = models.EmailField( 7 verbose_name='email address', 8 max_length=255, 9 unique=True, 10 null=True 11 ) 12 password = models.CharField(_('password'), max_length=128, 13 help_text=mark_safe(''' 14 <a href="password/">change your password</a> 15 ''') # 直接在前端页面上显示这个a标签方便密码的修改 16 ) # 这里是将继承中的password重写 17 name = models.CharField(max_length=32) 18 is_active = models.BooleanField(default=True) # 是否启用 19 is_admin = models.BooleanField(default=False) # 是否管理员 20 roles = models.ManyToManyField("Role", blank=True) 21 objects = UserProfileManager() # 关联到另外一个类 22 stu_account = models.ForeignKey("Customer", verbose_name="关联学员账号", blank=True, null=True, 23 help_text="只有学员报名后方可为其创建账号") 24 USERNAME_FIELD = 'email' # 身份的唯一标识 必须是unique 最主要的 25 REQUIRED_FIELDS = ['name'] # 创建superuser时候被提示 并且不能包含username——field 自动 26 27 def get_full_name(self): # 官方例子中有些必要的方法 28 # The user is identified by their email address 29 return self.email 30 31 def get_short_name(self): 32 # The user is identified by their email address 33 return self.email 34 35 def __str__(self): # 最好是哪个唯一标识 36 return self.email 37 38 def has_perm(self, perm, obj=None): 39 "Does the user have a specific permission?" 40 # Simplest possible answer: Yes, always 41 return True 42 43 def has_module_perms(self, app_label): 44 "Does the user have permissions to view the app `app_label`?" 45 # Simplest possible answer: Yes, always 46 return True 47 48 @property 49 def is_staff(self): 50 "Is the user a member of staff?" 51 # Simplest possible answer: All admins are staff 52 return True
其继承的两个类分别是权限的基类和权限组。字段object对应的类是用来组建普通用户和超级用户的:
class UserProfileManager(BaseUserManager): def create_user(self, email, name, password=None): # 创建一个用户的时候执行的函数 """ Creates and saves a User with the given email, date of birth and password. """ if not email: # email是必须的 raise ValueError('Users must have an email address') user = self.model( email=self.normalize_email(email), name=name, ) user.set_password(password) # 这里是对密码进行加盐哈希的主要过程 self.is_active = True user.save(using=self._db) return user def create_superuser(self,email, name, password): """ Creates and saves a superuser with the given email, date of birth and password. """ user = self.create_user( email, password=password, name=name, ) user.is_active = True user.is_admin = True user.save(using=self._db) return user
最后在setting中写入:AUTH_USER_MODEL = 'crm.UserProfile' 这样使得django默认的用户认证为自己的表。
完成后一下是注册admin过程中的自定义:
1 class UserProfileAdmin(BaseUserAdmin): 2 # The forms to add and change user instances 3 form = UserChangeForm 4 add_form = UserCreationForm 5 6 # The fields to be used in displaying the User model. 7 # These override the definitions on the base UserAdmin 8 # that reference specific fields on auth.User. 9 list_display = ('email', 'name', 'is_admin',"stu_account") 10 list_filter = ('is_admin',) 11 fieldsets = ( 12 (None, {'fields': ('email','password')}), 13 ('Personal', {'fields': ('name',)}), 14 ('Permissions', {'fields': ('is_admin','is_active',"user_permissions","groups")}), 15 ) 16 # add_fieldsets is not a standard ModelAdmin attribute. UserAdmin 17 # overrides get_fieldsets to use this attribute when creating a user. 18 add_fieldsets = ( 19 (None, { 20 'classes': ('wide',), 21 'fields': ('email', 'name', 'password1', 'password2')} 22 ), 23 ) 24 search_fields = ('email',) 25 ordering = ('email',) 26 filter_horizontal = ("user_permissions","groups") 27 28 29 # Now register the new UserAdmin... 30 admin.site.register(models.UserProfile, UserProfileAdmin)
这里多数的代码都是写死了不能变的。这个是注册时候的class,会引用到两个字段:form 和 add_form 下面有些一般不用改变 分别定义了修改和添加用户时所用到的东西。
特殊的fieldsets中字典中的每一个元组中对应的都是展示的内容:
add_fields中表示添加时候需要的字段。所需要的两个类:
class UserCreationForm(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 = models.UserProfile fields = ('email', 'name') 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(UserCreationForm, 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 = models.UserProfile fields = ('email', 'password', 'name', 'is_active', 'is_admin') 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"]
如何利用django的登录验证?
django中提供了封装好的用户验证和登录(验证,记录session,返回之前页面等)简单易用!只要引入:
from django.contrib.auth import login,authenticate,logout
1 user = authenticate(username=email, password=password) # 利用django自带 的验证功能 2 if user: 3 login(request, user) # 登录成功 记录session 4 next_url = request.GET.get("next", "/") 5 return render(request,"main/content.html") 6 else: 7 errors['error'] = "Wrong username or password!"
将用户账号密码传入,这里若是成功则返回用户对象否则返回为空。这是验证通过login登录成功记录session。
后面的是拿到登录之前的页面url,登录成功后跳转到这个页面。
同理logout也是一句话:
def logout_all(request):
logout(request)
return redirect("/login/")
如何将用户验证包装到具体的views函数上?
from django.contrib.auth.decorators import login_required
并将需要的函数装饰器上:@login_required
如何运用django的ModelForm进行表的增删改查,数据验证,前端生成等操作?
详细:http://www.cnblogs.com/khal-Cgg/p/6237575.html
django中models有choice这种选择数据类型,往往前端显示的都是内容的序号如何解决?
详述:
attendance = models.SmallIntegerField(choices=attendance_choices,default=0)
attendance_choices = ((0,'已签到'),
(1,'迟到'),
(2,'缺勤'),
(3,'早退'),
)
这是其中一个表的一个字段,django的choices限制了他只能从attendance_choices列表中选择。但是在前端直接显示的时候利用自动生成的{{field}}中显示的都是选择的序号。如何修改为显示内容,又如何做成select的样式显示多种选择?
解决方法:
必须通过simple_tag来显示在前端,假如通过反射拿到了choices的字段filed这个对象那么:
field.choices 就是那个attendance_choices列表,这样循环加入option标签中就可。
至于到底选择了那个可以用:
result = getattr(obj, "get_%s_display")() # obj是整个表的对象 中间的format是带choice的上述的field
result就是具体出勤情况,判断是否相同给options加上selected就行。
。。。。。。