Django第一个项目以及URL学习
一、创建第一个Django项目
使用命令行的方式创建
1、创建项目,打开终端,使用命令:django-admin startproject [项目名称] 即可创建。比如:django-admin startproject first_project。
2、创建应用(app):一个项目类似于一个架子,但真正起作用的还是app。在终端进入到项目所在的路径,然后执行python manage.py startapp [项目名称]创建一个app。
第一个Django程序的结构
运行项目
先进入项目中,然后执行python manage.py runserver
然后在浏览器中访问http://127.0.0.1:8000/
项目就成功运行起来了。
Ctrl+Fn+Pause即可退出程序
使用pycharm的方式创建
选择django,指定项目所在路径、以及python解释器,再点击Create即可创建项目。
pycharm创建的文件结构
运行程序
用pycharm运行项目,需要避免一个项目运行多次。
二、指定端口号和IP地址进行访问
python manage.py runserver 端口号
可以通过9000端口号访问网页
使用pycharm访问
访问网页
如果使用其他设备访问本设备的Django项目,需要在settings ALLOWED_HOSTS中放开其他设备的IP地址,关闭防火墙。
在windows主机上安装openssh
使用 PowerShell 安装 OpenSSH
若要使用 PowerShell 安装 OpenSSH,请先以管理员身份运行 PowerShell(win+x快捷键进行打开)。 为了确保 OpenSSH 可用,请运行以下 cmdlet:
Get-WindowsCapability -Online | Where-Object Name -like 'OpenSSH*'
如果两者均尚未安装,则此操作应返回以下输出:
Name : OpenSSH.Client~~~~0.0.1.0
State : NotPresent
Name : OpenSSH.Server~~~~0.0.1.0
State : NotPresent
然后,根据需要安装服务器或客户端组件:
# Install the OpenSSH Client
Add-WindowsCapability -Online -Name OpenSSH.Client~~~~0.0.1.0
# Install the OpenSSH Server
Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0
这两者应该都会返回以下输出:
Path : Online : True RestartNeeded : False
启动并配置 OpenSSH 服务器
若要启动并配置 OpenSSH 服务器来开启使用,请以管理员身份打开 PowerShell,然后运行以下命令来启动 sshd
service:
# Start the sshd service
Start-Service sshd
# OPTIONAL but recommended:
Set-Service -Name sshd -StartupType 'Automatic'
# Confirm the Firewall rule is configured. It should be created automatically by setup. Run the following to verify
if (!(Get-NetFirewallRule -Name "OpenSSH-Server-In-TCP" -ErrorAction SilentlyContinue | Select-Object Name, Enabled)) {
Write-Output "Firewall Rule 'OpenSSH-Server-In-TCP' does not exist, creating it..."
New-NetFirewallRule -Name 'OpenSSH-Server-In-TCP' -DisplayName 'OpenSSH Server (sshd)' -Enabled True -Direction Inbound -Protocol TCP -Action Allow -LocalPort 22
} else {
Write-Output "Firewall rule 'OpenSSH-Server-In-TCP' has been created and exists."
这样Linux可以通过22端口号访问windows
三、Django项目结构
1、manage.py 以后和项目交互基本上都是基于这个文件。一般都是在终端输入python manage.py[子命令],可以输入python manage.py help看下帮助
2、settings.py 项目的设置项,以后所有和项目相关的配置都是放在这个里面
3、urls.py 这个文件是用来配置URL路由的。比如访问http://127.0.0.1/news/ 是访问新闻列表页,这些配置需要再这个文件中完成。
4、wsgi.py 项目与WSGI协议兼容的web服务器的入口,部署的时候需要用到,一般情况下不需要修改。
四、Url与视图函数的映射
将生成的django项目中的url.py更改为如下代码:
from django.contrib import admin
from django.urls import path
from django.http import HttpResponse
def index(request):
return HttpResponse("首页")
def movie(request):
return HttpResponse('电影')
def book(request):
return HttpResponse('书籍')
urlpatterns = [
path("admin/", admin.site.urls),
# http://127.0.0.1:8000
path('', index),
path('movie/', movie),
path('book/', book),
]
如果改变返回首页为HttpResponse("首页")
返回电影页
返回书籍页
重构程序结构,生成book、movie package包,分割业务
将原始urls.py业务分割至book包和movie包中
urls.py
from django.contrib import admin
from django.urls import path
from django.http import HttpResponse
from book.views import book
from movie.views import movie
def index(request):
return HttpResponse("首页")
urlpatterns = [
path("admin/", admin.site.urls),
# http://127.0.0.1:8000
path('', index),
path('movie/', movie),
path('book/', book),
]
book.views.py
from django.http import HttpResponse
def book(request):
return HttpResponse('书籍')
movie.views.py
from django.http import HttpResponse
def movie(request):
return HttpResponse('电影')
新建书籍模型book models和电影模型movie models
如果处理表单验证类的可以新建两个forms.py
已经被安装的app
使用命令行创建app python manage.py startapp [app的名称]
可以看到django_001中多出了city app
五、Debug模式详解
开启debug模式的代码
开启debug模式的好处
1、如果开启了DEBUG模式,那么以后我们修改了Django项目的代码,然后按下Ctrl+S,那么Django就会自动给我们重启项目,不需要手动重启。
2、如果开启了DEBUG模式,那么如果以后Django项目中的代码中出现bug了,那么浏览器中和控制台会打印出错信息。
views.py
from django.http import HttpResponse
def book(request):
a=1
b=0
c=a/b
return HttpResponse('书籍')
3、在生产环境中,禁止开启DEBUG模式,不然有很大的安全隐患
4、如果关闭DEBUG模式,将DEBUG设置为False。必须要设置ALLOWED_HOSTS是用来设置以后通过这个变量中的IP地址和域名来进行访问。
如果不设置会产生错误:
将Run-configurations改为0.0.0.0
添加ALLOWED_HOSTS,以后访问必须通过ALLOWED_HOSTS中的IP地址进行访问,其他地址不允许
访问 http://本机IP:8000/
六、URL分发器
视图
视图一般都写在app的view.py中,并且视图的第一个参数永远都是request(一个HttpRequest)对象。这个对象存储了请求过来的所有信息,包括携带的参数以及一些头部信息等。在视图中,一般是完成逻辑相关的操作。比如这个请求是添加一篇博客,那么可以通过request来接收到这些数据,然后存储到数据库中,最后再把执行的结果返回给浏览器。视图函数的返回结果必须是"django.http.HttpRespoonseBase"对象或者子类的对象。视图函数的第一个参数必须是request,这个参数不能少。示例代码如下:
使用python manage.py startapp books先生成books项目
books.views.py
from django.http import HttpResponse
# Create your views here.
def books(request):
return(HttpResponse('图书首页'))
urls.py
from django.contrib import admin
from django.urls import path
from books.views import books
urlpatterns = [
path('admin/', admin.site.urls),
# http://127.0.0.1:8000
path('', index),
path('books/', books),
]
程序结构:
运行返回结果:
七、URL映射
视图写完后,需要与URL进行映射,也即用户在浏览器中输入什么URL的时候可以请求到这个视图函数,在用户输入了某个url,请求到我们的网站的时候,django会从项目的urls.py文件中寻找对应的视图。在urls.py文件中有一个urlpatterns变量,以后django就会从这个变量中读取所有的匹配规则。匹配规则需要使用django.urls.path函数进行包裹,这个函数会根据传入的参数返回URLPattern或者是URLResolver的对象。示例代码如下:
from django.contrib import admin
from django.urls import path
from books.views import books
urlpatterns = [
path('admin/', admin.site.urls),
path('books/', books),
]
1、由于在settings.py中指定了ROOT_URLCONF为“django_001.urls“,所以去urls.py寻找映射。
2、在urls.py中我们所有的映射,都应该放在urlpatterns变量中,django会固定去urlpatterns去寻找映射路径。
3、所有的映射都是使用path函数或者是re_path函数进行包装。
URL传递参数给视图函数
新建一个django_002项目2,并加入book app
book.views.py
from django.http import HttpResponse
# Create your views here.
def book(requests):
return HttpResponse("图书首页")
def book_detail(requests,book_id):
#可以从数据库中根据book_id提取这个图书的信息
text="您获取的图书id是%s"%book_id
return HttpResponse(text)
django_002.urls.py
from django.contrib import admin
from django.http import HttpResponse
from django.urls import path
from book import views
def index(request):
return HttpResponse("Hello, world. You're at the book index.")
urlpatterns = [
path("admin/", admin.site.urls),
path("", index),
path("book/", views.book),
# /book/detail/1
path("book/detail/<book_id>/",views.book_detail)
]
django_002.urls.py的映射参数的book_id与book.views.py中book_detail函数的参数book_id名称需要一致。
访问http://127.0.0.1:8000/book/detail/565/
访问http://127.0.0.1:8000/book/
修改为多个参数
book.views.py
from django.http import HttpResponse
# Create your views here.
def book(requests):
return HttpResponse("图书首页")
def book_detail(requests,book_id,book_category):
#可以从数据库中根据book_id提取这个图书的信息
text="您获取的图书id是%s图书分类是%s" %(book_id,book_category)
return HttpResponse(text)
django_002.urls.py
from django.contrib import admin
from django.http import HttpResponse
from django.urls import path
from book import views
def index(request):
return HttpResponse("Hello, world. You're at the book index.")
urlpatterns = [
path("admin/", admin.site.urls),
path("", index),
path("book/", views.book),
# /book/detail/1
path("book/detail/<book_id>/<book_category>",views.book_detail)
]
运行结果:
Url传参数
1、采用url中使用变量的方式,在path的第一个参数中,使用'<参数名>'的方式可以传递参数,然后在视图函数中也要写一个参数,视图参数中的参数必须和url中的参数名称保持一致,不然就找不到这个参数。另外,url中可以传递多个参数
2、可以采用查询字符串的方式:在url中,不需要单独的匹配查询字符串的部分,只需要在视图函数中使用"request.GET.get('参数名称')"的方式来获取。
采用查询字符串传参
book.views.py
from django.http import HttpResponse
# Create your views here.
def book(requests):
return HttpResponse("图书首页")
def book_detail(requests,book_id,book_category):
#可以从数据库中根据book_id提取这个图书的信息
text="您获取的图书id是%s图书分类是%s" %(book_id,book_category)
return HttpResponse(text)
def author_detail(requests):
author_id=requests.GET.get('id')
text="作者的id是:%s" %author_id
return HttpResponse(text)
django_002.urls.py
from django.contrib import admin
from django.http import HttpResponse
from django.urls import path
from book import views
def index(request):
return HttpResponse("Hello, world. You're at the book index.")
urlpatterns = [
path("admin/", admin.site.urls),
path("", index),
path("book/", views.book),
# /book/detail/1
path("book/detail/<book_id>/<book_category>",views.book_detail),
path("book/author/",views.author_detail)
]
输出结果:http://localhost:8000/book/author/?id=1
八、Path函数
path函数定义为:path(route,view,name=None,kwargs=None),以下对这几个参数进行讲解。
1、route参数:url的匹配规则,这个参数中可以指定url中需要传递的参数,比如在访问文章详情页的时候,可以传递一个id。传递参数是通过<>尖括号来进行指定的。并且在传递参数的时候,可以指定这个参数的数据类型,比如文章的id都是int类型,那么可以这样写<int id>,以后匹配的时候,就只会匹配id为int类型的url,而不会匹配其他的url,并且在视图函数中获取这个参数的时候,就已经被转换为一个int类型了。还有几种常用的类型:
- str:非空的字符串类型。默认的转换器,但是不能包含斜杠/
- int:匹配任意的0或者正数的整型。到视图函数中就是一个int类型。
- slug:由英文中的横杠-或者下划线_连接英文字符或者数字组成的字符串。
- uuid:匹配uuid字符串
- path:匹配非空的英文字符串,可以包含斜杠
这些都是类型转换器可以转换的类型
类型转换器覆盖类型
views.py
from django.http import HttpResponse
# Create your views here.
def book(requests):
return HttpResponse("图书首页")
def book_detail(requests,book_id,book_category):
#可以从数据库中根据book_id提取这个图书的信息
text="您获取的图书id是%s图书分类是%s" %(book_id,book_category)
return HttpResponse(text)
def author_detail(requests):
author_id=requests.GET.get('author_id')
text="作者的id是:%s" %author_id
return HttpResponse(text)
def publisher_detail(requests,publisher_id):
text='出版社的id是::%s' %publisher_id
return HttpResponse(text)
urls.py
from django.contrib import admin
from django.http import HttpResponse
from django.urls import path
from book import views
def index(request):
return HttpResponse("Hello, world. You're at the book index.")
urlpatterns = [
path("admin/", admin.site.urls),
path("", index),
path("book/", views.book),
# /book/detail/1
path("book/detail/<book_id>/<book_category>",views.book_detail),
path("book/author/",views.author_detail),
path("book/publisher_detail/<int:publisher_id>",views.publisher_detail)
]
运行结果:
如果更改为字符串转换器
from django.contrib import admin
from django.http import HttpResponse
from django.urls import path
from book import views
from django.urls import converters
def index(request):
return HttpResponse("Hello, world. You're at the book index.")
urlpatterns = [
path("admin/", admin.site.urls),
path("", index),
path("book/", views.book),
# /book/detail/1
path("book/detail/<book_id>/<book_category>",views.book_detail),
path("book/author/",views.author_detail),
path("book/publisher_detail/<str:publisher_id>",views.publisher_detail)
]
运行结果:
默认为str字符串转换器。字符串转换器不可识别/
如果更改为UUID类型
先生成一个UUID
>>> import uuid
>>> print(uuid.uuid4())
from django.contrib import admin
from django.http import HttpResponse
from django.urls import path
from book import views
from django.urls import converters
def index(request):
return HttpResponse("Hello, world. You're at the book index.")
urlpatterns = [
path("admin/", admin.site.urls),
path("", index),
path("book/", views.book),
# /book/detail/1
path("book/detail/<book_id>/<book_category>",views.book_detail),
path("book/author/",views.author_detail),
path("book/publisher_detail/<uuid:publisher_id>",views.publisher_detail)
]
输出结果为:
如果更改为slug类型
from django.contrib import admin
from django.http import HttpResponse
from django.urls import path
from book import views
from django.urls import converters
def index(request):
return HttpResponse("Hello, world. You're at the book index.")
urlpatterns = [
path("admin/", admin.site.urls),
path("", index),
path("book/", views.book),
# /book/detail/1
path("book/detail/<book_id>/<book_category>",views.book_detail),
path("book/author/",views.author_detail),
path("book/publisher_detail/<slug:publisher_id>",views.publisher_detail)
]
输出结果为:
如果更改为path类型
from django.contrib import admin
from django.http import HttpResponse
from django.urls import path
from book import views
from django.urls import converters
def index(request):
return HttpResponse("Hello, world. You're at the book index.")
urlpatterns = [
path("admin/", admin.site.urls),
path("", index),
path("book/", views.book),
# /book/detail/1
path("book/detail/<book_id>/<book_category>",views.book_detail),
path("book/author/",views.author_detail),
path("book/publisher_detail/<path:publisher_id>",views.publisher_detail)
]
输出结果为:
2、view参数:可以为一个视图参数或者类视图.as_view()或者是django.urls.include()函数的返回值。
3、name参数:这个参数是给这个url取个名字的,这在项目比较大,url比较多的时候用处很大
4、kwargs参数:有时候想给视图参数函数传递一些额外的参数,就可以通过kwargs参数进行传递。这个参数接收一个字典,传到视图函数中的时候,回座位一个关键字参数传过去。
九、URL模块化
在项目中,不可能只有一个app,如果把所有的views中的视图都放在urls.py中进行映射,肯定会让代码显得非常乱。因此django给我们提供了一个方法,可以在app内部包含自己的url的匹配规则,而在项目的urls.py中再统一包含这个app的urls。使用这个技术需要include函数。示例如下:
首先新建一个项目Django_003 djangoProject
在项目中加入book模块
在book中新建一个urls.py
from django.urls import path
from . import views
urlpatterns = [
path("", views.book),
path("detail/<book_id>/", views.book_detail),
path("book_list/", views.book_list),
]
book中的views.py
from django.http import HttpResponse
# Create your views here.
def book(request):
return HttpResponse("图书首页")
def book_detail(request,book_id):
text='图书的id是%s'%book_id
return HttpResponse(text)
def book_list(request):
return HttpResponse("图书列表页面")
djangoProject中的urls.py文件
from django.contrib import admin
from django.urls import path,include
from book import views
urlpatterns = [
path("admin/", admin.site.urls),
path("book/", include('book.urls')),
]
访问的url相当于djangoProject中的urls与books中的urls进行一个拼接,include使用的是相对于项目的路径。
运行如下:
url模块化:
如果项目变得越来越大,那么url会变得越来越多,如果都放在"urls.py"文件中,那么将不太好管理,因此我们可以将每个app自己的urls放到自己的app中进行管理。一般我们会在app中新建一个urls.py文件用来存储所有和这个app相关的子url。
需要注意的地方:
1、应该使用"include"函数包含"urls.py",并且这个"urls.py"的路径相对于项目的路径。
2、在'app'的'urls.py'中,所有的url匹配也要放在一个叫做'urlpattern'的变量中,否则找不到
3、'url'是会根据主'urls.py'和app中的'urls.py'进行拼接的,因此注意不要多加斜杠。
十、url命名
在pycharm中新建一个url_name_demo的项目
设置它的work interpreter
创建两个app front用来管理前台相关的代码,cms用来管理后台相关的代码
项目结构
分别在front模块和cms模块加入views.py视图
front.views.py
在front.views.py加判断获取用户名,如果非空返回首页,否则返回front登录页面
from django.http import HttpResponse
from django.shortcuts import redirect
# Create your views here.
def index(request):
#先判断是否有username
username=request.GET.get('username')
if username:
return HttpResponse("front首页%s" % username)
else:
return redirect('/login/')
def login(request):
return HttpResponse("front登录页面")
cms.views.py
from django.http import HttpResponse
# Create your views here.
def index(request):
return HttpResponse("CMS首页")
def login(request):
return HttpResponse("CMS登录页面")
分别在front模块、cms模块、url_name_demo中加入urls.py
front.urls.py
from . import views
from django.urls import path
urlpatterns = [
path('', views.index),
path('login/',views.login)
]
cms.urls.py
from . import views
from django.urls import path
urlpatterns = [
path('', views.index),
path('login/',views.login)
]
url_name_demo.urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path("admin/", admin.site.urls),
path('', include('front.urls')),
path('cms/', include('cms.urls')),
]
运行结果:
不加参数访问时
加参数访问时
反转url
front.view.py
from django.http import HttpResponse
from django.shortcuts import redirect,reverse
# Create your views here.
def index(request):
#先判断是否有username
username=request.GET.get('username')
if username:
return HttpResponse("front首页%s" % username)
else:
login_url=reverse('siginin')
print(login_url)
return redirect(login_url)
def login(request):
return HttpResponse("front登录页面")
front.urls.py
这里的siginin url会反转为login登录跳转至login中
from . import views
from django.urls import path
urlpatterns = [
path('', views.index,name='index'),
path('siginin/',views.login,name='login'),
]
CMS.urls.py
from . import views
from django.urls import path
urlpatterns = [
path('', views.index),
path('login/',views.login)
]
CMS.views.py
from django.http import HttpResponse
# Create your views here.
def index(request):
return HttpResponse("CMS首页")
def login(request):
return HttpResponse("CMS登录页面")
url_name_demo.urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path("admin/", admin.site.urls),
path('', include('front.urls')),
path('cms/', include('cms.urls')),
]
运行结果如下:
1、为什么需要给url命名?
因为url是需要经常变化的,如果在代码中写死可能会经常改代码,给url取个名字,以后使用url的时候就是用其名字反转即可。
2、如何给一个url指定名称
urlpatterns = [
path('', views.index,name='index'),
path('siginin/',views.login,name='login'),
]
十一、命名空间
当不指定命名空间时,如果不同模块取名相同,会跳转错误的链接,如下
CMS.urls.py
from . import views
from django.urls import path
urlpatterns = [
path('', views.index,name='index'),
path('login/',views.login,name='login'),
]
CMS.views.py
from django.http import HttpResponse
# Create your views here.
def index(request):
return HttpResponse("CMS首页")
def login(request):
return HttpResponse("CMS登录页面")
front.urls.py
from . import views
from django.urls import path
urlpatterns = [
path('', views.index,name='index'),
path('login/',views.login,name='login'),
]
front.views.py
from django.http import HttpResponse
from django.shortcuts import redirect,reverse
# Create your views here.
def index(request):
#先判断是否有username
username=request.GET.get('username')
if username:
return HttpResponse("front首页%s" % username)
else:
login_url=reverse('login')
print(login_url)
return redirect(login_url)
def login(request):
return HttpResponse("front登录页面")
url_name_demo.urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path("admin/", admin.site.urls),
path('', include('front.urls')),
path('cms/', include('cms.urls')),
]
当直接访问localhost:8000时,会自动跳转至CMS登录界面,但是我们希望的是跳转至front/login中
需要使用应用命名空间
改写front.urls
from . import views
from django.urls import path
app_name = 'front'
urlpatterns = [
path('', views.index,name='index'),
path('login/',views.login,name='login'),
]
改写cms.urls
from . import views
from django.urls import path
app_name = 'cms'
urlpatterns = [
path('', views.index,name='index'),
path('login/',views.login,name='login'),
]
改写front.views.py
from django.http import HttpResponse
from django.shortcuts import redirect,reverse
# Create your views here.
def index(request):
#先判断是否有username
username=request.GET.get('username')
if username:
return HttpResponse("front首页%s" % username)
else:
login_url=reverse('front:login')
print(login_url)
return redirect(login_url)
def login(request):
return HttpResponse("front登录页面")
此时可以正确的跳转到front login url
应用命名空间:在多个app之间,有可能产生同名的url,这时候为了避免反转url的时候产生混淆,可以使用应用命名空间做区分。定义应用命名空间非常简单,只要在'app'的urls.py中定义app_name即可。以后在做反转时可以使用“应用命名空间:url名称”的方式可以进行反转。
应用(app)命名空间和实例命名空间:
一个app,可以创建多个实例,可以使用多个url映射同一个app,所以这就会产生一个问题,以后在做反转的时候,如果使用应用命名空间,那么就会发生混淆,为了避免这个问题,我们可以使用实例命名空间,实例命名空间只需要在"include"函数中传递一个"namespace"变量即可。
url_name_demo.urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path("admin/", admin.site.urls),
path('', include('front.urls')),
path('cms1/', include('cms.urls',namespace='cms1')),
path('cms2/', include('cms.urls',namespace='cms2')),
]
CMS.urls.py
from . import views
from django.urls import path
app_name = 'cms'
urlpatterns = [
path('', views.index,name='index'),
path('login/',views.login,name='login'),
]
以后在做反转的时候可以根据实例命名空间来指定具体的url,示例代码如下:
CMS.views.py
from django.http import HttpResponse
from django.shortcuts import redirect
from django.urls import reverse
# Create your views here.
def index(request):
username=request.GET.get('username')
if username:
return HttpResponse('CMS首页, %s!' % username)
else:
current_namespace=request.resolver_match.namespace
return redirect(reverse("%s:login"%current_namespace))
def login(request):
return HttpResponse("CMS登录页面")
front.urls.py
from . import views
from django.urls import path
app_name = 'front'
urlpatterns = [
path('', views.index,name='index'),
path('login/',views.login,name='login'),
]
front.views.py
from django.http import HttpResponse
from django.shortcuts import redirect,reverse
# Create your views here.
def index(request):
#先判断是否有username
username=request.GET.get('username')
if username:
return HttpResponse("front首页%s" % username)
else:
login_url=reverse('front:login')
print(login_url)
return redirect(login_url)
def login(request):
return HttpResponse("front登录页面")
此时可以实现多url单映射场景
十二、include()函数详解
include函数的三种用法
1、include(module,namespace=None)
module:子url的模块字符串
namespace:实例命名空间,这个地方需要注意一点,如果指定实例命名空间,那么前提必须要先指定应用命名空间,也就是在子"urls.py"中添加"app_name"这个变量。
2、include(pattern_list)
include可以指定列表的形式,pattern_list是一个列表,这个列表中装的是'path'或者're_path'函数。
3、include(pattern_list,app_namespace,namespace=None)
函数的第一个参数既可以为一个字符串,也可以是一个元组,如果是一个元组,那么元组的第一个参数是子'urls.py'模块的字符串,也可以为一个元组,那么元组的第一个参数是子'urls.py'模块的字符串,元组的第二个参数是应用命名空间,也就是说,应用命名空间既可以在子'urls.py'中通过'app_name'指定,也可以在'include'函数中指定。
1、include(module,namespace=None)
需要指定应用命名空间之后在指定实例命名空间,如果只指定实例命名空间不指定应用命名空间会报错。比如:
cms.urls.py
from . import views
from django.urls import path
# app_name = 'cms'
urlpatterns = [
path('', views.index,name='index'),
path('login/',views.login,name='login'),
]
url_name_demo.urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path("admin/", admin.site.urls),
path('', include('front.urls')),
#在没有指定应用命名空间的时候,直接指定的是实例命名空间
path('cms1/', include('cms.urls',namespace='cms1')),
path('cms2/', include('cms.urls',namespace='cms2')),
]
报错如下:
当不在实例命名空间中指定app_name时,可以在url_name_demo.urls.py使用include函数直接指定实例命名空间。
book.urls.py
from django.urls import path
from . import views
# app_name='book'
urlpatterns = [
path("", views.book),
path("detail/<book_id>/", views.book_detail),
path("book_list/", views.book_list),
]
url_name_demo.urls.py
from django.contrib import admin
from django.urls import path,include
from book.views import book
urlpatterns = [
path("admin/", admin.site.urls),
path("book/", include(('book.urls','book'),namespace='book'))
]
运行结果如下:
2、include(pattern_list)
include可以指定列表的形式。
在项目中加入movie模块
books.urls.py
from django.urls import path
from . import views
# app_name='book'
urlpatterns = [
path("", views.book),
path("detail/<book_id>/", views.book_detail),
path("book_list/", views.book_list),
]
books.views.py
from django.http import HttpResponse
# Create your views here.
def book(request):
return HttpResponse("图书首页")
def book_detail(request,book_id):
text='图书的id是%s'%book_id
return HttpResponse(text)
def book_list(request):
return HttpResponse("图书列表页面")
movie.urls.py
from django.urls import path
from . import views
# app_name='book'
urlpatterns = [
path("", views.movie),
path("movie_list/", views.movie_list),
]
movie.views.py
from django.http import HttpResponse
# Create your views here.
def movie(request):
return HttpResponse("电影首页")
def movie_list(request):
return HttpResponse("电影列表页")
djangoProject.urls.py
from django.contrib import admin
from django.urls import path,include
from movie import views
urlpatterns = [
path("admin/", admin.site.urls),
path("book/", include(('book.urls','book'),namespace='book')),
path("movie/", include([
path('',views.movie),
path('list/',views.movie_list),
]))
]
访问http://localhost:8000/movie/
http://localhost:8000/movie/list/
十二、re_path函数详解
1、re_path和path作用都是一样的,只不过re_path是在写url的时候可以使用正则表达式,功能更加强大。
2、写正则表达式推荐使用原生字符串,也就是以"r"开头的字符串
3、在正则表达式中定义变量,需要使用圆括号括起来,这个参数是有名字的,那么需要使用"?p<参数的名字>",然后在后面添加正则表达式的规则。
4、如果不是特殊要求,尽量少使用re_path,使用path解决。
示例代码如下:
首先新建项目re_path_demo,然后在项目中加入article app
article.views.py
from django.shortcuts import render
# Create your views here.
from django.http import HttpResponse
def article(request):
return HttpResponse('文章首页')
def article_list(request,year):
text="您输入的年份是%s" %year
return HttpResponse(text)
def article_list_month(request,month):
text="您输入的月份是%s" %month
return HttpResponse(text)
article.urls.py
from . import views
from django.urls import re_path
urlpatterns = [
# r"",代表的是原生字符串(raw)
re_path(r'^$', views.article),
re_path(r"^list/(?P<year>\d{4})/$", views.article_list),
re_path(r"^list/(?P<month>\d{2})/$", views.article_list_month),
]
re_path_demo.urls.py
from django.urls import path, include
urlpatterns = [
path("article/", include('article.urls')),
]
运行结果如下:
十三、reverse函数补充
1、如果在反转url的时候,需要添加参数,那么可以传递kwargs参数到reverse函数中。
2、如果是想要添加查询字符串字段,则必须手动进行拼接。
新建项目reverse_demo,并加入app front
使用kwargs关键字添加参数
reverse_demo.front.views.py
from django.http import HttpResponse
from django.shortcuts import reverse,redirect
def index(request):
username=request.GET.get('username')
if username :
return HttpResponse('首页')
else:
detail_url=reverse("article_detail",kwargs={'article_id':1})
# /detail/1
return redirect(detail_url)
def login(request):
return HttpResponse("登录页面")
def article_detail(request,article_id):
text="您的文章id是:%s" %(article_id)
return HttpResponse(text)
reverse_demo.py
from front import views
from django.urls import path
urlpatterns = [
path('',views.index,name='index'),
path('login/',views.login,name='login'),
path('article_detail/<article_id>',views.article_detail,name='article_detail'),
]
运行结果如下:
这时候直接访问http://localhost:8000/会跳转至article_detail函数中去,kwargs的关键字是article_id为1
添加查询字符串
reverse_demo.front.views.py
from django.http import HttpResponse
from django.shortcuts import reverse,redirect
def index(request):
username=request.GET.get('username')
if username :
return HttpResponse('首页')
else:
# # 添加查询字符串
login_url=reverse('login')+"?next=/"
return redirect(login_url)
def login(request):
return HttpResponse("登录页面")
def article_detail(request,article_id):
text="您的文章id是:%s" %(article_id)
return HttpResponse(text)
reverse_demo.urls.py
from front import views
from django.urls import path
urlpatterns = [
path('',views.index,name='index'),
path('login/',views.login,name='login'),
path('article_detail/<article_id>',views.article_detail,name='article_detail'),
]
运行结果如下:
这个时候直接访问http://localhost:8000/会自动跳转
十三、自定义path转换器
之前已经学习过一些django的内置url转换器,包括int、uuid等,有时候这些内置的url的转换器并不能满足我们的需求,因此django给我们提供了一个接口可以让我们自己定义自己的url转换器。
自定义url转换器按照以下5个步骤:
1、定义一个类,这个类直接继承自object就可以了
2、在类中定义一个属性regex,这个属性是用来保存url转换器规则的正则表达式
3、实现to_python(self,value)方法,这个方法是将url中的值转换一下,然后给视图函数的。
4、实现to_url(self,value)方法,这个方法是在做url反转的时候,将传进来的参数转换后拼接成一个正确的url
5、将定义好的转换器,注册到django中。
新建项目path_converter_demo,并加入article模块
article.urls.py
from . import views
from django.urls import path, re_path
# 需求:
# 实现一个获取文章列表的demo,用户可以根据"/articles/文章分类"
# 的方式来获取文章。其中文章分类采用的是"分类1+分类2+分类3..."
# 的方式拼接的,并且如果只有一个分类,那就不需要加号。示例如下:
# #第一种:获取python分类下的文章
# /article/python
# #第二种:获取python和django分类下的的文章
# /articles/python+django/
# #第三种:获取python和django和flask下的文章
# /articles/python+django+flask/
urlpatterns = [
path('', views.article),
# \w: 0-9,a-z,A-Z
# re_path(r'list/(?P<category_name>\w+|(\w+\+\w+)+/', views.article_list),
path("list/<cate:category_name>/", views.article_list,name='list'),
path('detail/<int:article_id>/',views.article_detail,name='detail'),
]
article.views.py
from django.http import HttpResponse
from django.urls import reverse
def article(request):
return HttpResponse("文章首页")
def article_list(request,category_name):
reverse('list', kwargs={'category_name': category_name})
text='您填写的分类是:%s'%category_name
return HttpResponse(text)
def article_detail(request,article_id):
reverse('detail',kwargs={'article_id':article_id})
print(type(article_id))
return HttpResponse("文章详情%s"%article_id)
在article中实现CategoryConverter converter.py
from django.urls import converters,register_converter
class CategoryConverter(object):
regex = r'\w+|(\w+\+\w+)+'
def to_python(self, value):
# python+django+flask
# ['python','django','flask']
result=value.split("+")
return result
def to_url(self, value):
# value:['python','django','flask']
# python+django+flask
if isinstance(value,list):
result="+".join(value)
return result
else:
return RuntimeError("转换url的时候,分类参数必须要为列表!")
register_converter(CategoryConverter,"cate")
在article.__init__.py中引入converter
from . import converter
path_converter_demo.urls.py
from django.urls import path, include
urlpatterns = [
path('article/', include('article.urls')),
]
运行结果如下:
十四、指定默认的参数
使用path或者是re_path之后,在route中都可以包含参数,而有时候想指定默认的参数,这时候可以通过在views.py中指定默认参数来完成。
新建项目default_params_demo
urls.py
from django.urls import path
from . import views
urlpatterns = [
path("", views.books),
path("page/<int:page>/",views.books)
]
views.py
from django.http import HttpResponse
book_list=[
'三国演义',
'水浒传',
'西游记',
'红楼梦'
]
def books(request,page=0):
return HttpResponse(book_list[page])
访问http://localhost:8000/,会自动填充http://localhost:8000/page/0/
当在访问page/的时候,在page函数中,又有page=0这个默认参数,因此这时候就可以不用传递参数,而如果访问page/1的时候,因为在传递参数的时候传递了page,这时候也会执行views.books,然后把传递进来的参数传给books函数中的page。