Python-S9——Day83-ORM项目实战

  • 01 上节回顾
  • 02 后台管理布局
  • 03 按钮权限控制的简单形式
  • 04 修改表结构
  • 05 重构数据结构
  • 06 限制权限颗粒度

01 上节回顾

1.1 项目的组织架构;

1.2 项目组件的版本说明;

  使用的是Django1.11.1与最新的Django有区别,请注意。另外Pycharm创建的Django项目一般都是最新的,2018版本Pycharm自带virtualenv环境,无需个人再次安装。如需执行Django版本,可在本机的Python解释器环境下,pip install django=="1.11.1",然后通过Pycharm创建Django项目的时候指定一下内置的Python解释器,见下图。

1.3 settings.py文件说明;

自行配置TEMPLATES中的DIRS;

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')]
        ,
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

settings.py

"""
Django settings for s9day82_rbac project.

Generated by 'django-admin startproject' using Django 1.11.1.

For more information on this file, see
https://docs.djangoproject.com/en/1.11/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/1.11/ref/settings/
"""

import os

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = '0s(th#!ewf^xik5n&bqkqqjadz#q*vt+!hq(kzk5*-!t6@^0^i'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = []

# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'app01.apps.App01Config',
    'rbac.apps.RbacConfig',
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'rbac.service.rbac.ValidPermission',
]
from django.middleware.security import SecurityMiddleware

ROOT_URLCONF = 's9day82_rbac.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')]
        ,
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 's9day82_rbac.wsgi.application'

# Database
# https://docs.djangoproject.com/en/1.11/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}

# Password validation
# https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]

# Internationalization
# https://docs.djangoproject.com/en/1.11/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True

# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.11/howto/static-files/

STATIC_URL = '/static/'

1.4 urls.py;

"""s9day82_rbac URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/1.11/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.conf.urls import url, include
    2. Add a URL to urlpatterns:  url(r'^blog/', include('blog.urls'))
"""
from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^users/$', views.users),
    url(r'^users/add', views.add_user),
    url(r'^roles/', views.roles),
    url(r'^login/', views.login),
]

1.5 views.py;

import re
from django.shortcuts import render, HttpResponse

# Create your views here.

from rbac.models import *
from rbac.service.permissions import *


def users(request):
    user_list = User.objects.all()
    return render(request, "users.html", locals())


def add_user(request):
    return HttpResponse("Add User......")


def roles(request):
    role_list = Role.objects.all()
    return render(request, "roles.html......", locals())


def login(request):
    if request.method == "POST":
        user_obj = request.POST.get("user")
        pwd = request.POST.get("pwd")
        user = User.objects.filter(name=user_obj, pwd=pwd).first()
        if user:
            # #################在session中注册用户ID###########################;
            request.session["user_id"] = user.pk
            initial_session(user, request)
            '''
            此处的values()相当于:
            temp = []#定义一个空列表;
            for role in user.roles.all();#values属性,相当于循环该对象[<Role: 保洁>, <Role: 销售>]>
                temp.append({
                "title":role.title,
                "permissions__url":role.permissions.all()
                })
            '''
            return HttpResponse("登录成功!")
    return render(request, "login.html", locals())

1.6 models.py;

from django.db import models


# Create your models here.

class User(models.Model):
    name = models.CharField(max_length=32)
    pwd = models.CharField(max_length=32)
    roles = models.ManyToManyField(to="Role")

    def __str__(self):
        return self.name


class Role(models.Model):
    title = models.CharField(max_length=32)
    permissions = models.ManyToManyField(to="Permission")

    def __str__(self):
        return self.title


class Permission(models.Model):
    title = models.CharField(max_length=32)
    url = models.CharField(max_length=32)

    def __str__(self):
        return self.title

1.7 templates模板文件;

login.html 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h4>登录页面</h4>

<form action="" method="post">
    {% csrf_token %}
    用户名:<input type="text" name="user">
    密码:<input type="password" name="pwd">
    <input type="submit">
</form>
</body>
</html>

roles.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Users</title>
</head>
<body>
<h4>角色列表</h4>
<ul>
    {% for role in role_list %}
        <p>{{ role }}</p>
    {% endfor %}

</ul>
</body>
</html>

1.8 permissions.py

def initial_session(user, request):
    # #################在session注册权限列表###########################;
    # 查询当前登录用户的所有角色;
    ret = user.roles.all()
    print("ret", ret)  # <QuerySet [<Role: 保洁>, <Role: 销售>]>

    # 查询当前用户的所有权限;
    permissions = user.roles.all().values(
        "permissions__url").distinct()  # ret_role <QuerySet [{'permissions__url': '/users/'},
    #  {'permissions__url': '/users/add'}]>

    # 进行数据的处理,生成列表;
    permission_list = []
    for item in permissions:
        permission_list.append(item["permissions__url"])
    print("permission_list", permission_list)  # permission_list ['/users/', '/users/add']

    request.session["permission_list"] = permission_list

02 后台管理布局

login.html;

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<h4>登录页面</h4>

<form action="" method="post">
    {% csrf_token %}
    用户名:<input type="text" name="user">
    密码:<input type="password" name="pwd">
    <input type="submit">
</form>
</body>
</html>

base.html;

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
    <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css"
          integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
    <style>
        .header {
            width: 100%;
            height: 60px;
            background-color: #336699;

        }

        .menu {
            background-color: bisque;
            position: fixed;
            top: 60px;
            bottom: 0;
            left: 0;
            width: 200px;
        }

        .content {
            position: fixed;
            top: 60px;
            bottom: 0;
            right: 0;
            left: 200px;
            overflow: auto;
            padding: 30px;
        }
    </style>
</head>
<body>
<div class="header">
    <p>{{ user.name }}</p>
</div>
<div class="contain">

    <div class="menu">11</div>
    <div class="content ">
        {% block con %}

        {% endblock %}
    </div>

</div>
</body>
</html>

users.html;

{% extends 'base.html' %}
{% block con %}
    <h4>用户列表</h4>
    {% if per.add  %}
        <a href="/users/add/" class="btn btn-primary">添加用户</a>
    {% endif %}

    <table class="table table-bordered table-striped">
        <thead>
        <tr>
            <th>序号</th>
            <th>姓名</th>
            <th>角色</th>
            <th>操作</th>
        </tr>
        </thead>
        <tbody>

        {% for user in user_list %}
            <tr>
                <td>{{ forloop.counter }}</td>
                <td>{{ user.name }}</td>
                <td>
                    {% for role in user.roles.all %}
                        {{ role.title }}
                    {% endfor %}
                </td>
                <td>
                    {% if per.delete %}
                        <a href="/users/delete/{{ user.pk }}" class="btn btn-danger">删除</a>
                    {% endif %}
                    {% if per.edit %}
                        <a href="" class="btn btn-info">编辑</a>
                    {% endif %}
                </td>
            </tr>
        {% endfor %}

        </tbody>
    </table>
{% endblock %}

roles.html;

{% extends 'base.html' %}
{% block con %}
    <h4>角色列表</h4>
    {% if per.add %}
        <a href="" class="btn btn-primary">添加角色</a>
    {% endif %}

    <table class="table table-bordered table-striped">
        <tbody>
        {% for role in role_list %}
            <tr>
                <td>{{ forloop.counter }}</td>
                <td>{{ role.title }}</td>
                <td>
                    <a href="/users/delete/{{ user.pk }}" class="btn btn-danger">删除</a>
                    <a href="" class="btn btn-info">编辑</a>
                </td>
            </tr>
        {% endfor %}
        </tbody>
    </table>
{% endblock %}

03 按钮权限控制的简单形式

1、引入CDN的Bootstrap;

    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
    <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css"
          integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">

04 修改表结构

from django.db import models


# Create your models here.

class User(models.Model):
    name = models.CharField(max_length=32)
    pwd = models.CharField(max_length=32)
    roles = models.ManyToManyField(to="Role")

    def __str__(self):
        return self.name


class Role(models.Model):
    title = models.CharField(max_length=32)
    permissions = models.ManyToManyField(to="Permission")

    def __str__(self):
        return self.title


class Permission(models.Model):
    title = models.CharField(max_length=32)
    url = models.CharField(max_length=32)
    action = models.CharField(max_length=32, default="")
    group = models.ForeignKey("PermissionGroup", default=1)

    def __str__(self):
        return self.title


class PermissionGroup(models.Model):
    title = models.CharField(max_length=32)

    def __str__(self):
        return self.title

05 重构数据结构

06 限制权限颗粒度

settings.py; 

"""
Django settings for s9day82_rbac project.

Generated by 'django-admin startproject' using Django 1.11.1.

For more information on this file, see
https://docs.djangoproject.com/en/1.11/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/1.11/ref/settings/
"""

import os

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = '0s(th#!ewf^xik5n&bqkqqjadz#q*vt+!hq(kzk5*-!t6@^0^i'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = []

# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'app01.apps.App01Config',
    'rbac.apps.RbacConfig',
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'rbac.service.rbac.ValidPermission',
]
from django.middleware.security import SecurityMiddleware

ROOT_URLCONF = 's9day82_rbac.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')]
        ,
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 's9day82_rbac.wsgi.application'

# Database
# https://docs.djangoproject.com/en/1.11/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}

# Password validation
# https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]

# Internationalization
# https://docs.djangoproject.com/en/1.11/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True

# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.11/howto/static-files/

STATIC_URL = '/static/'

urls.py;

"""s9day82_rbac URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/1.11/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.conf.urls import url, include
    2. Add a URL to urlpatterns:  url(r'^blog/', include('blog.urls'))
"""
from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^users/$', views.users),
    url(r'^users/add', views.add_user),
    url(r'^users/delete/(d+)', views.del_user),
    url(r'^roles/', views.roles),
    url(r'^login/', views.login),
] 
原文地址:https://www.cnblogs.com/tqtl911/p/9582962.html