精华整理

如何自定义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
View Code

最后在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"]
View Code

如何利用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就行。

。。。。。。

原文地址:https://www.cnblogs.com/khal-Cgg/p/6527182.html