Django的下载与基本命令
- 下载Django:pip3 install django==2.0.1
- 创建一个django project: django-admin startproject luffy
- 在mysite目录下创建应用:python manage.py startapp app01
- 启动django项目:python manage.py runserver 8080 我们访问:http://127.0.0.1:8080/时就可以看到:
- python manage.py makemigrations
- python manage.py migrate
- python manage.py createsuperuser
- 命令行查看django版本:python -m django --version
一、文件介绍
- manage.py ----- Django项目里面的工具,通过它可以调用django shell和数据库等。
- settings.py ---- 包含了项目的默认设置,包括数据库信息,调试标志以及其他一些工作的变量。
- urls.py ----- 负责把URL模式映射到应用程序。
静态文件
1 2 3 4 5 | #在settings.py中: STATIC_URL = '/static/' STATICFILES_DIRS = ( os.path.join(BASE_DIR, 'static' ), ) |
路由
URL配置(URLconf)就像Django 所支撑网站的目录。它的本质是URL与要为该URL调用的视图函数之间的映射表;你就是以这种方式告诉Django,对于客户端发来的某个URL调用哪一段逻辑代码对应执行。
一、简单的路由配置
- 若要从URL 中捕获一个值,只需要在它周围放置一对圆括号。
- 不需要添加一个前导的反斜杠,因为每个URL 都有。例如,应该是^articles 而不是 ^/articles。
- 每个正则表达式前面的'r' 是可选的但是建议加上。它告诉Python 这个字符串是“原始的” —— 字符串中任何字符都不应该转义
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | # 在urls.py中: from django.urls import path,re_path from app01 import views # 路由配置: 路径--------->视图函数 urlpatterns = [ path( 'admin/' , admin.site.urls), #无名分组:捕获的值作为位置参数传递给视图函数 re_path(r '^articles/([0-9]{4})/$' , views.year_archive), #year_archive(request,'2009') re_path(r '^articles/([0-9]{4})/([0-9]{2})/$' , views.month_archive), # month_archive(request,'2009','12') re_path(r '^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$' , views.article_detail), # month_archive(request,'2009','12','1'),# month_archive(request,'2009','12','13') #有名分组:捕获的值作为关键字参数传递给视图函数 re_path(r '^articles/(?P<year>[0-9]{4})/$' , views.year_archive), # month_archive(request, year='2005') re_path(r '^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$' , views.month_archive), # month_archive(request, year='2005', month='03') re_path(r '^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})/$' , views.article_detail), # month_archive(request, year='2003', month='03', day='03') ] |
二、分发
1 2 3 4 5 6 7 8 9 10 11 | # 在urls.py中: from django.urls import path, re_path, include urlpatterns = [ path( 'admin/' , admin.site.urls), # 分发 re_path(r "^app01/" , include( "app01.urls" )), re_path(r "^app02/" , include( "app02.urls" )), re_path(r "^" , include( "app01.urls" )), ] |
三、反向解析
获得URL 的最终形式,,对于不同层级,Django 提供不同的工具用于URL 反查:
- 在模板中:使用url 模板标签。
- 在Python 代码中:使用from django.urls import reverse
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | # 在urls.py中: from django.urls import path, re_path, include from app01 import views urlpatterns = [ path( 'admin/' , admin.site.urls), # 反向解析 path( 'login.html/' , views.login, name = "Log" ), re_path(r '^articles/([0-9]{4})/$' , views.year_archive, name = 'news-year-archive' ), re_path(r '^articles/(?P<year>[0-9]{4})/$' , views.year_archive, name = 'news-year' ), ] # 在模板中:注意参数 """ <form action="{% url 'Log' %}" method="post"></form> <a href="{% url 'news-year-archive' 2012 %}">2012 Archive</a> <ul> {% for yearvar in year_list %} <li><a href="{% url 'news-year-archive' yearvar %}">{{ yearvar }} Archive</a></li> {% endfor %} </ul> <!--多个参数--> <a href="{% url "n4" i1 i2 %}">编辑</a> """ # 在views.py中: from django.urls import reverse from django.shortcuts import render, HttpResponse, redirect def redirect_to_year(request): # 无参 url = reverse( 'Log' ) print (url) # 有参 year = 2006 url88 = reverse( 'news-year-archive' , args = (year,)) url99 = reverse( 'news-year' , kwargs = { 'year' : 2008 }) return HttpResponse( 'OK' ) |
四、名称空间
命名空间(英语:Namespace)是表示标识符的可见范围。一个标识符可在多个命名空间中定义,它在不同命名空间中的含义是互不相干的。我们在开发项目时,会经常使用name属性反解出URL,当不小心在不同的app的urls中定义相同的name时,可能会导致URL反解错误,为了避免这种事情发生,引入了命名空间。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | # 在urls.py中: from django.urls import path, re_path, include, url urlpatterns = [ path( 'admin/' , admin.site.urls), # 分发 re_path(r "^app01/" , include( "app01.urls" )), re_path(r "^" , include( "app01.urls" )), # 两个应用中,URL 模式名字一样时: re_path(r "^app01/" , include(( "app01.urls" , "app01" ))), re_path(r "^app02/" , include(( "app02.urls" , "app02" ))), ] # 模板中 { % url 'app01:index' % } { % url 'app02:index' pk = item. id % } 带参数的 # app01中的urls.py from django.urls import path, re_path from app01 import views urlpatterns = [ re_path( "index/" , views.index, name = "index" ) ] # app02中的urls.py from django.urls import path, re_path from app02 import views urlpatterns = [ re_path( "index/" , views.index, name = "index" ) ] # app01中的views.py from django.shortcuts import render, HttpResponse,redirect from django.urls import reverse def index(reqeust): return redirect(reverse( "app01:index" )) # app02中的views.py from django.shortcuts import render, HttpResponse from django.urls import reverse def index(reqeust): return redirect(reverse( "app02:index" )) |
1、注意
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | # 'Specifying a namespace in include() without providing an app_name ' """ 方法1:在proj/urls.py中修改 """ urlpatterns = [ # url(r'^rbac/', include('rbac.urls', namespace='rbac')), url(r '^rbac/' , include(( 'rbac.urls' , 'rbac' ), namespace = 'rbac' )), ] """ 方法2:在rbac/urls.py中 添加 app_name='rbac' """ app_name = 'rbac' urlpatterns = [ url(r '^role/list/$' , role.role_list, name = 'role_list' ), # rbac:role_list ... ] """ 'ForeignKey' object has no attribute 'rel' """ self .remote_field = rel # return SearchGroupRow(title, field_object.rel.model.objects.filter(**db_condition), self, request.GET) return SearchGroupRow(title, field_object.remote_field.model.objects. filter ( * * db_condition), self , request.GET) |
五、django2.0版的path
1、基本实例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | # 在urls.py中: from django.urls import path, re_path from app01 import views urlpatterns = [ re_path( 'articles/(?P<year>[0-9]{4})/' , views.year_archive), re_path( 'article/(?P<article_id>[a-zA-Z0-9]+)/detail/' , views.detail_view), re_path( 'articles/(?P<article_id>[a-zA-Z0-9]+)/edit/' , views.edit_view), re_path( 'articles/(?P<article_id>[a-zA-Z0-9]+)/delete/' , views.delete_view), ] """ 1.函数 year_archive 中year参数是字符串类型的 2.三个路由中article_id都是同样的正则表达式,但是你需要写三遍,当之后article_id规则改变后,需要同时修改三处代码, 在Django2.0中,可以使用 path 解决以上的两个问题。 """ urlpatterns = [ path( 'articles/2003/' , views.special_case_2003), path( 'articles/<int:year>/' , views.year_archive), path( 'articles/<int:year>/<int:month>/' , views.month_archive), path( 'articles/<int:year>/<int:month>/<slug>/' , views.article_detail), ] |
2、基本规则
- 使用尖括号(<>)从url中捕获值。
- 捕获值中可以包含一个转化器类型(converter type),比如使用 捕获一个整数变量。若果没有转化器,将匹配任何字符串,当然也包括了 / 字符。
- 无需添加前导斜杠。
3、path转化器
Django默认支持以下5个转化器:
- str,匹配除了路径分隔符(/)之外的非空字符串,这是默认的形式
- int,匹配正整数,包含0。
- slug,匹配字母、数字以及横杠、下划线组成的字符串。
- uuid,匹配格式化的uuid,如 075194d3-6885-417e-a8a8-6c931e272f00。
- path,匹配任何非空字符串,包含了路径分隔符
4、注册自定义转化器
对于一些复杂或者复用的需要,可以定义自己的转化器。转化器是一个类或接口,它的要求有三点:
- regex 类属性,字符串类型
- to_python(self, value) 方法,value是由类属性 regex 所匹配到的字符串,返回具体的Python变量值,以供Django传递到对应的视图函数中。
- to_url(self, value) 方法,和 to_python 相反,value是一个具体的Python变量值,返回其字符串,通常用于url反向引用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | # urls.py: from django.urls import register_converter, path from app01 import yearconvert,views #使用register_converter 将其注册到URL配置中: register_converter(yearconvert.FourDigitYearConverter, 'yyyy' ) urlpatterns = [ path( 'articles/<yyyy:year>/' , views.year_archive), ] #app01.yearconvert.py: class FourDigitYearConverter: regex = '[0-9]{4}' #规则 def to_python( self , value): return int (value) # 在这转换了类型 def to_url( self , value): return '%04d' % value #app01.views.py: from django.shortcuts import render,HttpResponse,redirect def year_archive(request,year): print (year, type (year)) return HttpResponse( 'ok' ) |
MVC与MTV模型
一、MVC
Web服务器开发领域里著名的MVC模式,所谓MVC就是把Web应用分为模型(M),控制器(C)和视图(V)三层,他们之间以一种插件式的、松耦合的方式连接在一起,模型负责业务对象与数据库的映射(ORM),视图负责与用户的交互(页面),控制器接受用户的输入调用模型和视图完成用户的请求,其示意图如下所示:
二、MTV
Django的MTV模式本质上和MVC是一样的,也是为了各组件间保持松耦合关系,只是定义上有些许不同,Django的MTV分别是:
- M 代表模型(Model): 负责业务对象和数据库的关系映射(ORM)。
- T 代表模板 (Template):负责如何把页面展示给用户(html)。
- V 代表视图(View): 负责业务逻辑,并在适当时候调用Model和Template。
- 除了以上三层之外,还需要一个URL分发器,它的作用是将一个个URL的页面请求分发给不同的View处理,View再调用相应的Model和Template,MTV的响应模式如下所示: