Django之路(一) - 基本配置,路由系统
Python 的 WEB 框架有 Django、Tornado、Flask 等多种,Django 相较与其他 WEB 框架其优势为:大而全,框架本身集成了 ORM、模型绑定、模板引擎、缓存、Session等诸多功能。
基本配置
创建django程序
终端命令:django-admin startproject sitename
IDE(如Pycharm)创建Django程序时,本质上都是自动执行上述命令。
其他常用命令:
# 运行程序,[]为可省略部分
python manage.py runserver [ip:port](默认:127.0.0.1:8000)
# 创建 app,app被定义为网页中的一个功能模块,如图1-1
python manage.py startapp appname
# 创建数据库
python manage.py makemigrations
python manage.py migrate
# 在Django 1.9版本以后被migrate取代
python manage.py syncdb
# 将数据库中的数据导出
python manage.py dumpdata [appname] > xxx.json
# 将数据导入进数据库,无需指定 appname
python manage.py loaddata blog_dump.json
# 创建超级用户
python manage.py createsuperuser
关于dumpdata的优缺点:
优点:可以兼容各种支持的数据库,也就是说,以前用的是 SQLite3,可以导出后,用这种方法导入到 MySQL, PostgreSQL等数据库,反过来也可以。
缺点:数据量大的时候,速度相对较慢,表的关系比较复杂的时候可能导入不成功。
程序目录
目录配置文件(settings.py)
- 数据库
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME':'dbname',
'USER': 'root',
'PASSWORD': 'xxx',
'HOST': '',
'PORT': '',
}
}
# 由于Django内部连接MySQL时使用的是MySQLdb模块,而python3中还无此模块,所以需要使用pymysql来代替
# 如下设置放置在与project同名的配置的 __init__.py文件中
import pymysql
pymysql.install_as_MySQLdb()
- 模版(存放html模板)
TEMPLATE_DIRS = (
os.path.join(BASE_DIR,'templates'),
)
- 静态文件(css样式,jquery等...)
STATICFILES_DIRS = (
os.path.join(BASE_DIR,'static'),
)
路由系统
路由是关联 url 和处理该 url 函数的过程。Django 的路由都写在 urls.py 文件中的urlpatterns 列表中,由 path() 或 re_path() 作为元素组成。Django2.0版本中path(route, views.对应处理函数)
等价于低版本的url(r'^route/$’, views.对应处理函数)
。
Django的URL路由流程
- Django查找全局urlpatterns变量(urls.py)
- 按照先后顺序,对URL逐一匹配(匹配 urlpatterns 的每个元素)
- 找到第一个匹配时停止查找,根据匹配结果执行对应的处理函数
- 如果没有找到匹配或出现异常,Django进行错误处理
tips:Django的路由不考虑HTTP请求方式,仅根据URL进行路由,即,只要URL相同,无论POST、GET等哪种请求方式都指向同一个操作函数。
路由格式
Urlpatterns 中的 path() 处理字符串路由,re_path() 处理正则表达式路由。正则表达式可以看做字符串的模式。
urlpatterns=[
# [] 表示可省略项
path(route,views.函数名,[向处理函数提供的额外参数(以字典形式表示)],
[该URL模式的别名)]),
re_path(正则表达式,view.对应的处理函数),
]
Django支持三种方式表达route:
- 精确字符串格式
path('index/', views.index),
- Django的转换格式
path('index/<类型:变量名>/', views.index),
e.g. path(index/<int:year>/), views.index),
使用该种格式,视图函数定义时要创建对应的参数来接收获取的值。
转换格式类型:
str,匹配除分隔符(/)外的非空字符,默认类型,即<year>等价于<str:year>;
int,匹配0和正整数;
slug,匹配字母、数字、横杠、下划线组成的字符串,str的子集;
uuid,匹配格式化的UUID,如075194d3-6885-417e-a8a8-6c931e272f00;
path,匹配任何非空字符串,包括路径分隔符,是全集。
如果传入的视图函数参数有多个,可以用到*args或者**kwargs,前者用索引,后者可以用for循环取出值。
- 正则表达式格式,用的是re_path
# 不提取参数,表示四位数字,每一个数字都是0到9的任意数字;
re_path('index/[0-9]{4}/', views.index)
# 提取参数,将正则表达式提取的四位数字,每一个数字都是0到9的任意数字命名为year;
re_path('index/(?p<year>[0-9]{4})/', views.index)
include 的使用
当视图函数路径较多时,可以使用Include()进行去重:
urlpatterns=[
path('index/history/', views.history),
path('index/edit1/', views.edit),
path('index/edit2/', views.edit),
...
]
# include去重后
Urlpatterns = [
path('index/', include([
path('history/', views.history),
path('edit/', views.edit),
])
),
]
include 还可以用来实现 url 映射分发。例如:网站有论坛模块,则在论坛模块(论坛的app)下建个 urls.py 文件,将与论坛相关的页面的 url 全部写在这个文件里。具体操作如下,
全局的urls.py文件:
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('bbs/',include('bbs.urls'))
]
论坛模块( bbs/ )下的 urls.py 文件:
from django.urls import path
urlpatterns = [
path('news/', views.news),
]
然后在论坛模块下的 views.py 中写对应的 news 函数即可。最后生成的访问地址:.../bbs/news/
path() 的其他参数
- name 参数
为路由映射设置名称(name):
对你的URL进行命名,可以让你能够在Django的任意处,尤其是模板内显式地引用它。相当于给URL取了个全局变量名,你只需要修改这个全局变量的值,在整个Django中引用它的地方也将同样获得改变。
path('home', views.home, name='h1'),
path('index/(\d*)', views.index, name='h2'),
设置名称之后,可以在不同的地方调用,如:
模板中使用生成URL {% url 'h2' 2012 %}
函数中使用生成URL reverse('h2', args=(2012,))
Model中使用获取URL 自定义get_absolute_url() 方法
from django.urls import reverse
class NewType(models.Model):
caption = models.CharField(max_length=16)
def get_absolute_url(self):
"""
为每个对象生成一个URL
应用:在对象列表中生成查看详细的URL,使用此方法即可!!!
"""
# return '/%s/%s' % (self._meta.db_table, self.id)
# 或
return reverse('NewType.Detail', kwargs={'nid': self.id})
- 默认值参数
即匹配的的时候可以传入一个默认值。
path('index/', views.index, {'name': 'root'}),
...
def index(request,name):
print(name)
return HttpResponse('OK')
- namespace参数
命名空间,主要是用来区分Url的。
from django.conf.urls import url,include
urlpatterns = [
url(r'^a/', include('app01.urls', namespace='author-polls')),
url(r'^b/', include('app01.urls', namespace='publisher-polls')),
]
b. app01.urls.py
from django.conf.urls import url
from app01 import views
app_name = 'app01'
urlpatterns = [
url(r'^(?P<pk>\d+)/$', views.detail, name='detail')
]
c. app01.views.py
def detail(request, pk):
print(request.resolver_match)
return HttpResponse(pk)
以上定义带命名空间的url之后,使用name生成URL时候,应该如下:
v = reverse('app01:detail', kwargs={'pk':11})
{% url 'app01:detail' pk=12 pp=99 %}
django中的路由系统和其他语言的框架有所不同,在django中每一个请求的url都要有一条路由映射,这样才能将请求交给对一个的view中的函数去处理。其他大部分的Web框架则是对一类的url请求做一条路由映射,从而使路由系统变得简洁。