视图函数
- 视图函数的第一个参数必须是 request。这个参数绝对不能少。
- 视图函数的返回值必须是
django.http.response.HttpResponseBase
的子类对象
URL 映射:
- 为什么回去 urls.py文件中寻找映射呢?
- 是因为在
settings.py
文件中配置了ROOT_URLCONF
为 urls.py。所有 django 回去urls.py
中寻找
- 是因为在
- 在
urls.py
中我们所有的映射,都应该放在urlpatterns
这个变量中 - 所有的映射不是随便写的,而是使用
path
函数或者是re_path
函数进行包装的
url 传参数
-
采用在 url 中使用变量的方式:在 path 的第一个参数中,使用
<参数名>
的方式可以传递参数,然后再视图函数中也要写一个参数,视图函数中的参数必须和 url 中的参数名称保持一致,不然就找不到这个参数。另外,url 中可以传递多个参数 -
采用查询字符串的方式:在 url 中,不需要单独的匹配查询字符串的部分,只需要在视图函数中使用
request.GET.get('参数名称')
的方式来获取。代码示例# book.views文件 def author(request): author_id = request.GET.get('id') text = "作者的 id 是:{}".format(author_id) return HttpResponse(text) #url.py 文件 urlpatterns = [ path('admin/', admin.site.urls), path('', index), # path('city/', views.city), path('book/', views.book), path('book/<detail_id>', views.book_detail), path('book/<detail_id>/<classify_id>', views.book_detail_classify), path('book/author/', views.author), ]
path 函数
url 参数的转换器:
- str: 除了斜杠
/
意外所有的字符都是可以的 - int:只有是一个或者多个的阿拉伯数字
- path:所有的字符都是满足的
- uuid:只有满足
uuid.uuid4()
这个函数返回的字符串的格式 - slug:英文中的横杠或者英文字符或者阿拉伯数字或者下划线才满足
urls 模块化
-
如果项目变得越来越大,那么 url 会变得越来越多,如果都放在主
urls.py
文件中,那么将不太好管理,因此我们可以将每个 app 自己的 urls 放在自己的 app 中进行管理,一般我们会在 app 中新建一个 urls.py 文件用来存储所有和这个 app 相关的子 url -
需要注意的地方
-
1.应该使用
include
函数包含子urls.py
,并且这个urls.py
的路径是相对于项目的路径,示例代码如下:urlpatterns = [ path('admin/', admin.site.urls), path('', index), # path('city/', views.city), path('book/', include("book.urls")), path('detail/', include("detail.urls")) ]
-
2.在
app
的urls.py
中,所有的url 匹配也要放在一个叫做urlpatterns
的变量中,否则找不到 -
url
是会根据主urls.py
和 app 中的urls.py
进行拼接的,因此注意不需要多加斜杠
-
URL命名
为什么需要 url 命名?
- 因为 url 是京城变化的,如果在代码中写死可能会经常改代码,给 url 去个名字,以后使用 url 的时候就是用他的名字进行翻转就可以了,就不需要写死 url 了
如何给一个 url 指定名称
- 在
path
函数中,传递一个name
参数就可以指定示例代码如下
urlpatterns = [
path("", views.index, name='index'),
path("sigin/", views.login, name='login')
]
应用命名空间
- 在多个 app 之间,有可能产生同名的 url,这时候为了避免翻转 url 的时候产生混淆,可以使用应用命名空间,来做区分,定义应用命名空间非常简单,只要在
app
的urls.py
中定义一个app_name
的变量,来制定这个应用的命名空间即可
front 下的 urls.py
app_name = 'front'
urlpatterns = [
path("", views.index, name='index'),
path("sigin/", views.login, name='login')
]
- 以后在做反转的时候就可以使用
应用命名空间:url 名称
的方式进行反转。示例代码如下
def index(request):
if request.GET.get('username'):
return HttpResponse("这是前台首页")
else:
print(reverse('login'))
# return redirect('aaaaa') # 填写要去的页面的路径,此出的 login 并不是下面的 login 方法名
return redirect(reverse('front:login'))
def login(request):
return HttpResponse("这是前台登录页面")
- 应用命名空间是为了避免 path 中存在相同的名字,所以指定应用命名空间
应用命名空间和实例命名空间
- 一个 app,可以创建多个实例,可以使用多个 url 映射到同一个 app。所以这就会产生一个问题。以后再做反转的时候,如果使用应用命名空间,name 就会发生混淆,因为都是使用的 path 中的 url 的命名,每个人都可以起同样的名字,再反转的时候要指定对应的实例空间,为了避免这个问题就可以使用实例命名空间,实例命名空间也非常简单在
include
函数中传递一个namespace
变量即可示例代码如下
urlpatterns = [
path('', index),
path('cms1/', include('cms.urls', namespace='cms1')),
path('cms2/', include('cms.urls', namespace='cms2'))
]
- 以后在做反转的时候,就可以根据实例命名空间来指定具体的 url,实例代码如下
from django.shortcuts import render
from django.http import HttpResponse
from django.shortcuts import redirect, reverse
# Create your views here.
def index(request):
if request.GET.get("username"):
return HttpResponse("这是 cms 的首页")
else:
current_namespace = request.resolver_match.namespace
# return redirect(reverse('{}:login/'.format(current_namespace)))
return redirect(reverse('%s:login' % current_namespace))
def login(request):
return HttpResponse("这是 cms 的登录页面")
- 注意:在使用实例命名空间的时候需要要在 app 的
urls.py
文件中写应用命名空间,不指定会报错
django.core.exceptions.ImproperlyConfigured: Specifying a namespace in include() without providing an app_name is not supported. Set the app_name attribute in the included module, or pass a 2-tuple containing the list of patterns and app_name instead.
-
实例命名空间是为了在翻转 url 时,找到对应的实例,同一个 app 映射到不同的 url 上,那么如何找到对应的 url。就需要用道实例空间
-
如何反转到一个动态参数的页面,使用revers()的 kwargs 参数哦
def index(request):
if request.GET.get("username"):
return HttpResponse("电影首页")
else:
# return redirect(reverse('mv:login'))
current_spacename = request.resolver_match.namespace
# return redirect(reverse('{}:login'.format(current_spacename)))
return redirect(reverse('mv:list', kwargs={'movie_id': 222})) # 如何反转到一个有动态参数的页面?
include函数的用法
- 1.include(module,namespace=None):
- Module:子 url 的模块字符串
- namespace:实例命名空间,需要注意的是如果指定了实例命名空间那么前提必须要先指定应用命名空间,也就是子
urls.py
中添加app_name
变量
-
- include(pattern_list,app_namespace),namespace=None):
include
函数的第一个参数既可以为一个字符串,也可以为一个元祖,如果是元祖,那么元祖的第一个参数是字urls.py
模块的字符串,元祖的第二个参数是应用命名空间,也就是说应用命名空间既可以在字urls.py
中通过app_name
指定,也可以在include
函数中指定
- include(pattern_list,app_namespace),namespace=None):
re_path 笔记
-
re_path
和 path 的作用都是一样的,只不过re_path
是在写 url 的时候可以用正则表达式,功能上更加强大- 写正则表达式推荐使用原生字符串,也就是以
r
开头的字符串 - 在正则表达式中定义变量,需要使用圆括号括起来,这个参数是有名字的,那么需要使用
?P<参数名字>
,然后再后面添加正则表达式的规则,示例代码如下
urlpatterns = [ path('', views.index), re_path(r"^list/(?P<year>\d{4})/$", views.article_list), re_path(r"^list/(?P<year>\d{4})/(?P<month>\d{2})/(?P<day>\d{2})/$", views.article_list) ]
-
- 如果不是特别要求,直接使用
path
就够了,省的把代码搞得很麻烦(因为正则表达式其实晦涩的),特别是一些复杂的,可能就忘了,除非是 url 中确实需要使用正则表达式来解决才使用re_path
- 如果不是特别要求,直接使用
reverse 笔记
-
- 如果在反转 url 的时候,需要添加参数,那么可以传递
kwargs
参数到revers
函数中,示例代码
- 如果在反转 url 的时候,需要添加参数,那么可以传递
def index(request):
if request.GET.get("username"):
return HttpResponse("电影首页")
else:
# return redirect(reverse('mv:login'))
current_spacename = request.resolver_match.namespace
# return redirect(reverse('{}:login'.format(current_spacename)))
return redirect(reverse('mv:list', kwargs={'movie_id': 222})) # 如何反转到一个有动态参数的页面?
-
- 如果想要添加查询字符串的参数,则必须要手动进行拼接,示例代码如
def index(request):
if request.GET.get("username"):
return HttpResponse("电影首页")
else:
# return redirect(reverse('mv:login'))
current_spacename = request.resolver_match.namespace
# return redirect(reverse('{}:login'.format(current_spacename)))
# 如何反转到一个有动态参数的页面?
# return redirect(reverse('mv:list', kwargs={'movie_id': 222}))
# 如何反转一个查询字符串的页面呢?
return redirect(reverse('mv:login') + '?notlogin=1')