Python

Django之路(一) - 基本配置,路由系统

2018-02-28  本文已影响239人  Zoulf

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)

  1. 数据库
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() 
  1. 模版(存放html模板)
TEMPLATE_DIRS = (
        os.path.join(BASE_DIR,'templates'),
    )
  1. 静态文件(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路由流程

  1. Django查找全局urlpatterns变量(urls.py)
  2. 按照先后顺序,对URL逐一匹配(匹配 urlpatterns 的每个元素)
  3. 找到第一个匹配时停止查找,根据匹配结果执行对应的处理函数
  4. 如果没有找到匹配或出现异常,Django进行错误处理

tips:Django的路由不考虑HTTP请求方式,仅根据URL进行路由,即,只要URL相同,无论POST、GET等哪种请求方式都指向同一个操作函数。

路由格式

Urlpatterns 中的 path() 处理字符串路由,re_path() 处理正则表达式路由。正则表达式可以看做字符串的模式。

urlpatterns=[
    # [] 表示可省略项
    path(route,views.函数名,[向处理函数提供的额外参数(以字典形式表示)], 
         [该URL模式的别名)]),   
    re_path(正则表达式,view.对应的处理函数),
]

 
Django支持三种方式表达route:

  1. 精确字符串格式
    path('index/', views.index),
  2. 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循环取出值。
  1. 正则表达式格式,用的是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):
对你的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')

命名空间,主要是用来区分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请求做一条路由映射,从而使路由系统变得简洁。

上一篇下一篇

猜你喜欢

热点阅读