一.Django的流程和命令行工具
1.Djongo项目的结构:
2.Django实现流程:
url.py:jianshu.com/p/2fbafbddf4d2
- Django每次修改,自动重启
#安装:
pip3 install django
#添加环境变量
#在Pycharm的Terminal中输入命令
#1.创建项目(Project):
#如微信就是1个项目
django -admin startproject project_name_
#示例:
django -admin startproject mysite
#将创建1个mysite文件夹,内部包括:
mysite
#其中包括:
settings.py#配置信息
#内容:
INSTALLED_APPS:应用目录
MIDDLEWARE:中间件相关配置
url.py#路由配置文件(URL分发器)
urlpatterns=[
url(r'^<url>',<func>),
]
#本质是URL和被该URL调用的视图函数的映射表
#默认有1个url(r'^admin',admin.site.urls),用于admin.py
wsgi.py#协议
__init__.py
manage.py(启动文件)
#2.创建应用(App):
#如微信中的朋友圈就是1个应用
python mannage.py startapp app_name_
#示例:
python magage.py startapp app01
#mysite中将创建文件夹app01,其中包括
__init__.py
admin.py#Django提供的后台管理系统,管理数据库
apps.py
models.py#存放数据库相关内容,如创建数据库
tests.py#用于测试
views.py#用于存放视图函数
#3.settings配置
STATICFILES_DIRS=(
os.path.join(BASE_DIR,"statics"),
)
STATIC_URL='/static/'#相当于别名,导入时引用的是这个
#导入时只能用STATIC_URL,但STATIC_URL会按STATICFILES_DIRS找
#使用别名是为了避免在绝对路径被修改后,需要一个个修改引用
#4.根据需求设计代码
url.py
#在url.py中建立URL与视图函数的映射
#视图函数需要在url.py中导入
urlpatterns=[
url(r'^<url1>',<func1>),
url(r'^<url2>',<func2>)
]
views.py
#在views.py中写视图函数
#视图函数必须返回HttpResponse对象,以让服务器打包发回给前端
from django.shortcuts import HttpResponse
#HttpResponse是1个类
def show_time():
return HttpResponse("hello")
#实例化出1个HttpResponse对象
#5.使用模版创建Request对象
render(request,"html_name",sub_dict)
#render()只是进行了渲染,内部仍是返回HttpResponse对象
#参数说明:
request:请求对象
html_name:要返回的HTML文件(路径可通过settings.py中的配置找到)
sub_dict:1个字典,指定html_name中要替换的内容,形式如下:
{"in_html":sub...}
#in_html为HTML文件中的内容,sub为用以替换的内容
#HTML文件中要替换的内容应用{{...}}包起
#示例:
def show_time():
t=time.ctime()
return render(req,"index.html",{"time":t})
#time是前端的变量;t是后端的变量,通过render()被渲染到前端
#6.启动项目
python manage.py runserver IP:port
python manage.py runserver 127.0.0.1:8090
#7.连接数据库,操作数据
model.py
#8.引入静态文件:详情见 二.1.(3)
#在前端进行渲染,而render在后端进行渲染
#css/js/jquery渲染的是render渲染后的结果(仍是HTML文件)
#css/js文件放在project文件夹下的static文件夹中
#(大项目static文件夹在各个app文件夹下)
#导入方法1:
<script src="/static/jquery-3.1.1.js"></scirpt>
#导入方法2:
<head>
{% load staticfiles %}
</head>
<body>
<scirpt scr={% static 'jquery-3.1.1.js' %}>
</body>
#在后端渲染,前端拿到的和上一种相同
#并配置settings.py(见上)
- index.html:
<body>
<h1>The time is {{time}}</h1>#{{time}}将被替换
<!--time是前端的变量;t是后端的变量,通过render()被渲染到前端-->
</body>
3.Django的命令行工具
django-admin.py是Django的一个用于管理任务的命令行工具
manage.py是对django-admin.py的简单包装
每个Django Project里都会有1个mannage.py
django-admin.py startproject <proj_name>:创建1个Django项目
#参数说明:
proj_name:项目名称
#示例:创建1个mysite项目
django-admin.py startproject mysite
#当前目录下会生成mysite的工程(目录结构见下图1):
manage.py:Django项目里面的工具,通过它可以调用django shell和数据库等
settings.py:包含了项目的默认设置,包括数据库信息/调试标志等
urls.py:负责把URL模式映射到应用程序
python manage.py startapp <app_name>
#参数说明:
app_name:应用名称
#实例:在mysite目录下创建blog应用
python manage.py startapp blog
#Project目录下会生成应用blog的目录(目录结构见下图2)
启动django项目:python manage.py runserver 8080
访问http://127.0.0.1:8080/时就可以看到:
生成同步数据库的脚本:python manage.py makemigrations
同步数据库:python manage.py migrate
#注意:在开发过程中,数据库同步误操作之后,难免会遇到后面不能同步成功的情况
#解决这个问题的1个方法是把migrations目录下的脚本(除__init__.py外)全部删掉
#再把数据库删掉之后创建一个新的数据库,数据库同步操作再重新做一遍
访问http://127.0.0.1:8080/admin/时,会出现:
所以要创建超级管理员:python manage.py createsuperuser
设置好用户名和密码后即可登录
清空数据库:python manage.py flush
查询某个命令的详细信息:django-admin.py help startapp
#admin是Django自带的后台数据库管理系统
启动交互界面:python manage.py shell
#和直接运行python进入shell的区别是:可以在这个shell里面调用当前项目的models.py中的API
#对于操作数据,还有一些小测试非常方便
终端上输入python manage.py可以看到详细的列表
#在忘记子名称的时候特别有用
二.Django的配置文件(settings.py)
1.静态文件设置:
(1)概述:
#静态文件交由Web服务器处理,Django本身不处理静态文件
#简单的处理逻辑如下(以Nginx为例):
#URI请求:按照Web服务器里面的配置规则先处理
#主要求配置在nginx.conf里的location
#如果是静态文件,则由Nginx直接处理,如发送给前端
#否则交由Django处理,Django根据urls.py里面的规则进行匹配
#以上是部署到Web服务器后的处理方式
#为了便于开发,Django提供了在开发环境的对静态文件的处理机制:
#1.在INSTALLED_APPS里面加入:
'django.contrib.staticfiles'
#2.在urls.py里面加入:
if settings.DEBUG:
urlpatterns+=patterns('',
url(r'^media/(?P<path>.*)$',
'django.views.static.serve',
{'document_root': settings.MEDIA_ROOT}
),
url(r'^static/(?P<path>.*)$',
'django.views.static.serve',
{'document_root':settings.STATIC_ROOT}
),
)
#3.这样就可以在开发阶段直接使用静态文件了
(2)MEDIA_ROOT和MEDIA_URL:
#而静态文件的处理又包括STATIC和MEDIA两类,这往往容易混淆
#在Django里面是这样定义的:
MEDIA:指用户上传的文件,比如在Model里面的FileFIeld,ImageField上传的文件
#如果定义:
MEDIA_ROOT=C:\temp\media
#那么:
File=models.FileField(upload_to="abc/")#
#上传的文件就会被保存到c:\temp\media\abc
#eg:
class blog(models.Model):
Title=models.charField(max_length=64)
Photo=models.ImageField(upload_to="photo")
#上传的图片就上传到c:\temp\media\photo
#而在模板中要显示该文件,则在这样写:
#在settings里面设置的MEDIA_ROOT必须是本地路径的绝对路径
#一般是这样写:
BASE_DIR=os.path.abspath(os.path.dirname(__file__))
MEDIA_ROOT=os.path.join(BASE_DIR,'media/').replace('\\','/')
#MEDIA_URL是指从浏览器访问时的地址前缀:
MEDIA_ROOT=c:\temp\media\photo
MEDIA_URL="/data/"
#在开发阶段,media由django处理:
#访问http://localhost/data/abc/a.png就是访问c:\temp\media\photo\abc\a.png
#在模板里面这样写<img src="{{MEDIA_URL}}abc/a.png">
#在部署阶段最大的不同在于你必须让web服务器来处理media文件
#因此你必须在web服务器中配置,以便能让web服务器能访问media文件
#以Nginx为例,可以在nginx.conf里面这样:
location ~/media/{
root/temp/
break;
}
(3)STATIC_ROOT和STATIC_URL:
<!--STATIC主要指的是如css,js,images这样文件
在settings里面可以配置STATIC_ROOT和STATIC_URL
配置方式与MEDIA_ROOT是一样的,但是要注意:
STATIC文件一般保存在以下位置:
1.STATIC_ROOT:
在settings里面设置,在project文件夹中
一般用来放公共的js,css,images等
2.app的static文件夹:
在每个app所在文夹均可以建立1个static文件夹
然后运行collectstatic时,Django会遍历INSTALL_APPS里面所有app的static文件夹
将里面所有的文件复制到STATIC_ROOT
因此,如果要建立可复用的app,要将该app所需的静态文件放在static文件夹中
也就是说1个项目引用了很多app,那么该项目需要的静态文件分散在各app的static文件
比较典型的是admin应用:发布时需将这些分散的static文件收集到1个地方(STATIC_ROOT)
3.STATIC文件还可以配置STATICFILES_DIRS:指定额外的静态文件存储位置
#STATIC_URL的含义与MEDIA_URL类似-->
<!--1.为了后端的更改不影响前端的引入,避免造成前端大量修改-->
STATIC_URL = '/static/'#引用名
STATICFILES_DIRS=(
os.path.join(BASE_DIR,"statics")<!--实际文件夹的名字-->
)
<!--django对文件进行映射/引用时,只能用引用名,不能用实际名-->
<script src="/statics/jquery-3.1.1.js"></script>
<!--error--不能直接用,必须用STATIC_URL = '/static/'-->
<script src="/static/jquery-3.1.1.js"></script>
<!--2.statics文件夹写在不同的app下时静态文件的调用-->
STATIC_URL = '/static/'
STATICFILES_DIRS=(
('hello',os.path.join(BASE_DIR,"app01","statics")),
<!--或os.path.join(BASE_DIR,"app01/statics")-->
)
<script src="/static/hello/jquery-1.8.2.min.js"></script>
<!--3.引入方法2-->
STATIC_URL='/static/'
STATICFILES_DIRS=(
os.path.join(BASE_DIR,"statics"),
)
<head>
{% load staticfiles %}
</head>
<script src={% static "jquery-1.8.2.min.js" %}></script>
2.其他重要参数的设置:
APPEND_SLASH
Default:True
#When set to True,if the request URL
#does not match any of the patterns in the URLconf
#and it doesn’t end in a slash,
#an HTTP redirect is issued to the same URL
#with a slash appended.
#Note that the redirect may cause any data
#submitted in a POST request to be lost
3.在PyCharm中配置IP与Port:
三.Django URL(路由系统)
1.URL配置(URLconf)就像Django所支撑的网站的目录,本质是URL模式以及要为该URL模式调用的视图函数之间的映射表,用于告诉Django,对某个URL调用哪段代码
#url.py中:
urlpatterns=[
url(regex,view,**kwargs,name='an_name'),
]
#参数说明:
regex:正则表达式,用于匹配URL
格式:r'...'
#如果要拿到URL的某部分,使用分组符'()'将这部分括起,并在view中加1个参数
view:views视图函数
#多个URL可以对应1个视图函数
kwargs:传递给视图函数的参数字典
an_name:别名(关键字参数)
2.无命名的分组:后端可以随意命名
#url.py中:
urlpatterns=[
url(r'^articles/2003/$',views.special),
#url(r'^articles/[0-9]{4}/$',views.year1),
url(r'^articles/(\d{4})/$',views.year),#将4个数字分为1组,传给year()
#无命名的分组(no-named group)
url(r'^articles/(\d{4})/(\d{2})/$',views.month),
#$表示必须以其结尾,不加/2004/02/会匹配第2条
url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$',views.article_detail),
]
#在views.py中:
def special(req):
return HttpResponse('2003')
def year(req,y):#y接收的就是\d{4}部分
return HttpResponse('year:%s'%y)
def month(req,y,m):
return HttpResponse('year:%s month:%s'%(y,m))
def article_detail(req,y,m,num):
return HttpResponse('detail')
- Note:
1There’s no need to add a leading slash, because every URL has that.
For example,it’s ^articles,not ^/articles.
2.A request to /articles/2005/03/ would match the third entry in the list.
Django would call the function 'views.month_archive(request,'2005','03')'.
3./articles/2005/3/ would not match any URL patterns
4./articles/2003/ would match the first pattern in the list, not the second one
5./articles/2003/03/03/ would match the final pattern.
Django would call the function 'views.article_detail(request,'2003','03','03')'.
3.有命名的分组:后端命名必须与前端一致
(?P<xxx>regex):表示分组并将该组命名为xxx
#url.py中:
urlpatterns = [
url(r'^articles/2003/$',views.special_case_2003),
url(r'^articles/(?P<year>[0-9]{4})/$',views.year_archive),
url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$',views.month_archive),
]
#views.py中:
def year_archive(req,year):
return HttpRequest('year_archive')
def month_archive(req,year,month):
return HttpRequest('month_archive')
- Note:
获得的参数是'关键字参数',而非无命名分组中的'位置参数'
故参数'名字不能与前端不同',但顺序可变
4.向视图函数传递参数:
URLconfs have a hook that lets you pass extra arguments
to your view functions,as a Python dictionary.
The django.conf.urls.url() function can take
an optional third argument which
should be a dictionary of extra keyword arguments
to pass to the view function.
#url.py中:
urlpatterns=[
url(r'^blog/(?P<year>[0-9]{4})/$',views.year_archive,{'foo':'bar'}),
]
- Note:
In this example,for a request to /blog/2005/,
Django will call views.year_archive(request,year='2005',foo='bar')
This technique is used in the syndication framework
to pass metadata and options to views
Dealing with conflicts
It’s possible to have a URL pattern
which captures named keyword arguments,
and also passes arguments with the same names
in its dictionary of extra arguments.
When this happens,the arguments in the dictionary
will be used instead of the arguments captured in the URL
5.别名:同样用于防止需要前端随后端一一修改引用
#url.py中:
urlpatterns=[
url(r'^index',views.index,name='bieming'),
]
#views.py中:
def index(req):
if req.method=='POST':
username=req.POST.get('username')#获得username
password=req.POST.get('password')#获得password
if username=='alex' and password=='123':
return HttpResponse("登陆成功")
return render(req,'index.html')
<!--templates中的index.html-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--<form action="/index/" method="post">-->
<!--IP+port会被Django自动补上,默认按同源(即当前页面的IP+port)-->
<form action="{% url 'bieming' %}" method="post">
<!--提交到该处,此处使用了别名-->
<!--格式:{%url '别名' %}-->
用户名:<input type="text" name="username">
密码:<input type="password" name="password">
<input type="submit" value="submit">
</form>
</body>
</html>
6.路由分发(URLconfs):每个app有自己的路由;用于解耦
#At any point,your urlpatterns can “include” other URLconf modules.
#This essentially “roots” a set of URLs below other ones.
#For example,here’s an excerpt of the URLconf for the Django website itself.
#It includes a number of other URLconfs:
#django_lesson下的url.py中:
from django.conf.urls import include,url
urlpatterns=[
url(r'^admin/',admin.site.urls),
url(r'^blog/',include('blog.urls')),
#有关blog的请求都分发到blog.urls去
]
#blog下的urls.py中:
#实际处理与blog有关的请求
urlpatterns=[
url(r'^article/(\d{4})$',views.year),
...
]