Django补充
django配置文件相关操作
django实际上有两个配置文件
一个是提供给用户可以自定义的基本配置
from 项目名 import settings
一个是全局的系统默认的配置
from django.conf import global_settings
提示:用户不指定的情况下采用全局的系统默认的配置
配置文件使用的优先级
用户如果在提供给用户的配置文件中指定了配置就使用用户指定的配置,不指定的情况下则使用系统默认的配置
django两个配置文件的关系
提供给用户的配置文件中有的配置,系统配置文件中肯定有
提供给用户的配置文件中没有的配置,系统配置文件中也有
在django中如果想要同时使用两个配置文件的导入方式
from django.conf import settings
基于django配置文件源码编写代码
os.environ
可看成是一个项目全局的大字典,任何地方都可以使用
django的入口文件是manage.py
可看成是启动文件
os.environ.setdefault()
相当于给字典添加键值对
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day67.settings")
print(settings.BASE_DIR) # C:\D_disk\PythonProject\week14\day67,没有添加会报错django.core.exceptions.ImproperlyConfigured: Requested setting BASE_DIR, but settings are not configured. You must either define the environment variable DJANGO_SETTINGS_MODULE or call settings.configure() before accessing settings.
源码分析
class LazySettings(LazyObject):
"""
A lazy proxy for either global Django settings or a custom settings object.
The user can manually configure settings prior to using them. Otherwise,
Django uses the settings module pointed to by DJANGO_SETTINGS_MODULE.
"""
def _setup(self, name=None):
"""
Load the settings module pointed to by the environment variable. This
is used the first time we need any settings at all, if the user has not
previously configured the settings manually.
"""
settings_module = os.environ.get(ENVIRONMENT_VARIABLE) # 获取提供给用户的配置文件字符串路径 'day67.settings'
if not settings_module:
desc = ("setting %s" % name) if name else "settings"
raise ImproperlyConfigured(
"Requested %s, but settings are not configured. "
"You must either define the environment variable %s "
"or call settings.configure() before accessing settings."
% (desc, ENVIRONMENT_VARIABLE))
self._wrapped = Settings(settings_module) # 将上述字符串路径当做参数传给Settings类实例化
class Settings(object):
def __init__(self, settings_module):
# update this dict from global settings (but only for ALL_CAPS settings)
for setting in dir(global_settings): # 获取系统配置文件中所有的变量名
if setting.isupper(): # 校验变量名是否是纯大写
setattr(self, setting, getattr(global_settings, setting)) # 给settings对象赋值通过反射获取到的系统配置文件中所有的大写变量名和对应的值
# store the settings module in case someone later cares
self.SETTINGS_MODULE = settings_module # 存储设置模块,后面可能用到
mod = importlib.import_module(self.SETTINGS_MODULE)
tuple_settings = (
"INSTALLED_APPS",
"TEMPLATE_DIRS",
"LOCALE_PATHS",
)
self._explicit_settings = set()
for setting in dir(mod): # 循环获取提供给用户的配置文件中所有的变量名
if setting.isupper():
setting_value = getattr(mod, setting) # 给对象设置属性
基于setting源码编程
# 启动文件
import sys
import os
sys.path.append(os.path.dirname(__file__))
if __name__ == '__main__':
os.environ.setdefault('user_setting', 'conf.settings')
from conf import settings
print(settings.ATTRIBUTE_NAME)
from lib.conf import global_settings
print(global_settings.ATTRIBUTE_NAME)
from lib.conf import setting
print(setting.ATTRIBUTE_NAME)
# 用户配置文件
ATTRIBUTE_NAME = '用户设置中的属性'
# 全局配置文件
ATTRIBUTE_NAME = '全局设置中的属性'
# init__.py
import importlib
import os
from lib.conf import global_settings
class Settings(object):
def __init__(self):
for setting_name in dir(global_settings):
if setting_name.isupper():
values = getattr(global_settings, setting_name)
setattr(self, setting_name, values)
user_module_path = os.environ.get('user_setting')
settings = importlib.import_module(user_module_path)
for name in dir(settings):
if name.isupper():
settings_values = getattr(settings, name)
setattr(self, name, settings_values)
setting = Settings()
权限管理简介
web领域的权限
使用账号访问某个网站资源,有些用户可以访问(VIP),有些用户不能访问(普通用户)。web领域的权限关键在url,当用户登录之后获取该用户的权限,然后用户每次发送网络请求先核对该请求地址是否在用户可以访问的url列表内,如果在url列表则允许访问,不在则拒绝访问。
权限的设计
用户表
id | name | password |
---|---|---|
1 | linda | qwe |
2 | simon | qaz |
3 | sam | wsx |
4 | tom | edc |
权限表
id | permissin |
---|---|
1 | 添加书籍 |
2 | 查看书籍 |
3 | 编辑书籍 |
4 | 删除书籍 |
用户与权限关系表
id | userId | permissionId |
---|---|---|
1 | 1 | 1 |
2 | 1 | 2 |
3 | 1 | 3 |
4 | 1 | 4 |
5 | 2 | 2 |
6 | 3 | 2 |
上述的权限设计是存在缺陷的,用户数据量比较大的时候与权限的绑定关系在第三张关系表中过于臃肿
基于角色的权限管理(RBAC)
提前在角色和权限关系表中绑定好关系,之后有新用户只需在用户和角色关系表中添加一两条数据
用户表
id | name | password |
---|---|---|
1 | linda | qwe |
2 | simon | qaz |
3 | sam | wsx |
4 | tom | edc |
角色表
id | role |
---|---|
1 | admin |
2 | user |
权限表
id | permissin | url |
---|---|---|
1 | 添加书籍 | /add/book/ |
2 | 查看书籍 | /check/book/ |
3 | 编辑书籍 | /modify/book/ |
4 | 删除书籍 | /delete/book/ |
用户角色关系表
id | userId | roleId |
---|---|---|
1 | 1 | 1 |
2 | 1 | 2 |
3 | 1 | 2 |
4 | 1 | 2 |
5 | 2 | 2 |
6 | 3 | 2 |
角色权限关系表
id | roleId | permissionId |
---|---|---|
1 | 1 | 1 |
2 | 1 | 2 |
3 | 1 | 3 |
4 | 1 | 4 |
5 | 2 | 2 |
权限管理案例
# app01\permissions\mypermission.py
from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse
import re
class MyPermission(MiddlewareMixin):
def process_request(self, request):
# 定义网站白名单
white_url_list = ['/home/', '/check_book/', '/login/', '/logout/', '/register/', '/admin/.*']
# 获取当前用户请求的url
target_url = request.path
# 先校验是否在白名单中,是则直接放行
for url in white_url_list:
re_path = '^%s$' % url
res = re.search(re_path, target_url)
if res:
return
# 获取当前用户的权限列表
permission_list = request.session.get('permission_list')
for permission in permission_list:
re_path = '^%s$' % permission
res = re.search(re_path, target_url)
if res:
return
return HttpResponse(f'<br><h2 style="text-align: center">没有权限</h2>'
'<br><a href="/home/"><h2 style="text-align: center"">返回主页</h2></a>'
# app01\models.py
from django.db import models
# Create your models here.
# 图书表
class Book(models.Model):
book_title = models.CharField(max_length=64, verbose_name='图书名')
book_price = models.DecimalField(max_digits=6, decimal_places=2, verbose_name='图书价格')
publish_time = models.DateField(auto_now=True, verbose_name='出版日期')
publish = models.ForeignKey(to='Press', null=True)
authors = models.ManyToManyField(to='Author')
stock_amount = models.IntegerField(default=5000)
sale_amount = models.IntegerField(default=2000)
def __str__(self):
return "%s-图书对象" % self.book_title
# 出版社表
class Press(models.Model):
press_name = models.CharField(max_length=64, verbose_name='出版社名称')
press_addr = models.CharField(max_length=64, verbose_name='出版社地址')
def __str__(self):
return "%s-出版社对象" % self.press_name
# 作者表
class Author(models.Model):
author_name = models.CharField(max_length=64, verbose_name='作者姓名')
author_age = models.IntegerField(verbose_name='作者年龄')
author_details = models.OneToOneField(to='AuthorDetail')
def __str__(self):
return "%s-作者对象" % self.author_name
# 作者详情表
class AuthorDetail(models.Model):
author_addr = models.CharField(max_length=64, verbose_name='作者地址')
author_phone = models.BigIntegerField(verbose_name='作者联系方式')
def __str__(self):
return "%s-作者详情对象" % self.author_addr
# 用户表
class User(models.Model):
uid = models.IntegerField(primary_key=True)
name = models.CharField(max_length=32)
password = models.CharField(max_length=32)
roles = models.ManyToManyField(to='Role')
def __str__(self):
return self.name
# 角色表
class Role(models.Model):
rid = models.IntegerField(primary_key=True)
role_name = models.CharField(max_length=32)
permission = models.ManyToManyField(to='Permission')
def __str__(self):
return self.role_name
# 权限表
class Permission(models.Model):
pid = models.IntegerField(primary_key=True)
permission_name = models.CharField(max_length=32)
url = models.CharField(max_length=64)
def __str__(self):
return self.permission_name
点击查看app01\views.py代码
from django.shortcuts import render, HttpResponse
from app01 import models
from django.contrib import auth
from django import views
# Create your views here.
def check_book(request):
book_objs = models.Book.objects.all()
return render(request, 'check_book.html', {'book_objs': book_objs})
def home(request):
return render(request, 'home.html')
def add_book(request):
if request.method == 'POST':
book_title = request.POST.get('book_title')
book_price = request.POST.get('book_price')
publish_time = request.POST.get('publish_time')
publish_id = request.POST.get('publish_id')
author_id = request.POST.get('author_id')
models.Book.objects.create(book_title=book_title, book_price=book_price, publish_time=publish_time,
publish_id=publish_id)
book_obj = models.Book.objects.filter(book_title=book_title).first()
book_obj.authors.add(author_id)
return HttpResponse('<br><h2 style="text-align: center">添加成功</h2>'
'<br><a href="/home/"><h2 style="text-align: center">返回主页</h2></a>')
return render(request, 'add_book.html')
def book_detail(request, book_detail_id):
book_obj = models.Book.objects.filter(id=book_detail_id).first()
publish_id = book_obj.publish_id
# author_id = book_obj.authors_id
press_obj = models.Press.objects.filter(id=publish_id).first()
# author_obj = models.Author.objects.filter(id=author_id).first()
return render(request, 'book_detail.html', locals())
def modify_book(request, modify_id):
book_obj = models.Book.objects.filter(id=modify_id).first()
if request.method == 'POST':
book_title = request.POST.get('book_title')
book_price = request.POST.get('book_price')
publish_time = request.POST.get('publish_time')
publish_id = request.POST.get('publish_id')
models.Book.objects.filter(id=modify_id).update(book_title=book_title, book_price=book_price,
publish_time=publish_time, publish_id=publish_id)
return HttpResponse(f'<br><h2 style="text-align: center">id为{modify_id}的图书修改成功</h2>'
'<br><a href="/home/"><h2 style="text-align: center">返回主页</h2></a>')
return render(request, 'modify_book.html', {'book_obj': book_obj})
def delete_book(request, delete_id):
models.Book.objects.filter(id=delete_id).delete()
return HttpResponse(f'<br><h2 style="text-align: center">id为{delete_id}的图书删除成功</h2>'
'<br><a href="/home/"><h2 style="text-align: center"">返回主页</h2></a>')
def logout(request):
auth.logout(request)
return HttpResponse(f'<br><h2 style="text-align: center">退出登陆</h2>'
'<br><a href="/home/"><h2 style="text-align: center"">返回主页</h2></a>')
def login(request):
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
user_obj = models.User.objects.filter(name=username, password=password).first()
if user_obj:
# 获取当前用户的权限
permission_list = models.User.objects.filter(name=username, password=password).values(
'roles__permission__url').distinct()
# 存储当前登录用户的权限用于后续比对
permission_list = [item.get("roles__permission__url") for item in permission_list]
request.session['permission_list'] = permission_list
# auth.login(request, user=user_obj)
return render(request, 'login.html')
admin配置类重要参数和admin源码
from django.contrib import admin
from app01 import models
# Register your models here.
# class PressInline(admin.StackedInline): # TabularInline
# extra = 0
# model = models.Press
class Bookconfig(admin.ModelAdmin):
list_display = [
'book_title',
'book_price',
'stock_amount',
'sale_amount',
] # 控制字段展示
# list_display_links = ['stock_amount'] # 控制修改字段
search_fields = ['book_title', 'book_price'] # 指定搜索字段
list_filter = ['publish', 'authors'] # 指定筛选字段(外键)
list_editable = ['stock_amount'] # 指定可以在列表时编辑的列
# list_select_related = ['publish']
# inlines = ['PressInline', ]
def patch_init(self, arg, queryset):
from django.db.models import F
queryset.update(stock_amount=F('stock_amount') + 100)
patch_init.short_description = '进货100本'
def sale_init(self, arg, queryset):
from django.db.models import F
queryset.update(sale_amount=F('sale_amount') - 100)
sale_init.short_description = '销售100本'
actions = [patch_init,
sale_init,
]
admin.site.register(models.Book, Bookconfig)
# admin.site.register(models.Press, PressInline)
第三方bug检测功能
安装
pip3 install django-debug-toolbar
配置
settings.py
将debug_toolbar在INSTALL_APPS里注册
INSTALLED_APPS = [
'debug_toolbar',
]
urls.py
from django.conf import settings
from django.conf.urls import include, url
if settings.DEBUG:
import debug_toolbar
urlpatterns = [
url(r'^__debug__/', include(debug_toolbar.urls)),
] + urlpatterns
settings.py
在中间件中注册DebugToolbarMiddleware
MIDDLEWARE = [
'debug_toolbar.middleware.DebugToolbarMiddleware',
]
本机调试的设置方法
需要将地址127.0.0.1加入INTERNAL_IPS
# settings.py
INTERNAL_IPS = [‘127.0.0.1’, ]
配置jQuery的URL
在settings.py中配置
django-debug-toolbar默认使用Google的地址
JQUERY_URL = '//ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js'
国内可以修改地址
DEBUG_TOOLBAR_CONFIG = {
"JQUERY_URL": '//cdn.bootcss.com/jquery/2.2.4/jquery.min.js',
}