• Django 常用的 Web 应用程序工具


    Django 提供了多种开发 Web 应用程序所需的常用工具,如:缓存、日志、发送邮件、自定义认证等,更多可参考:<https://docs.djangoproject.com/zh-hans/2.2/>

    1. 自定义权限

    要为给定模型对象创建自定义权限,请使用 permissions 模型Meta属性

    # 创建两个自定义权限,即用户可以或不可以Task对应用程序执行的操作的操作
    class Task(models.Model):
        ...
        class Meta:
            permissions = [
                ("change_task_status", "可以改变任务的状态"),
                ("close_task", "可以通过将其状态设置为已关闭来删除任务"),
            ]
    

    检查用户是否有某个权限:

    user.has_perm('app.close_task')			# has_perm()  方法
    

    更多权限可查看 auth_permission 表:

    2. 扩展现有 User模型

    2.1 一对一关联 User

    如果您希望存储与之相关的信息User,可以使用a OneToOneField到包含这些字段的模型以获取其他信息。这种一对一模型通常称为配置文件模型,因为它可能存储有关站点用户的非身份验证相关信息。例如,您可以创建一个Employee模型:

    from django.contrib.auth.models import User
    
    class Employee(models.Model):
        user = models.OneToOneField(User, on_delete=models.CASCADE)
        department = models.CharField(max_length=100)
    

    访问:

    >>> u = User.objects.get(username='fsmith')
    >>> freds_department = u.employee.department
    

    要将配置文件模型的字段添加到管理员的用户页面,另外还需配置 admin.py

    from django.contrib import admin
    from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
    from django.contrib.auth.models import User
    
    from my_user_profile_app.models import Employee
    
    # Define an inline admin descriptor for Employee model
    # which acts a bit like a singleton
    class EmployeeInline(admin.StackedInline):
        model = Employee
        can_delete = False
        verbose_name_plural = 'employee'
    
    # Define a new User admin
    class UserAdmin(BaseUserAdmin):
        inlines = (EmployeeInline,)
    
    # Re-register UserAdmin
    admin.site.unregister(User)
    admin.site.register(User, UserAdmin)
    

    2.2 替换自定义User模型

    如果你不想用 auth_user 这个表名,你也可以在 settings 中 配置`

    AUTH_USER_MODEL = 'myapp.MyUser'
    

    2.3 在启动项目时使用自定义用户模型

    如果您要开始一个新项目,强烈建议您设置自定义用户模型,即使默认User模型足够您。此模型的行为与默认用户模型相同,但如果需要,您将来可以自定义它:

    from django.contrib.auth.models import AbstractUser
    
    class User(AbstractUser):
        pass
    

    别忘了指出AUTH_USER_MODEL它。在创建任何迁移或第一次运行之前执行此操作。manage.py migrate

    此外,在应用程序中注册模型admin.py

    from django.contrib import admin
    from django.contrib.auth.admin import UserAdmin
    from .models import User
    
    admin.site.register(User, UserAdmin)
    

    2.4 用户自定义认证

    为了便于将Django的权限框架包含到您自己的用户类中,Django提供了PermissionsMixin。这是一个抽象模型,可以包含在用户模型的类层次结构中,为您提供支持Django权限模型所需的所有方法和数据库字段。

    PermissionsMixin 提供了以下方法和属性:

    • is_superuser()
    • has_perm(perm):是否有指定权限
    • has_perms(perm_list):权限列表

    除了上面三个还有很多,可以查看官网提供的文档或者源码:<https://docs.djangoproject.com/zh-hans/2.2/topics/auth/customizing/>

    1、settings.py

    AUTH_USER_MODEL = 'crm.UserProfile'
    

    2、models.py

    models 中我们自定义用户认证,继承以下三个类,使得我们可以使用 Django 提供的权限工具、用户认证等工具。

    • BaseUserManager:提供创建普通、超级用户方法或属性
    • AbstractBaseUser:提供将密码加密、验证用户是否登录等方法或属性
    • PermissionsMixin:提供权限相关方法或属性
    from django.db import models
    from django.contrib.auth.models import (
        BaseUserManager, AbstractBaseUser, PermissionsMixin
    )
    
    class UserProfileManager(BaseUserManager):
        def create_user(self, email, name, password=None):
            """创建普通用户"""
            if not email:
                raise ValueError('用户必须有一个邮箱地址')
    
            user = self.model(
                email=self.normalize_email(email),
                name=name,
            )
    		# 将密码明文变成密文(md5+salt)
            user.set_password(password)
            user.save(using=self._db)	# 保存
            return user
    
        def create_superuser(self, email, name, password):
            """创建超级用户"""
            user = self.create_user(
                email,
                password=password,
                name=name,
            )
            user.is_admin = True	
            user.save(using=self._db)
            return user
    
    
    class UserProfile(AbstractBaseUser,PermissionsMixin):
        email = models.EmailField(
            verbose_name='邮箱',
            max_length=255,
            unique=True,
        )
        name = models.CharField(max_length=64)
        role = models.ManyToManyField(Role, blank=True, null=True)
        is_active = models.BooleanField(default=True)
        is_admin = models.BooleanField(default=False)
        is_staff = models.BooleanField(default=False)
        # 创建普通用户和超级用户,关联上面的
        objects = UserProfileManager()
    
        USERNAME_FIELD = 'email'
        #必须要有的字段
        REQUIRED_FIELDS = ['name']
    
        def __str__(self):
            return self.email
    
        def has_perm(self, perm, obj=None):
        	"""判断用户是否有权限"""
            return True
    
        def has_module_perms(self, app_label):
            "判断用户是否有权查看 app `app_label`?"
            return True
    
        def get_full_name(self):
            # The user is identified by their email address
            return self.email
    
        def get_short_name(self):
            # The user is identified by their email address
            return self.email
    
        @property
        def is_staff(self):
            "Is the user a member of staff?"
            # Simplest possible answer: All admins are staff
            return self.is_admin
    

    3、admin.py

    from django import forms
    from django.contrib import admin
    from django.contrib.auth.models import Group
    from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
    from django.contrib.auth.forms import ReadOnlyPasswordHashField
    
    from app01.models import UserProfile
    
    
    class UserCreationForm(forms.ModelForm):
        """用于创建新用户的表单。 包括所有要求字段,加上重复的密码."""
        password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
        password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput)
    
        class Meta:
            model = 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("两次密码不匹配")
            return password2
    
        def save(self, commit=True):
            # Save the provided password in hashed format
            # 继承基类的save()
            user = super(UserCreationForm, self).save(commit=False)
            # 把明文密码改成密文
            user.set_password(self.cleaned_data["password1"])
            if commit:
                user.save()
            return user
    
    
    class UserChangeForm(forms.ModelForm):
        """用于更新用户的表单。 包括所有字段用户,但用admin's替换密码字段密码哈希显示字段.
        """
        # 把密码改成哈希的了
        password = ReadOnlyPasswordHashField()
    
        class Meta:
            model = UserProfile
            fields = ('email', 'password', 'name', 'is_active', 'is_superuser')
    
        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 UserProfileAdmin(BaseUserAdmin):
        # The forms to add and change user instances
        form = UserChangeForm
        add_form = UserCreationForm
    
        # The fields to be used in displaying the User model.
        # These override the definitions on the base UserAdmin
        # that reference specific fields on auth.User.
        list_display = ('email', 'name','is_superuser')
        list_filter = ('is_superuser',)
        fieldsets = (
            (None, {'fields': ('email', 'password')}),
            ('Personal info', {'fields': ('name',)}),
            ('Permissions', {'fields': ('is_staff','is_active','role','user_permissions','groups','is_superuser')}),
        )
        # add_fieldsets is not a standard ModelAdmin attribute. UserAdmin
        # overrides get_fieldsets to use this attribute when creating a user.
        add_fieldsets = (
            (None, {
                'classes': ('wide',),
                'fields': ('email', 'name', 'password1', 'password2')}
            ),
        )
        search_fields = ('email',)
        ordering = ('email',)
        filter_horizontal = ('role','user_permissions','groups')
    
    # Now register the new UserProfileAdmin...
    admin.site.register(UserProfile, UserProfileAdmin)
    # ... and, since we're not using Django's built-in permissions,
    # unregister the Group model from admin.
    # admin.site.unregister(Group)
    
  • 相关阅读:
    Mysql count(*)与count(col)d对比
    Mysql区分度很差是否有必要建索引
    Vscode换背景图片
    常用正则匹配规则
    开源项目
    你会用ES6,那倒是用啊!(转自掘金红尘炼心)
    C compiler "gcc" not found: exec: "gcc": executable file not found in %PATH%
    HTTP长连接、短连接究竟是什么?
    我看懂了oracle中pivot行转列的用法
    xshell无法调用gdc
  • 原文地址:https://www.cnblogs.com/midworld/p/11380480.html
Copyright © 2020-2023  润新知