无意中在网上发现了这个网站自强学堂(作者还是校友),上面整理的教程都很不错,正好适合刚学完DjangoBasic篇之后的扩展。本系列作为该自强学堂教程的笔记,为节省时间,与DjangoBasic部分重叠的话,会省略。
1. Django全貌
-
urls.py,网址入口,关联到对应的views.py中的一个函数,访问网址就对应一个函数。
-
views.py,处理用户发出的请求,从urls.py中对应过来, 通过渲染templates中的网页可以将显示内容,比如登陆后的用户名,用户请求的数据,输出到网页。
-
models.py,与数据库操作相关,存入或读取数据时用到这个,当然用不到数据库的时候 你可以不使用。
-
forms.py,表单,用户在浏览器上输入数据提交,对数据的验证工作以及输入框的生成等工作,当然你也可以不使用。
-
templates文件夹,views.py 中的函数渲染templates中的Html模板,得到动态内容的网页,当然可以用缓存来提高速度。
-
admin.py,后台,可以用很少量的代码就拥有一个强大的后台。
-
settings.py,Django 的设置,配置文件,比如 DEBUG 的开关,静态文件的位置等。
2. 常用Django相关命令
功能 | 命令 | 备注 |
---|---|---|
新建一个 django project | django-admin startproject project_name | - |
新建 app | python manage.py startapp app_name | - |
创建数据库类SQL文件(.py) | python manage.py makemigrations | |
将类SQL文件应用到数据库 | python manage.py migrate | |
使用开发服务器 | python manage.py runserver | |
清空数据库 | python manage.py flush | 保留空表 |
创建超级管理员 | python manage.py createsuperuser | |
修改 用户密码 | python manage.py changepassword username | |
★导出数据 | python manage.py dumpdata appname > appname.json | |
★导入数据 | python manage.py loaddata appname.json | |
Django 项目环境终端 | python manage.py shell | |
★数据库命令行 | python manage.py dbshell | 能执行sql |
更多命令 | 终端上输入 python manage.py 可以看到详细的列表 |
3. Django 视图与网址
3.1 基础
- 创建app
(myvenv) C:\Users\utane\OneDrive\pythonCode>django-admin startproject zqxtTest
(myvenv) C:\Users\utane\OneDrive\pythonCode>cd zqxtTest
(myvenv) C:\Users\utane\OneDrive\pythonCode\zqxtTest>python manage.py startapp learn
- 将’learn’添加到setting.py的INSTALLED_APPS中
新建的 app 如果不加到 INSTALL_APPS 中的话, django 就不能自动找到app中的模板文件(app-name/templates/下的文件)和静态文件(app-name/static/中的文件)
- 定义视图函数 打开上述新建的app的views.py文件,添加新的视图:
from django.shortcuts import render
from django.http import HttpResponse
def index(request):
return HttpResponse(u"欢迎光临")
现在还剩下一步,如何上讲述view与url关联。
- view与url的关联-方法1 这种方法是之前DjangoBasic中使用的,也是通用性最好的方法-遇到特定的网址,就把解析的任务交给特定的app的url解析器。 urls.py文件中
from django.conf.urls import url,include # 方法1
from django.contrib import admin
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^$', include('learn.urls'))
]
同时在learn中也需要添加urls.py文件
# 方法1
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^$', views.index, name='index'),
]
- view与url的关联-方法2和方法3 将其他app的views引入当前app中,然后指向该app的对应view,两类方法类似。
from django.conf.urls import url
from django.contrib import admin
# from learn import views # 方法2
# from learn.views import index # 方法3
urlpatterns = [
url(r'^admin/', admin.site.urls),
# url(r'^$',index,name="index") # 方法3
# url(r'^$',views.index, name="index") # 方法2
]
3.2 进阶(获取get型request中的参数)
本示例,通过url传递参数过来,在view中进行计算,并将结果生成html相应结果,再返回给用户。
1. 采用 /add/?a=4&b=5&c=6
这样GET方法进行
- views.py中添加对应的处理view
def add(request):
a = request.GET.get('a',0)
b = request.GET.get('b',0)
x = request.GET.get('x',0)
c = int(a) + int(b) + int(x)
return HttpResponse(str(c))
request.GET.get('x',0)
,当无法取到x的时候,会有默认值0。
- project的urls.py中,添加对应的url处理:如果遇到add开头的url,则将处理丢给learn这个app处理。
url(r'^add/*', include('learn.urls'),name='add')
- learn的urls.py中,添加对应的url处理:
urlpatterns = [
url(r'^$', views.add, name='add'),
]
上面的url是经过project的url处理过后的url,故已经没有了
add
。
- 访问
http://127.0.0.1:8000/add/?a=4&b=5&x=50
,html上显示59
。如果访问http://127.0.0.1:8000/add/?a=4&b=5
,也可以得到正确的结果。因为add view在处理的时候使用request.GET.get('x',0)
,当无法取到x的时候,会有默认值0。
总结:
上面的处理方式,限定了url中的参数名称,如果将x修改为y的话,就无法取到值,得到错误结果了。
2. 采用 /add/4/5/50
这样的网址的方式
- 将learn app的urls.py修改为如下:
urlpatterns = [
url(r'^$', views.add, name='add'),
url(r'^(\d+)/(\d+)/(\d+)/$', views.add2, name='add2'),
]
即网址中多了 (\d+), 正则表达式中 \d 代表一个数字,+ 代表一个或多个前面的字符,写在一起 \d+ 就是一个或多个数字,用括号括起来的意思是保存为一个子组,每一个子组将作为一个参数
,被 views.py 中的对应视图函数接收。
- views中添加对应的处理视图
def add2(request, a, b,x):
c = int(a) + int(b) + int(x)
return HttpResponse(str(c))
-
project中的urls.py不需要修改,因为已经定义了
url(r'^add/*', include('learn.urls'),name='add')
,只要url中出现add,就会将url的解析任务交给learn app的url解析器。 -
访问
http://127.0.0.1:8000/add/4/5/50/
,可以得到正确的结果59
.
3. (参考)URL中参数的传递和提取
参考:在 DjangoBasic-03-模板扩展-blog详情页面中也涉及到了参数的传递和提取,参考如下的代码:
- 产生url的链接入口,在这里生成了一个pk参数,传递给了url生成器,url生成器用name为
post_detail
去标识。
<a href="[% url 'post_detail' pk=post.pk %}">[{ post.title }}</a>
- url解析器,接收到name为
post_detail
的url请求,会生成一个url,按照格式r'^post/(?P<pk>[0-9]+)/$'
,另外这个也可以用来匹配,即用户直接输入url时匹配用。
urlpatterns = [
url(r'^$', views.post_list, name='post_list'),
url(r'^post/(?P<pk>[0-9]+)/$', views.post_detail, name='post_detail'),
]
- 视图处理,接收上面子组(
每一个子组将作为一个参数
),与request一起传递给对应的视图post_detail。
def post_detail(request, pk):
post = get_object_or_404(Post, pk=pk)
return render(request, 'blog/post_detail.html', {'post': post})
4. Django URL name详解
4.1 通过html页面上的link进行计算
- 修改project的urls.py,为进入index视图添加url解析,注意这里修改了url的解析方式,这样直接从project的url解析跳到app的视图。
from django.conf.urls import url
from django.contrib import admin
from learn.views import index,add2 # new!
urlpatterns = [
url(r'^$', index, name='home'), # new!
url(r'^admin/', admin.site.urls),
url(r'^add/(\d+)/(\d+)/(\d+)/$', add2, name='add2'),
]
- views中添加对应视图
def index(request):
return render(request, 'home.html')
- 添加html模板文件,在learn下新建templates文件夹,添加home.html
<!DOCTYPE html>
<html>
<head>
<title>自强学堂</title>
</head>
<body>
<a href="/add/4/5/80">计算 4+5+80</a>
</body>
</html>
- 这时运行http://localhost:8000,可以看到上述页面,点击链接可以得到正确的结果。
通过点击链接,跳转到对应的url,在project的urls中进行解析,进入learn的解析器,进入对应的视图add2,进行计算,并返回response。
4.2 问题:url的显示需求有变更
如果我不想用add表示在url中,要改成jiafa
呢,这样要修改对应的html模板和project的url解析器。
如果有大量的html文件,使用了上面的/add/4/5/80
链接进行计算呢,那么所有的都需要修改。
有没有一种更加优雅有效的方式呢,让呈现出来的url与link无关呢。
-
修改html中的link方式:
<a href="[% url 'add2' 4 5 20 %}">link</a>
-
将project中的url解析修改为
url(r'^jiafa/(\d+)/(\d+)/(\d+)/$', add2, name='add2'),
-
再次点击上面的link,除了能正确计算结果外,还能呈现修改后的网址
http://127.0.0.1:8000/jiafa/4/5/20/
可以看到,上面通过name匹配,生成了正确的url。
4.3 问题:如何让http://127.0.0.1:8000/add/4/5/20/
继续可用呢?
如果某个用户收藏了旧的网址,那么将不能进行计算了?如果让旧的网址仍然可用呢?
- 在 views.py 写一个跳转的函数,
from django.http import HttpResponseRedirect
def old_add2_redirect(request,a,b,x):
return HttpResponseRedirect(
reverse('add2',args=(a,b,x))
)
-
urls.py
中,添加url(r'^add/(\d+)/(\d+)/(\d+)/$', old_add2_redirect),
,即碰到这个url后,就进行redirect。 -
再次输入
http://127.0.0.1:8000/add/4/5/20/
,将url跳转到http://127.0.0.1:8000/jiafa/4/5/20/
,并能计算出结果。