1 Дизайн модели управления правами
1.1 Создать приложение
Создайте новое приложение с именем system, которое включает основные системные модули, такие как управление пользователями, управление меню и управление полномочиями.
- Используйте pycharm, чтобы открыть наш проект, щелкните правой кнопкой мыши корневой каталог проекта, выберите «Создать» → «Пакет Python» и введите приложения во всплывающем окне.Этот пакет используется для хранения всех приложений, созданных в проекте.
- Выберите «Инструменты» над pycharm и нажмите «Выполнить».manage.pyЗадача ..., затем окно откроется ниже Pycharm, введите STARTAPP System и нажмите Enter, чтобы создать приложение, как показано ниже:
- Переместите только что созданную систему в приложения
- Чтобы успешно получить доступ к нашему новому приложению, щелкните правой кнопкой мыши приложения и выберите «Отметить каталог как» → «Корень источников».
- Измените sandboxMP/sandboxMP/settings.py и добавьте следующее:
import sys
sys.path.insert(0, os.path.join(BASE_DIR, 'apps'))
1.2 Создайте модель аутентификации разрешений
В проекте sandboxMP используется настраиваемая модель аутентификации авторизации.Описание модели:
Menu: 菜单管理,用来存储系统可用的URL
Role: 角色组,通过外键关联Menu,角色组中的用户将继承Role关联菜单的访问权限
Structure:组织架构,包含单位和部门信息
UserProfile: 自定义用户认证模型,替换系统原有的User模型
Следующее содержимое представляет собой подробное содержимое модели аутентификации авторизации. Скопируйте следующее содержимое в apps/system/models.py.
from django.db import models
from django.contrib.auth.models import AbstractUser
class Menu(models.Model):
"""
菜单
"""
name = models.CharField(max_length=30, unique=True, verbose_name="菜单名") # unique=True, 这个字段在表中必须有唯一值.
parent = models.ForeignKey("self", null=True, blank=True, on_delete=models.SET_NULL, verbose_name="父菜单")
icon = models.CharField(max_length=50, null=True, blank=True, verbose_name="图标")
code = models.CharField(max_length=50, null=True, blank=True, verbose_name="编码")
url = models.CharField(max_length=128, unique=True, null=True, blank=True)
def __str__(self):
return self.name
class Meta:
verbose_name = '菜单'
verbose_name_plural = verbose_name
@classmethod
def get_menu_by_request_url(cls, url):
return dict(menu=Menu.objects.get(url=url))
class Role(models.Model):
"""
角色:用于权限绑定
"""
name = models.CharField(max_length=32, unique=True, verbose_name="角色")
permissions = models.ManyToManyField("menu", blank=True, verbose_name="URL授权")
desc = models.CharField(max_length=50, blank=True, null=True, verbose_name="描述")
class Structure(models.Model):
"""
组织架构
"""
type_choices = (("unit", "单位"), ("department", "部门"))
name = models.CharField(max_length=60, verbose_name="名称")
type = models.CharField(max_length=20, choices=type_choices, default="department", verbose_name="类型")
parent = models.ForeignKey("self", null=True, blank=True, on_delete=models.SET_NULL, verbose_name="父类架构")
class Meta:
verbose_name = "组织架构"
verbose_name_plural = verbose_name
def __str__(self):
return self.name
class UserProfile(AbstractUser):
name = models.CharField(max_length=20, default="", verbose_name="姓名")
birthday = models.DateField(null=True, blank=True, verbose_name="出生日期")
gender = models.CharField(max_length=10, choices=(("male", "男"), ("female", "女")),
default="male", verbose_name="性别")
mobile = models.CharField(max_length=11, default="", verbose_name="手机号码")
email = models.EmailField(max_length=50, verbose_name="邮箱")
image = models.ImageField(upload_to="image/%Y/%m", default="image/default.jpg",
max_length=100, null=True, blank=True)
department = models.ForeignKey("Structure", null=True, blank=True, on_delete=models.SET_NULL, verbose_name="部门")
post = models.CharField(max_length=50, null=True, blank=True, verbose_name="职位")
superior = models.ForeignKey("self", null=True, blank=True, on_delete=models.SET_NULL, verbose_name="上级主管")
roles = models.ManyToManyField("role", verbose_name="角色", blank=True)
class Meta:
verbose_name = "用户信息"
verbose_name_plural = verbose_name
ordering = ['id']
def __str__(self):
return self.name
1.3 Использование модели
После определения моделей нам также нужно указать Django использовать эти модели.Нам нужно изменить файл settings.py и добавить имя приложения, где models.py находится в INSTALLED_APPS:
INSTALLED_APPS = [
...原内容省略...
'system',
]
Чтобы использовать пользовательскую модель аутентификации UserProfile, вам также необходимо добавить следующее в settings.py:
AUTH_USER_MODEL = 'system.UserProfile'
Уведомление:
Тип поля ImageField используется при определении пользовательской модели.Перед выполнением makemigrations необходимо установить пакет зависимостей: подушка, открыть окно CMD, войти в виртуальную среду python этого проекта, а затем установить подушку:
C:\Users\RobbieHan>workon sandboxMP
(sandboxMP) C:\Users\RobbieHan>pip install pillow
Вы также можете выполнить команду установки в окне терминала pycharm: pip install Pillow
Наконец, выполните makemigrations и выполните миграцию, чтобы сгенерировать таблицу данных, используйте инструменты pycharm, нажмите «Выполнить».manage.pyЗадача ..., в управлении окном введите следующую команду:
makemigrations
migrate
1.4 Знания, связанные с моделями
Тип поля:
Типы полей, используемые в модели аутентификации авторизации, следующие:
CharField: 用来存储字符串,必须制定一个参数 max_length用来限定字段最大长度
Foreignkey: 是一个关联字段,创建多表之间的多对一关系,如果创建同表之间的递归关联关系,可以使用models.ForeignKey('self')
ManyToManyField: 用来实现多对多的关联关系
DateField: 日期时间字段
EmailField: email字段,用来检查email地址是否合法
ImageField: 图片字段,用来定义图片上传和图片检查,需要安装pillow库
Опции поля:
unique: 设置为True, 则表示这个字段必须有唯一值,这是从数据库级别来强制数据唯一,后面我们还会介绍通过form验证来确保数据输入的唯一
verbose_name:
blank: 默认值是False, 设置为True,则该字段润许为空
null: 默认值是False,如果为True,Django会在数据库中将空值转存为NULL
choices: 是一个可迭代结构(元祖),每个元组中的第一个元素,是存储在数据库中的值;第二个元素是使人容易理解的描述。
on_delete : До django 2.0 параметр on_delete не был необходим при определении поля ассоциации. После django 2.0 параметр on_delete должен быть определен при определении поля ассоциации. Общие параметры следующие:
on_delete=models.CASCADE, # 删除关联数据,与之关联也删除
on_delete=models.DO_NOTHING, # 删除关联数据,什么也不做
on_delete=models.PROTECT, # 删除关联数据,引发错误ProtectedError
on_delete=models.SET_NULL, # 删除关联数据,与之关联的值设置为null
on_delete=models.SET_DEFAULT, # 删除关联数据,与之关联的值设置为默认值
Следует отметить, что при использовании set_null поле необходимо устанавливать при определении модели, например:
user = models.ForeignKey(User, on_delete=models.SET_NULL, blank=True, null=True)
Также при использовании SET_DEFAULT вам необходимо предварительно определить значение по умолчанию:
user = models.ForeignKey(User, on_delete=models.SET_DEFAULT, default='默认值')
Для получения дополнительных типов полей и параметров полей см.:
docs.Django project.com/en/1.11/hotwind…
2 Аутентификация пользователя и ограничение доступа
Требования для аутентификации пользователя при входе в систему следующие:
- Пользователи могут получить доступ к определенным страницам только после входа в систему.
- Если пользователь не вошел в систему, для прямого доступа произойдет переход к экрану входа в систему,
- После того, как пользователь завершит вход в интерфейс входа в систему с переходом, он автоматически получит доступ и перейдет к ранее доступному адресу.
- Пользователь может использовать имя пользователя, номер мобильного телефона или другие поля в качестве имени пользователя для входа.
В pycharm выберите sandboxMP/apps/system, щелкните правой кнопкой мыши, выберите «Создать» → «Файл Python», введите имя во всплывающем окне: views_user и импортируйте необходимые модули на только что созданную страницу:
from django.shortcuts import render
from django.views.generic.base import View
from django.http import HttpResponseRedirect
from django.contrib.auth import authenticate, login, logout
from django.urls import reverse
Описание: Представления, созданные ниже, записываются в файл sandboxMP/apps/system/views_user.py.
2.1 Создание представления индексной страницы
Просмотр страницы индекса является первым представлением, созданным этим проектом:
class IndexView(View):
def get(self, request):
return render(request, 'index.html')
Введение в очки знаний:
1. Просмотр:Введение «представлений» в официальной документации Django используется для инкапсуляции логики обработки пользовательских запросов и возврата ответов.
Мы можем определить функции представления, чтобы принимать веб-запросы и возвращать веб-ответы, или мы можем использовать объекты представлений на основе классов Реализации представлений в этом проекте — это все представления, созданные на основе классов, которые отличаются от представлений на основе функций.
- Код, связанный с HTTP-методом (GET, POST и т. д.), может быть написан в отдельном методе, и нет необходимости судить о HTTP-методе через условные переходы.
- Код может быть разложен на повторно используемые компоненты, такие как Mixin (множественное наследование), с использованием преимуществ объектно-ориентированной технологии, более гибкого использования и простоты расширения.
2. функция визуализации:Быстрая функция Django, которая объединяет заданный шаблон с заданным словарем контекста и возвращает необязательный объект HttpRespose, синтаксис: render(request, template_name, context=None, content_type=None, status=None, using=None), где request и template_name обязательные параметры, а другие являются необязательными параметрами.
2.2 Создайте представление входа пользователя
Прежде чем создавать представление для входа пользователя, сначала создайте файл sandboxMP/apps/system/forms.py для проверки ввода пользователя для входа в систему, содержимое которого выглядит следующим образом:
from django import forms
class LoginForm(forms.Form):
username = forms.CharField(required=True, error_messages={"requeired": "请填写用户名"})
password = forms.CharField(required=True, error_messages={"requeired": "请填写密码"})
Создайте представление входа пользователя:
from .forms import LoginForm
class LoginView(View):
def get(self, request):
if not request.user.is_authenticated:
return render(request, 'system/users/login.html')
else:
return HttpResponseRedirect('/')
def post(self, request):
redirect_to = request.GET.get('next', '/')
login_form = LoginForm(request.POST)
ret = dict(login_form=login_form)
if login_form.is_valid():
user_name = request.POST['username']
pass_word = request.POST['password']
user = authenticate(username=user_name, password=pass_word)
if user is not None:
if user.is_active:
login(request, user)
return HttpResponseRedirect(redirect_to)
else:
ret['msg'] = '用户未激活!'
else:
ret['msg'] = '用户名或密码错误!'
else:
ret['msg'] = '用户和密码不能为空!'
return render(request, 'system/users/login.html', ret)
Введение в очки знаний:
Django использует сеансы и промежуточное программное обеспечение для перехвата объектов запроса в системе аутентификации. Они предоставляют свойство request.user по каждому запросу, представляющим текущий пользователь. Если текущий пользователь не вошел в систему, это свойство будет установлено на экземпляр Anonymousizer, в противном случае он будет экземпляром пользователя.
1. request.user.is_authentential:Используется для определения того, вошел ли пользователь в систему, например, в LoginView:
# 当用户访问登陆页面时,判断用户如果未登入则访问登陆页面,如果登入则跳转到首页
if not request.user.is_authenticated:
return render(request, 'system/users/login.html')
else:
return HttpResponseRedirect('/')
2. is_valid():Для проверки поля используется метод силы формы.Когда значение входного поля является допустимым, он возвращает True и сохраняет данные формы в атрибуте clean_data.
3. аутентификация (запрос = нет, ** учетные данные):Используется для аутентификации пользователей. Учетные данные – это параметр ключевого слова. По умолчанию – имя пользователя и пароль. Если проверено средство аутентификации, возвращается объект User.
4. Войти (запрос, пользователь, Backend = None):Для входа пользователя из представления, а идентификатор пользователя хранится в таблице сеансов. Примечание. Перед вызовом функции login() необходимо использовать аутентификацию(), чтобы успешно аутентифицировать пользователя.
5. HttpResponseRedirect[источник]:Используется для перенаправления доступа. Параметр представляет собой адрес перенаправления, который может быть полным URL-адресом или абсолютным путем к проекту.
2.3 Создайте представление выхода пользователя
class LogoutView(View):
def get(self, request):
logout(request)
return HttpResponseRedirect(reverse('login'))
Введение в очки знаний:
1. выход (запрос):Выйдите из системы.
2. реверс (имя вида):Выполните обратный анализ URL-адреса в соответствии с именем URL-адреса.
2.4 Настройка маршрутизации URL-адресов пользователей
Если вы хотите получить доступ к приложению представления через URL-адрес, вам также необходимо настроить маршрутизацию URL-адресов и изменить файл sandboxMP/sandboxMP/urls.py:
from django.contrib import admin
from django.urls import path
from system.views_user import IndexView, LoginView, LogoutView
urlpatterns = [
path('admin/', admin.site.urls),
path('', IndexView.as_view(), name='index'),
path('login/', LoginView.as_view(), name='login'),
path('logout/', LogoutView.as_view(), name='logout'),
]
2.5 Создайте аутентифицированного пользователя
Выберите «Инструменты» в pycharm и нажмите «Выполнить».manage.pyЗадача..., в открывшемся окне введите createsuperuser, следуйте подсказкам ввести имя пользователя, электронную почту и пароль, операция следующая:
manage.py@sandboxMP > createsuperuser
"C:\Program Files\JetBrains\PyCharm2017.3.2\bin\runnerw.exe" C:\Users\RobbieHan\Envs\sandboxMP\Scripts\python.exe "C:\Program Files\JetBrains\PyCharm2017.3.2\helpers\pycharm\django_manage.py" createsuperuser D:/ProjectFile/sandboxMP
用户名: admin
邮箱: robbie_han@outlook.com
Warning: Password input may be echoed.
Password: !qaz@wsx
Warning: Password input may be echoed.
Password (again): !qaz@wsx
Superuser created successfully.
Запустите проект для доступа к системе:http://127.0.0.1:8000, мы не вошли в систему пользователя и можем напрямую получить доступ к домашней странице, что не соответствует нашим требованиям. Затем внедрите ограничения доступа к странице, требующие, чтобы пользователи вошли в систему для доступа.
2.6 Ограничения доступа к странице
Требования к реализации ограничений доступа к странице:
- Пользователи должны войти в систему, чтобы получить доступ к определенным страницам
- Если пользователь не вошел в систему и получает прямой доступ, он перейдет к интерфейсу входа в систему.
- После того, как пользователь завершит логин на прыжковой посадочной странице, пользователь автоматически доступа к адресу доступа до прыжка
Создайте новый файл sandboxMP/apps/system/mixin.py и напишите следующее содержимое:
from django.contrib.auth.decorators import login_required
class LoginRequiredMixin(object):
@classmethod
def as_view(cls, **init_kwargs):
view = super(LoginRequiredMixin, cls).as_view(**init_kwargs)
return login_required(view)
Измените sandboxMP/sandboxMP/settings.py, добавьте LOGIN_URL
LOGIN_URL = '/login/'
Представления, к которым должны получить доступ вошедшие в систему пользователи, должны наследовать только LoginRequiredMixin.Измененное представление IndexView выглядит следующим образом:
from .mixin import LoginRequiredMixin
class IndexView(LoginRequiredMixin, View):
def get(self, request):
return render(request, 'index.html')
Примечание. LoginRequiredMixin находится в крайнем левом углу списка наследования.
Перезапускаем проект, снова заходим на домашнюю страницу, открываем браузер, вводим http://127.0.0.1:8000, после чего обнаружим, что URL в браузере станет таким:http://127.0.0.1:8000/логин/?следующий=/,Нам нужно перейти на домашнюю страницу после того, как вы выйдете в интернет.
Используйте наших пользователей, созданных в разделе 2.5: Admin, пароль: !QAZ@WSX посадочная система
2.7 Доступ к медиафайлам
Хотя аватар по умолчанию устанавливается при создании пользователя, и изображение, используемое аватаром по умолчанию, размещено, аватар не может отображаться после входа пользователя в систему, поэтому необходимо настроить доступ к медиафайлам.
Медиафайл — это файл, загруженный пользователем, и путь к нему изменен, например файл аватара, загруженный пользователем.
Установить каталог для загрузки файлов
Измените файл sandboxMP/sandboxMP/settings.py и добавьте следующую конфигурацию:
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
Откройте sandboxMP/sandboxMP/urls.py и добавьте следующую конфигурацию:
from django.conf import settings
from django.urls import re_path
from django.views.static import serve
if settings.DEBUG:
urlpatterns += [
re_path(r'^media/(?P<path>.*)$', serve, {"document_root": settings.MEDIA_ROOT}),
]
Вы можете увидеть аватар пользователя, обновив страницу.Следует отметить, что причина использования if settings.DEBUG здесь заключается в том, что этот режим конфигурации следует использовать только в режиме разработки, и эти медиафайлы должны обрабатываться через веб-интерфейс. в производственной среде Доступ.
Самые последние и наиболее полные документы публикуются на Планете знаний, вы можете выполнить поиск в общедоступной учетной записи «Планета знаний» через WeChat и ответить непосредственно на «52824366», чтобы получить доступ.
Документация в этом разделе соответствует версии исходного кода: GitHub.com/Робби Хан/ это…
Заинтересованные друзья очень рады быть гостем на моем Github или Nuggets, В свободное время ставьте лайк или звезду, а также дарите розы в руки и оставляйте аромат
Документ, подтверждающий адрес проекта:GitHub.com/Робби Хан/ это…
Адрес проекта с открытым исходным кодом облегченной системы управления офисом:GitHub.com/Робби Хан/…