zoukankan      html  css  js  c++  java
  • 精华整理

    如何自定义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就行。

    。。。。。。

  • 相关阅读:
    支持向量机(SVM)相关免费学习视频集锦
    《量化投资:以MATLAB为工具》连载(2)基础篇-N分钟学会MATLAB(中)
    《量化投资:以MATLAB为工具》连载(1)基础篇-N分钟学会MATLAB(上)
    OpenCV 轮廓基本特征
    !!破解灯塔线取点与画线的“难点”
    理工科应该的知道的C/C++数学计算库(转)
    521. 最长特殊序列 Ⅰ
    520. 检测大写字母
    459. 重复的子字符串
    443. 压缩字符串
  • 原文地址:https://www.cnblogs.com/khal-Cgg/p/6527182.html
Copyright © 2011-2022 走看看