Django之初步了解
目录:
django介绍
django流程
传统的MVC框架,把web应用分为模型M,控制器C和视图V三层,这三层之间通过插件似的松耦合连接在一起。
- 模型负责业务对象与数据库的对象,即ORM;
- 视图负责与用户前端交互;
- 控制器负责接收用户输入调用模型和视图完成用户请求。
而django也同理
- model为模型,负责业务对象与数据库的对象
- template为模板,负责如何把页面展示给用户
- view为视图,负责业务逻辑,并在适当的时候调用model和tempale
- url为路由,将不同的url请求发送给不同的views处理
一个请求的流程就是在页面访问,先到url路由到url中记录的匹配的view视图,视图可能会去module读或写数据,然后根据module返回的结果,将展示的数据夹带tempate模板返回给用户。
更多可以参考官方文档以及django book 2.0中文版
创建django项目
安装django
[C:\Python27\Scripts]$ pip.exe install django
Collecting django
Downloading Django-1.11.5-py2.py3-none-any.whl (6.9MB)
Collecting pytz (from django)
Downloading pytz-2017.2-py2.py3-none-any.whl (484kB)
Installing collected packages: pytz, django
Successfully installed django-1.11.5 pytz-2017.2
创建项目
[C:\Python27\Scripts]$ django-admin.exe startproject mysite
程序目录
- manager.py是调用功能
- setting.py是全局的配置文件
- urls.py是全局的路由入口
- wsgi.py提供wsgi接口
manager提供的功能有很多
- python manage.py runserver 0.0.0.0
- python manage.py startapp appname
- python manage.py syncdb
- python manage.py makemigrations
- python manage.py migrate
- python manage.py createsuperuser
创建app
python manage.py startapp app
- admin.py用于创建和管理
- app.py用于配置app
- models.py用于创建ORM对象
- tests.py用于测试
- views.py用于处理业务的请求,逻辑复杂的话可以创建views的文件夹
- 可以创建二级路由的urls.py文件
app的作用更多的是区分业务。
运行程序
C:\pycode\mysite>python manage.py runserver
Performing system checks...
System check identified no issues (0 silenced).
You have 13 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
Run 'python manage.py migrate' to apply them.
September 25, 2017 - 23:58:07
Django version 1.11.5, using settings 'mysite.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.
[25/Sep/2017 23:58:36] "GET / HTTP/1.1" 200 1716
也可以单独指定端口
python manage.py runserver 127.0.0.1:8009
url
url的本质是url模式和url调用的视图函数之间的映射表,django可以根据不同url调用不用的代码。
url的根目录是从创建项目时自带的urls.py文件开始,可以根据第一级请求转发到不同的app,由app中urls.py文件进行余下的路由。
from django.conf.urls import url
from django.contrib import admin
urlpatterns = [
url(r'^admin/', admin.site.urls),
]
默认自带的admin则为django提供的管理界面
使用方式
urlpatterns = [
url(正则表达式, views函数, 参数, 别名),
]
- 正则表达式,django会根据url进行正则匹配
- views函数为一个可调用对象
- 可选,需要传递给views函数的默认参数,为字典形式
- 可选,别名
示例
urlpatterns = [
url(r'index', views.index, {"name":"why"}, "INDEX"),
]
参考官方示例
示例url代码
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^articles/2003/$', views.special_case_2003),
url(r'^articles/([0-9]{4})/$', views.year_archive),
url(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive),
url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail),
]
构建示例路由views
创建views.py
目录结构
views代码
from django.shortcuts import HttpResponse
def special_case_2003(request):
return HttpResponse('2003')
def year_archive(request,year):
print year
return HttpResponse('2017')
def month_archive(request, year, mouth):
return HttpResponse('2017/09')
def article_detail(request, year, mouth, day):
return HttpResponse('2017/09/26')
可以看到有了url路由就不能正常访问了,就会出现这个大黄页
输入对应url
输入对应url
输出的根据分组的year为2017
2017
[26/Sep/2017 00:54:09] "GET /articles/2017/ HTTP/1.1" 200 4
在year_archive要传入两个参数,一个是request,另一个是url中根据分组匹配到的year,在打印中也可以看到
否则会报错
TypeError: year_archive() takes exactly 1 argument (2 given)
输入对应url
输入对应url
路由匹配顺序
对于2003,能匹配到第一个路由也能匹配到第二个路由,但是使用了special_case_2003,是因为在前的原因
可以调整一下两个路由在列表中的位置
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^articles/([0-9]{4})/$', views.year_archive),
url(r'^articles/2003/$', views.special_case_2003),
url(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive),
url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail),
]
也就解释了django路由匹配的时候是从上到下依次匹配的。
分组进行参数指定
url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),
在views接收参数的时候必须是year,而不能是其他的
二级路由
from django.conf.urls import url, include
from . import views
urlpatterns = [
url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),
url(r'^articles/2003/$', views.special_case_2003),
url(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive),
url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail),
url(r'^app',include('app.urls'))
]
注意要import include,另外url(r'^app',include('app.urls'))
的app后不能有$
在app中创建urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'articles/(?P<year>[0-9]{4})/$', views.year_archive),
]
注意url(r'articles/(?P<year>[0-9]{4})/$', views.year_archive),
的articles前不能有^
views中添加
from django.shortcuts import HttpResponse
def year_archive(request,year):
return HttpResponse('archive/archive/%s' % year)
参数作用
在url中添加参数
urlpatterns = [
url(r'articles/(?P<year>[0-9]{4})/$', views.year_archive,{ 'mouth': '09' }),
]
配置对应
from django.shortcuts import HttpResponse
def year_archive(request,year, mouth):
return HttpResponse('app/archive/%s/%s' % (year, mouth))
别名作用
最后一个别名用于在前端页面使用
修改setting配置文件
- MIDDLEWARE中的'django.middleware.csrf.CsrfViewMiddleware'注释掉,防止csrf影响。
- TEMPLATES设置'DIRS': [os.path.join(BASE_DIR, 'templates')],
创建templates目录
index.html文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="{% url 'home' %}" method="post">
<input type="text" name="name">
<input type="text" name="passwd">
<input type="submit" value="提交">
</form>
</body>
</html>
这里直接用url的别名{% url 'home' %},这样正则匹配怎么修改,都会锁定到这个views
url配置
urlpatterns = [
url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),
url(r'^articles/2003/$', views.special_case_2003),
url(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive),
url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail),
url(r'^app',include('app.urls')),
url(r'^index/$', views.index),
]
views代码
def index(request):
if request.method == "GET":
return render(request, "index.html")
elif request.method == "POST":
if request.name == "why" and request.passwd == "123456":
return HttpResponse('login')
else:
return HttpResponse('password error')
views
http请求中的两个核心就是请求request和响应response
request
对于request,django会自动创建对象,有以下方法
- path请求的全路径,不包含域名,也不包含参数,如果是get_full_path()可以获取到全路径加参数
- method使用的HTTP方法的字符串,并且全为大写,例如"GET"和"POST",进行判断例如
if request.method=="GET"
- GET包含GET参数的字典
- POST包含POST参数的字典
- COOKIES包含cookies参数的字典
- FILES包含上传文件的字典,每一个Key都是
<input type="file" name="" />
标签中name属性的值,FILES中的每一个value同时也是一个标准的python字典对象,字典中有三个Keys,filename上传文件名,用字符串表示,content_type上传文件的Content Type和content上传文件的原始内容 - user是指django的用户,是一个django.contrib.auth.models.User对象,代表当前登陆的用户,如果访问用户当前没有登陆,user将被初始化为django.contrib.auth.models.AnonymousUser的实例,可以通过user的
is_authenticated()
方法来辨别用户是否登陆,示例if req.user.is_authenticated()
,只有激活Django中的AuthenticationMiddleware时该属性才可用 - session包含当前会话的字典对象,唯一可读写的属性,代表当前会话的字典对象;自己有激活Django中的session支持时该属性才可用。
response
对于response需要自定创建,用于views的返回值
django.http.HttpResponse
- HttpResponse("str")直接返回内容,等价于tornado的self.write,ajax请求就可以通过HttpResponse来进行返回;
- render(request,"index.html")等价于tornado的self.render,需要传入两个参数;
- render_to_response("test.html")直接返回页面,和render的区别是在csrf的时候,render有能力返回csrf的随机字符串,而render_to_response没有能力;
- redirect('/index/')跳转到某个路由,等价于tornado的self.redirect。
如果传值的时候传一个locals(),则代表所有局部变量。
setting
数据库
默认使用SQLite3,还支持MySQL,Oracle和PostgreSQL
默认配置
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
如果想使用MySQL
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME':'dbname',
'USER': 'root',
'PASSWORD': 'xxx',
'HOST': '',
'PORT': '',
}
}
对于django默认是使用MySQLdb模块,不过python3中没有MySQLdb模块,需要使用pymysql代替。
需要在project同名的app的__init__.py
文件中添加
import pymysql
pymysql.install_as_MySQLdb()
对于python2,直接使用MySQLdb需要做上述修改。
详细的可以参考install_as_MySQLdb
方法的源码
同步数据库
- python manage.py makemigrations
- python manage.py migrate
同步的数据库需要在setting的INSTALLED_APPS中注册才能使用,否则是不会同步module中的表的。
模版
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',
],
},
},
]
静态文件
静态文件的前缀
STATIC_URL = '/static/'
静态文件的目录
STATICFILES_DIRS = (
os.path.join(BASE_DIR, 'static'),
)
在html中调用的时候就可以使用前缀加目录里的文件,示例href="/static/why.css"
测试可以在在static目录下创建why.css,然后引入的文件中
body{
background-color: antiquewhite;
}