Django 高级特性总结 - archering/basic GitHub Wiki
Django 高级特性总结
通过命令创建一个django项目
django-admin startproject 项目名
项目创建后,结构如下:
project_name
├──project_name
│ ├──__init__.py
│ ├──settings.py
│ ├──urls.py
│ └──wsgi.py
└──manage.py
__init__.py 这个文件的存在决定了这是一个package
settings.py django项目的配置文件,内部变量均大写,他配置了启动的端口,静态目录,模板目录....
CACHE_BACKEND默认值: 'simple://'
DATABASE_HOST默认值: ''
DATABASE_NAME默认值: '' (空的字符串)
DATABASE_PASSWORD默认值: '' (空的字符串)
DATABASE_PORT默认值: '' (空的字符串)
DEBUG默认值: False
DEFAULT_CHARSET默认值: 'utf-8'
DEFAULT_CONTENT_TYPE默认值: 'text/html'
ENABLE_PSYCO默认值: False #如果允许 Psyco, 将使用Pscyo优化 Python 代码. 需要 Psyco 模块.
IGNORABLE_404_ENDS默认值: ('mail.pl', 'mailform.pl', 'favicon.ico', '.php')
LANGUAGE_CODE默认值: 'en-us' #一个 tuple('da', _('Danish')),('de', _('German'))
PREPEND_WWW默认值: False # 是否为没有 "www." 前缀
SESSION_COOKIE_NAME默认值: 'sessionid'
SESSION_COOKIE_AGE默认值: 1209600 (2周, 以秒计) # session cookies 的生命周期, 以秒计
SESSION_COOKIE_DOMAIN默认值: None
SITE_ID默认值: Not defined
urls.py 路由的映射关系,最重要的urlpatterns 这个list, 定义映射关系在这里
wsgi.py Web Server Gateway Interface
#回到 manage.py 所在的目录
python manage.py runserver # 启动server
修改项目中的配置文件 settings.py
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.0/howto/static-files/
STATIC_URL = '/statics/' # 这个目录是存放在项目根目录下的
STATICFILES_DIRS = [ # list 或 tuple, 静态资源的绝对路径根目录
os.path.join(os.path.dirname(__file__), '../statics/').replace('\\', '/')
]
配置完上面两个信息,重启服务,就可以通过url访问资源了
假设我们在项目根目录简历了一个叫 statics的文件夹,里面建子目录js,css, css目录里面放着bootstrap
statics ├──css │ └──bootstrap3.3.6 │ ├──css │ ├──js └──js
http://localhost:8001/statics/css/bootstrap3.3.6/css/bootstrap.css # 这样就可以在浏览器输出css内容了
模板中使用静态资源有两种方式
一种是直观的,url地址方式,向上面这个css访问的地址是
http://localhost:8001/statics/css/bootstrap3.3.6/css/bootstrap.css
模板中直接引用或者采用相对地址的方式,单数注意,需要进入父级目录(否则前面会跟着虚拟机名字) ..
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<link rel="stylesheet" href="../statics/css/bootstrap3.3.6/css/bootstrap.css">
</head>
另外一种通过 {% load staticfiles %} href 哪块有个变量 static 不是 statics
{% load staticfiles %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>template render</title>
<link rel="stylesheet" href="{% static 'css/bootstrap3.3.6/css/bootstrap.min.css' %}">
</head>
block 块中需要再次 load staticfiles 要不然无法使用static 变量
下面例子, base.html 中已经 load static了, block main 中 需要再次 load staticfiles, 否则无法使用 static
{% extends 'base.html' %}
{% block main %}
{% load staticfiles %}
<div class="hello max">
hello world
</div>
<button class="btn btn-info max">click me</button>
<script src="{% static 'angular/angular.min.js' %}"></script>
<script>
console.log(angular);
</script>
{% endblock %}
STATIC_ROOT 是在部署静态文件时(pyhton manage.py collectstatic)所有的静态文静聚合的目录,STATIC_ROOT要写成绝对地址
STATIC_ROOT 是在部署的时候才发挥作用, 而实际情况下,静态文件的一般安放位置有两种:
1.一种就是在每个app里面新建一个static文件夹,将静态文件放到里面,在加载静态文件时,比如要在模板中用到静态文件,django会自动在每个app里面搜索static文件夹(所以,不要把文件夹的名字写错哦, 否则django就找不到你的文件夹了)
2.另一种,就是在所有的app文件外面,建立一个公共的文件夹, 因为有些静态文件不是某个app独有的,那么就可以把它放到一个公共文件夹里面,方便管理(注意,建立一个公共的静态文件的文件夹只是一种易于管理的做法,但是不是必须的,app是可以跨app应用静态文件的,因为最后所有的静态文件都会在STATIC_ROOT里面存在) 那现在的问题是**如何让django知道你把一些静态文件放到app以外的公共文件夹中呢,**那就需要配置STATICFILES_DIRS了
STATICFILES_DIRS告诉django,首先到STATICFILES_DIRS里面寻找静态文件,其次再到各个app的static文件夹里面找(注意, django查找静态文件是惰性查找,查找到第一个,就停止查找了)
STATICFILES_DIRS = [
os.path.join(os.path.dirname(__file__), '../statics/').replace('\\', '/'),
os.path.join(os.path.dirname(__file__), '../node_modules/').replace('\\', '/')
]
这个变量设置之后,静态文件的查找就会先在这个列表描述的地址里面进行,然后是个app自己的static文件夹
此时并不能通过 浏览器地址栏直接输入 url的方式 找到这些静态资源
django利用STATIC_URL来让浏览器可以直接访问静态文件
你可以在浏览器中输入 http:// ...../static/jquery/dist/jquery.js
当django服务发现static这个路由时,就会去 STATICFILES_DIRS 列表对应的路径下去搜 jquery/dist/jquery.js
搜到之后就显示出来。
STATIC_URL = '/static/' 是一个映射route, 具体是对应(上面列表里的)node_modules 还是 statics目录完全取决于在哪里找到这个资源。
<script src="{% static 'jquery/dist/jquery.js' %}"></script>
###django 项目中给静态资源加header 头部信息
from django.views.generic.base import View
from django.http import HttpResponse
from django.shortcuts import render
from . import models
from .help import getURL
class Hello(View):
def get(self,request):
lis = models.CharlesList.objects.all()
print(lis)
response = render(request,getURL("me_first/templates/db.html"),{"list":lis})
response["Cache-Control"] = "public;max-age=" + str(60*60*1000)
response["X-XSS-Protection"] = "1; mode=block"
response["X-Frame-Options"] = "SAMEORIGIN"
response["X-Content-Type-Options"] = "nosniff"
return response
###summary
STATIC_URL = '/static/' 是一个映射route
STATICFILES_DIRS 静态资源搜索列表
STATIC_ROOT 静态资源聚合目录
URLs.py
当从浏览器发来的请求到达Django之后,Django首先去urls.py去找urlpatters列表,这个列表对应着相应的路由和具体解析和处理这个路由的类
views.py
Django 的views 就是其他MVC框架中的controllers
view 默认接收一个request 对象,返回一个response对象
view 可以是一个function 也可以是一个Class-based view
Class-based view 一般继承自django.views.generic.base.View (已经实现了许多方法,不必从头写起)
view.py 代码具体来说只用来处理request请求,执行各种业务逻辑,展现层面的东西最好交给template
os.path.dirname(__file__) #指的是 当前文件所在目录,不包括文件名
os.path.abspath(__file__) #指的是 当前文件的绝对路径,包括文件名
os.path.dirname(os.path.dirname(__file__)) #指的是 当前文件所在目录的所在目录,即上一层文件夹。
settings.py 里面要有TEMPLATES.DIRS ,要不然 render_to_response("temp0.html",{date:date.today()}) 不知道去哪里找这个temp0.html
实现从template的直接渲染展现界面的方式有两种,一种 django.shortcuts.render_to_response
另一种是使用django.views.generic.base.TemplateView 继承并override 里面的方法
views 是个笼统的概念,任何一个*.py都有可能是一个view。
view 可以基于function
from django.shortcuts import render
from django.http.response import HttpResponse
def index(request):
return HttpResponse("hello this is from function based view")
urls.py 引入时可以
from . import funView
path("func/",funView.index),
也可以基于class
from django.views.generic.base import View
from django.http.response import HttpResponse
from django.shortcuts import render_to_response
from datetime import date
class Temp(View):
def get(self,request):
return render_to_response("temp0.html",{date:date.today()})
urls.py引入可以这样
from .temp import Temp
path("temp/",Temp.as_view()),
view 里面的template 混合写python 代码应该这样写: 要有一个开始 和 结束的block 。 比如 if --- endif
<table border="1">
{% for item in tableList %}
<tr>
<td>{{item.a}}</td>
<td>{{item.b}}</td>
<td>{{item.c}}</td>
<td>{{item.d}}</td>
<td>{{item.e}}</td>
</tr>
{% endfor %}
</table>
{% if hello %}
<h1>{{hello}}</h1>
{% endif %}
Django其实自带了Hash和Cache静态文件的功能,在默认情况下没有启动而已
启用静态资源缓存,修改settings.py
STATICFILES_STORAGE = 'django.contrib.staticfiles.storage.CachedStaticFilesStorage'
当进行部署时,Debug=True,执行python manage.py collectstatic 就会自动在生成hash命名的静态文件在STATIC_ROOT/CACHE/下面
压缩静态文件
- 安装django_compressor
pip install django_compressor
2.设置(setting.py)
INSTALLED_APPS = (
# other apps
"compressor",
)
# 增加Finders
STATICFILES_FINDERS = (
'django.contrib.staticfiles.finders.FileSystemFinder',
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
# other finders..
'compressor.finders.CompressorFinder',
)
# 设置默认参数
COMPRESS_ENABLED = True
COMPRESS_OFFLINE = True
-
模板中使用
# 在模板中使用 {% load staticfiles compress %} {% compress css %} <link rel="stylesheet" href="/static/css/one.css" type="text/css" charset="utf-8"> <style type="text/css">p { border:5px solid green;}</style> <link rel="stylesheet" href="/static/css/two.css" type="text/css" charset="utf-8"> {% endcompress %} {% compress js %} <script src="/static/js/one.js" type="text/javascript" charset="utf-8"></script> <script type="text/javascript" charset="utf-8">obj.value = "value";</script> {% endcompress %}
部署
首先,确认在setting.py中加入了STATIC_ROOT并修改DEGUB=False 然后,执行以下命令: python manage.py collectstatic # 执行之后会生成STATIC_ROOT 指定的目录结构,并聚合所有静态文件 python manage.py compressor
models.py
以下事例中,me_first 是创建的项目名字或者应用名
sqllite 数据库可视化工具 SQLitestudio
通常都要继承自 django.db.models, 这个里面定义的class 数据结构类将用来生成数据库(默认sqllite)中相应的表。
django 创建数据库INSTALLED_APPS 里面去
me_first 这个要加到 settings.py 的
python manage.py makemigrations me_first
Migrations for 'me_first':
me_first\migrations\0001_initial.py
- Create model Charles
- Create model CharlesList
同时,项目的目录下会创建一个 migrations的文件夹,这个里面偶有一个 0001_initial.py 保存着表的映射关系
makemigration 命令会创建migrations目录,并记录所有关于models.py的改动,这个改动还没有作用到数据库
python manage.py migrate #将 models.py 的表关系实际生成数据库中的表
当0001_initial.py 文件创建后,可以使用以下命令,查看sql执行命令将怎样创建表结构
python manger.py sqlmigrate me_first 0001
class Charles(models.Model):
# fk = models.ForeignKey(CharlesList)
name = models.CharField(max_length=100)
gender = models.IntegerField()
due_date = models.DateTimeField()
passed = models.BooleanField(default=False) # 新增
fk = models.ForeignKey(CharlesList,on_delete=models.CASCADE) #新增
如果在执行命令中出现下面问题
(pyone) D:\py\me_first>python manage.py makemigrations me_first
You are trying to add a non-nullable field 'fk' to charles without a default; we can't do that (the database needs something
Please select a fix:
1) Provide a one-off default now (will be set on all existing rows with a null value for this column)
2) Quit, and let me add a default in models.py
Select an option: 2
解决办法:
-
先修改models.py ,添加一个 default=1
fk = models.ForeignKey(CharlesList,on_delete=models.CASCADE,default=1)
-
执行命令
python manage.py makemigrations me_first
-
删除default =1 保存
fk = models.ForeignKey(CharlesList,on_delete=models.CASCADE)
-
再执行 命令
python manage.py makemigrations me_first
python manage.py migration
python manage.py createsuperuser # 创建一个 admin 密码是admin123的 超级用户
运行程序,进入admin
用你创建的超级用户登录