视图一般都写在app的views.py中。并且视图的第一个参数永远都是request(一个HttpRequest)对象。这个对象存储了请求过来的所有信息,包括携带的参数以及一些头部信息等。在视图中,一般是完成逻辑相关的操作。比如这个请求是添加一篇博客,那么可以通过request来接收到这些数据,然后存储到数据库中,最后再把执行的结果返回给浏览器。视图函数的返回结果必须是HttpResponseBase对象或者子类的对象。
视图文件:book/views.py
from django.shortcuts import render
# Create your views here.
from django.http import HttpResponse
# django框架中写视图函数,必须要传参request
def book(request):
return HttpResponse("图书首页") # 返回值必须是 HttpResponse包裹住的类型
# django框架中写视图函数,必须要传参request
def index(request):
return HttpResponse("hello world") # 返回值必须是 HttpResponse包裹住的类型
定义路由文件:项目名称 /urls.py, 该路由文件与其他文件相互关联的原因在frist_django/settings.py
文件中的ROOT_URLCONF = 'frist_django.urls'
设置,frist_django是项目app名称。
"""frist_django URL Configuration
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/2.2/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: path('', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path
from django.http import HttpResponse
from book.views import book # 从其他app模块中导入定义的路由方法
from book.views import index
urlpatterns = [
path('admin/', admin.site.urls), # django默认路由前面有/,不需要添加
path('', index), # 路由为/,绑定的方法是book模块中views.py的index方法
path('book/', book), # 路由为book/,绑定的方法是book模块中views.py的index方法
]
视图写完后,要与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 book import views
urlpatterns = [
path('admin/', admin.site.urls),
path('book/',views.book_list)
]
创建新的Django项目
# 首先先进入虚拟环境下
cd /d E:\ENV\Django项目\2-课
# 创建django项目,名称为django_url
django-admin startproject django_url
# 进入
cd django_url\
# 创建新的app模块,名称为book
python manage.py startapp book
有时候,url中包含了一些参数需要动态调整。比如简书某篇文章的详情页的url,是https://www.jianshu.com/p/a5aab9c4978e后面的a5aab9c4978e就是这篇文章的id,那么简书的文章详情页面的url就可以写成https://www.jianshu.com/p/,其中id就是文章的id。那么如何在django中实现这种需求呢。这时候我们可以在path函数中,使用尖括号的形式来定义一个参数。比如我现在想要获取一本书籍的详细信息,那么应该在url中指定这个参数。(后面的a5aab9c4978e就是这篇文章的id,是为了安全考虑,防止SQL注入等手段;还有就是隐藏网站中的真实文章数量等功能)
视图文件:book/views.py
from django.shortcuts import render
from django.http import HttpResponse
def book(request):
return HttpResponse("图书首页")
def book_detail(request, book_id, cate_id):
return HttpResponse("图书详情,id为%s,分类id%s" % (book_id, cate_id))
定义路由文件:项目名称 /urls.py
from django.contrib import admin
from django.urls import path
from book import views
urlpatterns = [
path('admin/', admin.site.urls),
path('book/', views.book),
path('book//' , views.book_detail), # 必须与views.book_detail方法中的参数名称相同
]
视图文件:book/views.py
from django.shortcuts import render
from django.http import HttpResponse
def book_list(request):
print(type(request)) # 类
book_id = request.GET.get('id') # 从urls.py传输过来的参数id,GET是request类中的方法,request.GET返回的是字典,get获取字典中的参数
return HttpResponse("图书列表%s" % book_id)
定义路由文件:项目名称 /urls.py
from django.contrib import admin
from django.urls import path
from book import views
urlpatterns = [
path('admin/', admin.site.urls),
path('book_list/', views.book_list), # 关键字传参,不需要在路由中写参数
]
关键字传参,以? 号隔开传参参数,不需要在路由中写参数,实现的路由效果:
def book_list(request):
print(type(request)) # 类
book_id = request.GET.get('id') # 从urls.py传输过来的参数id,GET是request类中的方法,request.GET返回的是字典,get获取字典中的参数
c_id = request.GET.get('cid')
return HttpResponse("图书列表%s, 图书类别是%s" % (book_id, c_id))
URL中包含另外一个urls模块:
在我们的项目中,不可能只有一个app,如果把所有的app的views中的视图都放在urls.py中进行映射,肯定会让代码显得非常乱。因此django给我们提供了一个方法,可以在app内部包含自己的url匹配规则,而在项目的urls.py中再统一包含这个app的urls。使用这个技术需要借助include函数。
定义路由文件:项目名称 /urls.py
from django.contrib import admin
from django.urls import path, include # include是url模块化
urlpatterns = [
path('admin/', admin.site.urls),
# path('book/', views.book),
# path('book//', views.book_detail), # 必须与views.book_detail方法中的参数名称相同
# path('book_list/', views.book_list), # 关键字传参,不需要在路由中写参数
# url模块化,定义book模块的前缀路由,关联book模块下的urls.py文件
path("book/", include("book.urls"))
]
book模块app文件下的路由文件:book/urls.py
# -*- encoding: utf-8 -*-
"""
@File : urls.py
@Time : 2020/6/17 15:54
@Author : chen
book模块app文件下的路由文件:book/urls.py
"""
from django.urls import path
from . import views # 引用当前文件夹下的views.py文件
# 此时的路由是book模块下定义的,需要被整体项目下的urls.py文件包含,而且路由前缀是需要在django_url/urls.py文件中定义
urlpatterns = [
path('', views.book),
path('book//' , views.book_detail), # 必须与views.book_detail方法中的参数名称相同
path('book_list/', views.book_list), # 关键字传参,不需要在路由中写参数
]
在urls.py文件中把所有的和book这个app相关的url都移动到app/urls.py中了,django_first/urls.py中,通过include函数包含book.urls,以后在请求book相关的url的时候都需要加一个book的前缀。
from django.urls import converters
UUID:https://www.cnblogs.com/franknihao/p/7307224.html
from django.urls import path
from . import views # 引用当前文件夹下的views.py文件
from django.urls import converters
# 此时的路由是book模块下定义的,需要被整体项目下的urls.py文件包含,而且路由前缀是需要在django_url/urls.py文件中定义
urlpatterns = [
path('', views.book),
# 需要限制book_id和cate_id的数据类型,采用int类型数据
path('book//' , views.book_detail), # 必须与views.book_detail方法中的参数名称相同
path('book_list/', views.book_list), # 关键字传参,不需要在路由中写参数
]
1.为什么需要URL命名
因为在项目开发的过程中URL地址可能经常变动,如果写死会经常去修改
2.如何给一个URL指定名称
path("",views.index,name="index") # 将路由地址命名为index
实例如下:
视图文件:front/views.py
from django.shortcuts import render, redirect,reverse # 重定向
from django.http import HttpResponse
def front_index(request):
# 传参
username = request.GET.get('username') # 传参username,模拟传递用户名
if username:
return HttpResponse("前台首页") # 模拟用户登录后,转到首页界面
else: # 用户未登陆的时候,需要重定向到登录界面
# 重定向
# return redirect('login/') # 地址与front/urls.py文件中的路由地址要绑定
return redirect(reverse('front:login')) # 通过路由的name来进行反转,查找到定义的路由"signin/",front:是限制该路由的应用命名空间名称
def front_login(request):
return HttpResponse("前台登录界面")
注意:代码中的front:是限制该路由的应用命名空间名称,防止不同app模块命名路由相同,访问出现重定义,限制路由访问,该命名从urls.py文件中传入。
定义前台路由文件:front/urls.py
# -*- encoding: utf-8 -*-
"""
@File : urls.py
@Time : 2020/6/17 16:56
@Author : chen
定义前台路由文件:front/urls.py
"""
from django.urls import path
from . import views
# 应用命名空间
app_name = "front"
urlpatterns = [
path("", views.front_index, name="index"),
path("signin/", views.front_login, name="login"), # 路由名称signin/,如果后期项目需要修改路由,只需修改这里的路由地址,其他的都可以不用修改了
]
一个app,可以创建多个实例。可以使用多个URL映射同一个App。在做反转的时候,如果使用应用命名空间,就会发生混淆,为了避免这个问题,可以使用实例命名空间,实例命名空间使用,namespace=‘实例命名空间’。
django_url/urls.py ,定义实例命名空间
from django.contrib import admin
from django.urls import path, include # include是url模块化
# from book import views
urlpatterns = [
path('admin/', admin.site.urls),
# path('book/', views.book),
# path('book//', views.book_detail), # 必须与views.book_detail方法中的参数名称相同
# path('book_list/', views.book_list), # 关键字传参,不需要在路由中写参数
# url模块化,定义book模块的前缀路由,关联book模块下的urls.py文件
path("book/", include("book.urls")),
path("cms/", include("cms.urls")),
path("", include("front.urls")), # 前台界面直接访问
path("cms1/", include("cms.urls", namespace='cms1')), # 实例命名空间
path("cms2/", include("cms.urls", namespace='cms2')), # 实例命名空间
]
cms/views.py, 显示当前访问的实例命名空间名称
from django.shortcuts import render
from django.http import HttpResponse
def cms_index(request):
current_namespace = request.resolver_match.namespace # 获取当前访问的实例命名空间名称
print(current_namespace)
return HttpResponse("后台首页")
def cms_login(request):
return HttpResponse("后台登录界面")
如果这个url中需要传递参数,那么可以通过kwargs来传递参数。
reverse("book:detail",kwargs={"book_id":1})
因为django中的reverse反转url的时候不区分GET请求和POST请求,因此不能在反转的时候添加查询字符串的参数。如果想要添加查询字符串的参数,只能手动的添加。
login_url = reverse("front:singin") + "?name=xxx"
return redirect(login_url)
front/views.py
from django.shortcuts import render, redirect,reverse # 重定向
from django.http import HttpResponse
def front_index(request):
# 传参
username = request.GET.get('username') # 传参username,模拟传递用户名
if username:
return HttpResponse("前台首页") # 模拟用户登录后,转到首页界面
else: # 用户未登陆的时候,需要重定向到登录界面
# 重定向
# return redirect('login/') # 地址与front/urls.py文件中的路由地址要绑定
# return redirect(reverse('front:login')) # 通过路由的name来进行反转,查找到定义的路由"signin/",front:是限制该路由的应用命名空间名称
# 第一种传参:url反转重定向传参,关键字传参
# return redirect(reverse('front:article', kwargs={"article_id": 3}))
# 第二种传参:url反转重定向传参,字符串拼接传参
return redirect(reverse('front:login') + "?name = 详情信息")
def front_login(request):
name = request.GET.get('name')
return HttpResponse("前台登录界面% s" % name) # 这种选择字符拼接传参
def front_article(request, article_id):
return HttpResponse("前台登录界面 %s" % article_id) # 这种选择关键字传参
定义前台路由文件:front/urls.py
# -*- encoding: utf-8 -*-
"""
@File : urls.py
@Time : 2020/6/17 16:56
@Author : chen
定义前台路由文件:front/urls.py
"""
from django.urls import path
from . import views
# 应用命名空间
app_name = "front"
urlpatterns = [
path("", views.front_index, name="index"),
path("signin/", views.front_login, name="login"), # 路由名称signin/,如果后期项目需要修改路由,只需修改这里的路由地址,其他的都可以不用修改了
path("article/" , views.front_article, name="article"), # 定义路由
]
两种传参方式的选择不同,效果如下: