django路由与视图

路由用于将URL映射到相应的视图函数,使得用户可以通过URL访问到相应的页面或数据

path函数的用法/路由须知

path函数涉及四个参数 route,view我在这里主要讲后两种

路由须知:
我们在路由中使用视图时,在要在前面加上引用

from . import views

route参数
必须是字符串类型,用来匹配域名
比如输入 admin/ 就会匹配 http://127.0.0.1:8000/admin 地址

view参数
用于设置视图函数,后面会讲到

name参数
为路由进行命名,后面会讲到

URL转发(设置分路由)

URL转发可以把路由分散到其他文件夹中,避免都在主文件夹中,造成堵塞。[wazhantest/urls.py ],转化为副项目名 [fruits/urls.py]。

urls.py,需要自己创建。复制以下代码:

from . import views
from django.urls import path 
urlpatterns = [
	path('sub',views.shop1) #在该域名下设置视图函数
]

定义视图函数view.py

from django.http import HttpResponse
def shop1(request):
	return HttpResponse("你好呀!我是大帅哥")

之后,打开主项目的urls.py文件,在里面加上以下内容:

from django.urls import includes
path('fruits/',include('fruits.urls')) #第一个参数是app的名字,第二个是域名的名字

之后运行服务器即可。

设置路由变量

当调用的视图对象过多时,可以设置路由变量来方便维护,路由变量可以支持

类型用法
字符型(str)可以匹配除了 " \ " 以外的字符串,时默认值
整形(int)匹配0以及任何整数
slug型匹配任意ASCll字母,数字,连字符和下滑线,如代表最新商品展示信息的网页路由地址 Dood-2022-7-7-1
uuid型匹配一个格式化的UUID唯一序列号,所有字符必须小写,并且用"-"连接

下面来看一个案例:
在根路由的views.py的urlpatterns路由列表中加入以下代码:

from django.http import HttpResponse
def MPage(request,year,day,mouth):
    return HttpResponse("我在"+str(year)+"-"+str(day)+"-"+str(mouth)+"号真帅")

在根路由的urls.py下加(在urlpatterns中)

from wanzhantest.views import MPage 
path('<int:year>/<int:mouth>/<slug:day>',MPage)

完成后运行服务器,输入网址 http://127.0.0.1/2023/3/7 就会出现我们输入的url了
进入网址:点我进入
在这里插入图片描述

路由命名+视图中使用模板

创建一个新的应用 background 应用:

python manage.py startapp background

路由命名需要path的一个参数name实现

命名路由是指给 URL 路由分配一个名称。这个名称可以在应用程序的其他部分中引用(比如html中),而不用直接使用 URL 地址 (从一个模板中跳到另一个模板中的时候用 {% url })

在分路由的urls.py中加入代码:

path('1/',views.index,name='index'),
path('r/',views.register,name='register')

我们已经把"r/“命名为register(相当于把"register相当于”/")
在分路由的view.py中加入:

def index (request):
	return HttpResponse("你好呀!我是大帅哥1")
def register (request):
	return render(request,'register.html')  #render函数在这里用来说明视图如何

为了调用模板,我们要在backgroud目录下建立templates子目录
并在templates目录下创建html文件register.html
在这里插入图片描述
把这些复制过去,这里把a中的跳转更改为路由名,点击jump to 就可以跳转到这个页面(函数)了。
“{%url ‘register’ %}” 为路由名(就是我们命名的/r,可以相当于打注释)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>注册管理模板</title>
</head>
<body>
  <br>
  <h1 style = "text-align:center"><a href = "{%url 'register' %}">jump to</a></h1>

</body>
</html>

最后,完成主项目的urls.py的总路由

path('back',include('background.urls'))

运行服务器,如果出现找不到模板问题
在这里插入图片描述
需要在根项目的setting.py中的INSTALLED_APPSTEMPLATES
在这里插入图片描述
BASE_DIR/“templates”
在这里插入图片描述

命名路由空间

命名路由空间可以解决 在不同app下使用相同的路由名导致url反向解析出错
命名空间使得即使在不同的app中定义了相同的url名称,也能够正确的实现 url 反向解析。

为路由命名会在这种情况下引发问题。我们需要使用命名空间

假设我们在 background的目录fruits的目录 下有:

两者的urls.py:(输入的url不同,但是路由命名相同)

|background|:
在这里插入图片描述
|fruits|:

在这里插入图片描述

两者的函数(在视图函数中,路由名相同)相同,都为:
在这里插入图片描述

根路由urls.py
在这里插入图片描述
之后运行服务器,输入:
127.0.0.1/app1/ww 会发现:

在这里插入图片描述
显然,这并不是我们想要的结果。
django在反向解析URL时,会在项目全局顺序搜素,当查找到第一个name指向的URL时,便立即返回。所以上面访问不同URL,反向解析得到相同的path。

就是为了防止在不同app下使用相同的路由名所引发的问题,我们才使用命名空间
用include 来管项目URL,并进行namespace(命名空间)

在根项目的目录下修改代码为:(在include函数中修改)

    path('app1/',include('background.urls',namespace='app1')),
    path('app2/',include('fruits.urls',namespace='app2')),

在background/urls.py修改代码:(声明命名空间)

app_name = 'app1'

在这里插入图片描述
在fruits/urls.py修改代码:(声明命名空间)

app_name = 'app2'

在这里插入图片描述
之后,修改视图函数:
语法为:namespace:name

在这里插入图片描述
在这里插入图片描述
就完成了
在这里插入图片描述

在这里插入图片描述

反向解析(回环地址)

每个视图函数都有一个和其相对应的路由,但是如果它们之间的匹配关系发生了变化,那么与之对应的访问地址也会跟着发生改变,这是极其不方便的

反向路由的主要作用是简化代码编写和维护,并且使得更改路由规则时的代价更小
因为我们更改url的时候,其他的程序不会进行改动

Django 提供了不同的方式来实现 URL 反向解析:
1.在模板层使用 {% url %} 模板标签;
2.在视图函数的 Python 代码中:使用 reverse() 函数;我们主要讲解第二点

我们现在在根路由的urls.py中输入:

path('i/',include(('fruits.urls'),namespace='index1'))

解释一下include参数:
在这里插入图片描述

之后,在fruits.urls文件中输入:

path('',views.Shop,name='Show'),
path('Show1/',views.ShowGoods,name='Show2')

解释一下:第一个参数是一个空字符串 ‘’ 。这表示该路由将匹配来自父URL配置的任何请求。也可以用来匹配空url
在这里插入图片描述

随后,添加视图函数

def Shop(request):
	url = reverse('index1:Show2')
	print(url)
	return HttpResponseRedirect(url)

def ShowGoods(request):
	return HttpResponse("荔枝大卖,最后98天!")

在这里插入图片描述

下面是解释:

第一行路由配置path(‘’,views.Shop,name=‘Show’)表示当用户访问站点根目录时,会调用名为Shop的视图函数,并将其命名为Show。

第二行路由配置path(‘Show1/’,views.ShowGoods,name=‘Show2’)表示当用户访问/Show1/路径时,会调用名为ShowGoods的视图函数,并将其命名为Show2。

在Shop视图函数中,使用了reverse方法,通过参数index1:Show2获取到了名为Show2的视图函数所对应的URL地址。然后,又使用HttpResponseRedirect方法将请求重定向到该地址,在浏览器中展示给用户的结果就是ShowGoods视图函数返回的内容:荔枝大卖,最后98天! (reverse函数会实现路由空间:路由名的反向解析)

总的来说,这段代码实现的功能是:当用户访问站点根目录时,自动跳转到/Show1/路径,并显示ShowGoods视图函数的返回结果。

完成了,登录网址127.0.01/i/Show1即可:点我进入
PS:因为回环地址的出现,当我们输入空字符串的时候(也就是127.0.0.1/i)也会返回一样的结果

加载静态资源

更改静态资源的时候要先清除cookies

Ctrl + F //清除cookies

django默认是没有办法加载js,css,图片之类的静态资源,我们需要创建一个static文件夹,用来专门放静态资源
1.我们需要在setting.py中加入下面这段代码:

STATICFILES_DIRS = [
 os.path.join(BASE_DIR,"static")
]

在这里插入图片描述
2.创建一个static文件夹,把静态文件放在里面
在这里插入图片描述
3.用下面的命令来加入

{% load static %} //在模板中的 <head> 中加入
 
<link href="{% static 'css/style.css' %}" rel="stylesheet"/>  //css样式
 
<script src="{% static "js/jquery-3.1.1.min.js" %}" type="text/javascript"></script> //js样式
 
<img src="{% static "email.png" %}" alt="图片加载失败"> //图片


4.案例

<!DOCTYPE html>
<html lang="en">
<head>
    {% load static %}   //必须要有
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>导航</title>
</head>
<body>
  <nav>
    <ul>
      <li><a href="{%url 'register2' %}">首页lkj</a></li>
      <li><a href="#">关于我们</a></li>
      <li><a href="#">联系我们</a></li>
        <p>图片的测试</p>
    <img src="{% static "3.png" %}" alt="">  //图片
    </ul>
  </nav>
</body>
</html>

回环地址

就是改a标签。比如<a href="index.html">

<a href="{% url 'index' %}">Index</a>
urlpatterns = [
    path('', views.index, name='index'),
    # 其他URL模式...
]
def index(request):
    return render(request, 'index.html')

视图函数

基本的视图函数我们已经使用了很多次了,现在我们来讲解一下第二部分

关于响应码

状态码功能说明
100该响应码表示请求已经成功,下面会返回响应结果,它只是一个临时状态
200请求成功
204服务器完成请求,而且无需返回内容
301永久指向确定发网页地址
302指向临时的网页地址
400访问url有误,服务器不处理该请求
404网页不存在或url无效
500互联网出错

render函数(使用模板)

之前我们就使用过render函数来返回响应,事实上,如果我们项目的网页太多的话,会导致调整时不够灵活,因此我们会放到templates模板下,而这就是render函数的作用
render函数的使用格式如下:

from django.shortcuts import render #使用前需要导入
render(request,template_name)

参数说明:
request:必选参数,表示url请求访问信息
template_name:必选参数,用来指定模板文件的名称,也可以认为时一个静态的网页文件比如 index.html

context:可选参数,用于对模板内的变量赋值
content_type:可选参数,响应内容的数据格式,默认为text/html
status:响应状态码,默认为200
using:设置加载模板的模板引擎名称,用于解析模板,生成响应的网页内容

总之,我们把写好的html文件放到template中再完成对应的路由和视图函数就行

视图的重定向

当我们从正在访问的视图中访问到另一个视图的时候,比如返回到网站的首页,就可以使用重定向的方法。我们使用Django内置的HttpResponseRedirect方法,
使用HttpResponseRedirect需要导入:

from django.http import HttpResponseRedirect

再根文件下增加如下视图函数

def NewURL(request):
    return HttpResponseRedirect('http://www.ifeng.com') #跳转到凤凰网

加入路由函数:

path('4/',NewURL)

这样,当我们输入网址127.0.0.1/4/的时候就会跳转到凤凰网:点我进入

错误提示视图

一般django会在你输入错误的网址的情况下显示一个错误视图:
在这里插入图片描述
一般而言,错误视图是给开发人员看,在真正的运行时我们要关闭这个界面,在根目录下的setting.py的 DEBUG更改为False,以及ALLOWED_HOST=[‘*’] 以防止出现安全问题

自定义错误提示视图

默认的视图错误信息都是英文的,而一般的中文网站希望提供中文的错误信息来处理404视图,500视图等。
在这里插入图片描述

我们需要进入setting.py文件下:修改如下两个参数
DEBUG=False # 关闭调试模式
ALLOWED_HOSTS=[‘*’] # * 代表允许所有的URL访问服务器,默认为 []
在这里插入图片描述
之后,我们创建一个模板用来存html文件,下面时404.html文件的代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>404错误提示信息</title>
</head>
<body>
<h1>无法访问,页面找不到--{{URL_path}}</h1>
</body>
</html>

{{URL_path}}为模板变量,用来接受错误提示视图中的变量值

view.py中完成对全局404配置函数的书写:

def page_not_found(request, exception):
	#自定义错误视图函数必须提供request,exception函数
    path = {'URL_path': request.path}
    return render(request, '404.html', path, status=404) #只能用于404错误

在路由文件urls.py中设置全局路由:(这里注意了,必须写到urlpatterns的[ ]的外面)

handler404='wanzhantest.views.page_not_found'

在这里插入图片描述
最后,我们输入一个不存在的路由地址:(比如127.0.0.1/ikunikunjojojojo),就会出现
在这里插入图片描述
PS:完成这节学习后,最好调回原版的错误提示界面,以方便我们的学习

HttpRequest对象

Django会把http数据包封装为HttpRequest对象并将其转递给每个视图函数的第一个参数request

在PyCharm中点击“终端”按钮并输入python manage.py shell以打开Django Shell

HttpRequest对象的方法

get_host方法

该方法用来获取请求访问的服务器的地址或域名,可以带上端口号
我们在视图函数view.py中加上:

def index(request):
    host=request.get_host() #获取请求方法的服务器或域名
    html='一个简单的返回信息!'+host 
    response = HttpResponse(html, status=200)
    response.charset = 'utf-8' #很重要,用来转化为中文
    return response

同时,加上路由:

from wanzhantest.views import index
path('1/',index)

之后,输入网址127.0.0.1/1,我们就可以知道请求的服务器了:点我进入

get_port()方法

该方法用来获取端口号,我们现在简单改一下代码

def index(request):
    host = request.get_host()
    port = request.get_port() #获得请求访问的服务器的地址
    html = '一个简单的返回信息!' + host +'<br>' + 'get_port()方法获得:' + str(port)
    #'<br>'是一个换行符
    response = HttpResponse(html, status=200)
    response.charset = 'utf-8'
    return response

现在,我们输入网址 http://127.0.0.1:80/1/就会出现:(80时默认端口)
在这里插入图片描述

PS:值得一提的是,当我们运行django服务器的时候如果输入
python manage.py runserver 0.0.0.0:800 代表我们把本地的端口改为了800
这时我们就要输入http://127.0.0.1:800/1/

get_full_path()方法

该方法用于获得完整的url地址,改动代码

def index(request):
    host = request.get_full_path()
    port = request.get_port() #获得请求访问的服务器的地址
    html = '一个简单的返回信息!' + host +'<br>' + 'get_port()方法获得:' + str(port)
    response = HttpResponse(html, status=200)
    response.charset = 'utf-8'
    return response

返回:
在这里插入图片描述

is_secure()方法

该方法用于判断知否是安全的访问(https)如果是,返回True,否则,返回False
改动代码:

def index(request):
    host = request.is_secure()
    port = request.get_port() #获得请求访问的服务器的地址
    html = '一个简单的返回信息!' + str(host) +'<br>' + 'get_port()方法获得:' + port
    response = HttpResponse(html, status=200)
    response.charset = 'utf-8'
    return response

会返回:
在这里插入图片描述

文件上传

这一章我们完成"文件上传"的操作,我们在这里可以看到前端和后端的联动
第一步"建立模板":
在template文件夹下建立 upload.html 文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>上传文件模板</title>
</head>
<body>
   <form enctype="multipart/form-data" action="/uploadfile/" method="post">
       {% csrf_token %}  <!--防CSRF攻击-->
   <input type="file" name="newfile" />
   <br/>
   <input type="submit" value="上传文件"/>
   </form>
</body>
</html>

参数解析
enctype属性: 用来指定上传文件给服务器之前对表单数据进行的编码方式,这里必须指定为 “multipart/form-data” 表示不对字符进行编码,支持通过文件上传的方式将数据发给服务端。
action属性: 用来指定需要上传的目标的URL,这里指定了/uploadfile 地址 ,必须在项目路径下建立 upuploadfile 字目录路径,即建立一个空的目录
method属性:用来指定post值(必须指定),表示使用post方法提交表单
{% csrf_token %}: 用来防止攻击,后面会细讲

第二步,完成视图函数:

import os
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
def upload_file(request):
    if request.method == "POST":                # 请求方法为POST时,可以读取文件数据
        newFile =request.FILES.get("newfile", None)  #获取上传文件数据,若没有文件则返回None
        if not newFile:                         #如果没有文件
            return HttpResponse("提交无效,没有文件上传!",status=200) #返回无效操作提示,终止视图函数执行
        to_path=open(os.path.join(BASE_DIR,'uploadfile',newFile.name),'wb+') #打开特定的文件进行二进制的写操作
        for chunk in newFile.chunks():      # 分块写入文件
            to_path.write(chunk)
        to_path.close()
        return HttpResponse("上传成功!")
    else:
        return HttpResponse('非表单提交访问!')

第三部,在视图函数中调用上传模板的视图函数(主要用于返回模板)

def login1(request):
	return render(request,'upload.html') #返回模板给访问的浏览器

最后,完成路由

path('file/',login1), #使用template目录下的upload.html视图
path('uploadfile/',upload_file) #调用上传文件的视图函数

我们输入网址http://127.0.0.1/file/进行确认:点我进入
在这里插入图片描述
点击上传文件,并选中一个图片进行上传
PS:我们建立的 uploadfile目录必须放在项目的根目录下,而不是同名的应用下
| 在这里插入图片描述

文件下载

Django提供4种下载文件的方式:HttpResponse,StreamingHttpResponse,FileResponse以及JsonResponse
使用这4种方式时都需要导入:

from django.http import HttpResponse,StreamingHttpResponse,FileResponse,JsonResponse

我们主要讲最简单的HttpResponse
我们需要在根目录下创建一个给用户下载的文件夹,里面放入一张图片,即创建目录"download"里面放个图片

第二部,我们创建一个下载的模板download.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>下载文件</title>
</head>
<body>
   <br>
   <div class="col-md-4"><a href="{% url 'index:download' %}" rel="external nofollow" >点击下载文件</a></div>
</body>
</body>
</html>

第三步,建立下载的视图函数

from django.http import Http404
def download(request):
    filename='cats.jpg'
    try:
        download_path = open(os.path.join(BASE_DIR, 'download',filename ), 'rb') #读取指定地址下的文件
        print(download_path)
        d=HttpResponse(download_path)
        d['content_type']='application/octet-stream'
        d['Content-Disposition']='attachment;filename='+filename   #下载文件
        return d
    except:
        raise Http404('下载文件'+filename+'失败!')

完成路由:

from wanzhantest.views import download
 path('download1/',download)

最后输入网址(http://127.0.0.1/download1,居然直接下载了:点我下载
在这里插入图片描述

视图类

视图类是另一种使用视图的方法,视图类比起普通的定义视图会显得更直观

内置显示视图类

内置显示视图主要将模型数据,模板展示在用户访问的浏览器上,Django为此提供了5种视图类:View,TemplateView,RedirectView,ListView,DetailView

View视图类

View类用来响应各种来自前端的请求。
需要导入:(视图类在使用时必须实例化,下面会说)

from django.views import View

第一步,我们在background/view.py文件下增加视图:

from django.views import View
class firstClassView(View):
	def get(self,request):
		return HttpResponse(request.path)
	def post(self,request):
		if request.POST!=None:
			return HttpResponse('Post请求访问结果=有值')
		else:
			return HttpResponse('Post请求访问结果=无值')

第二步:在urls.py下添加视图(必须使用as_view()实例化)

path('Go1/',views.firstClassView.as_view()),

第三步:在根路由urls.py下添加视图:

path('bg/',include('background.urls'))

最后,运行服务器输入网址http://127.0.0.1/bg/Go1/ 点我进入
因为从地址栏访问都是get请求,所以会返回输入的地址
在这里插入图片描述

模板视图类

TemplateView类用于模板处理响应与展示的视图类,需要导入

from django.views.generic.base import TemplateView

该类的父类是:TemplateResponseMixin类,查看父类的方法是:
选中TemplateView并按下 Ctrl + B可以跳转到该类的定义处,可以在这里查看父类
在这里插入图片描述
这是其父类的属性

第一步,在background应用下增加如下视图类

class T_View(TemplateView):
	template_name = 'T_home.html'  #设置模板
	def get_context_data(self, **kwargs): #重写方法
		context=super().get_context_data(**kwargs) #继承方法
		context['address']='天津' #传递变量及值
		context['name']='刘瑜'#传递变量及值
		context['oet']='猫猫' #传递变量及值
		return context

第二步,加入模板

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>模板视图的模板</title>
</head>
<body>
<table border="1" cellpadding="5">
  <tr>
    <th>地址:</th>
    <th>{{address}}</th>
  </tr>
  <tr>
    <td>姓名:</td>
    <td>{{name}}</td>
  </tr>
  <tr>
    <td>宠物:</td>
    <td>{{pet}}</td>
  </tr>
</table>
</body>
</html>

第三步,加入路由在background/urls.py处加入(必须使用as.view()实例化)

path('v1/',views.T_View.as_view()),

第四步,在根路由中加入

path('bg/',include('background.urls')),

最后,输入网址http://127.0.0.1/bg/v1/可以看到:点我进入
在这里插入图片描述

重定向视图类

RedirectView用来完成视图的重定向
在该类中,我们在 127.0.0.1/bg/3/ 网页中跳转到 127.0.0.1/bg/3/k=10 (也就是show方法处)
该类还是需要导入:

from django.views.generic.base import RedirectView

该类同样拥有四个属性:

第一步:我们在background/view.py下加入:

class R_View(RedirectView):
    pattern_name ='index2:www'   #指定重定向到应用的 命名空 间及对应的 命名路由
    query_string =True          #允许请求路由传递查询参数值给重定向路由地址
    
 def login(request): #先访问的网页
	return render(request,'login.html')
	
def show(request):  #重定向到的网页(可以是模板)
    return HttpResponse("数据操作成功!")

第二步:加入路由:

path('3/', login, name='first'),
path('f/', R_View.as_view(), name='Redirect'),
ath('ff/', show, name='www'),

第三步:在根路由下加入

path('bg1/',include('background.urls','first'),namespace='index2')

第四步:加入模板

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>RedirectView</title>
</head>
<body>
    <br>
    <a href="{%url 'index2:Redirect' %}?k=10">Go</a>
</body>
</html>

最后,我们输入网址 http://127.0.0.1/bg/3/ 点我进入
在这里插入图片描述
点击 GO
在这里插入图片描述

列表视图类

使用前需要导入:

from django.views.generic import ListView

第一步:在background/views.py文件下:

from django.views.generic import ListView 
from fruits.models import goods #从模型中导入 goods类
class ListView1(ListView):
	model = goods # 指向 goods 模型
	context_object_name = 'MyGoods'  #把 goods 模型命名为 MyGoods 并传递该模板(数据传递给模板的变量名)
	template_name = 'ListView.html' #指定模板

第二步:加入模板(background下的模板)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
   <h2>水果店信息</h2>
    <ul>
        {% for one in MyGoods %}
            <li>名称:{{ one.name }} 数量:{{ one.number}} 单价:{{ one.price}}</li>
        {% endfor %}
    </ul>
</body>
</html>

第三步:background.urls 加入子路由:(必须使用as.view()实例化)

from . import views
path('s/',views.ListView1.as_view(),name='Show')

第四步:加入总路由

path('bg/',include('background.urls'))

最后,输入网址http://127.0.0.1/bg/s/ : 点我进入
在这里插入图片描述

一条记录视图类

DetailView也是用于获取模型的类,它于ListView类唯一区别就是一次只可以处理一条记录
使用该类需要引用:

from django.views.generic import DetailView

第一步:在background/views.py文件下加入

from django.views.generic import DetailView
from fruits.models import goods
class DetailView1(DetailView):
	model = goods #指定模型
	template_name = 'DetailView.html' #指定模板
	slug_field = 'name' #指定需要查询的字段
	slug_url_kwarg = 'name' #于slug_field一致,用于指定URL请求访问的变量名
	pk_url_kwarg = 'pk' #指定了 URL 中捕获主键的关键字参数的名称,对应下面的URL

第二步,加入模板:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>DetailView</title>
</head>
<body>
   <h1>名称{{goods.name}}</h1>
   <h2>数量{{goods.number}}</h2>
   <h2>单价{{goods.price}}</h2>
</body>
</html>

第三步:完成子路由:(必须使用as.view()实例化)

from . import views
path('<pk>/<name>.html',views.DetailView1.as_view(),name='One') #使用<pk>值表示商品的主键值

注意了,URL参数后面加上 .html 用来限制变量输入的内容,以防止输入太多无关值(只要没用特殊的输入,输入什么都行)

http://127.0.0.1/bg/2/ikunaaaa.html
http://127.0.0.1/bg/2/ikunbbbbhtml
http://127.0.0.1/bg/2/ikuncccc.html
等这些(没有特殊值的,都是可以的)

第四步:完成根路由

path('bg/',include('background.urls'))

之后我们输入网址:http://127.0.0.1/bg/4/爱坤.html :点我进入
(正好对应了数据库中 id=4 name=爱坤 的数据)
在这里插入图片描述
如果我们输入 http://127.0.0.1/bg/4/爱坤dddddd.html (数据库中没有 id=4 name=爱坤dddddd 的数据),会出现
在这里插入图片描述
可见,输入正确的pk值(主键值,默认为id),也是可以的,如果输入完整的url可以更好(因为有时name参数值相同)的定位

再试一次,输入 http://127.0.0.1/bg/2/ikun.html (我们建的表中有两个name=ikun的参数):点我进入
在这里插入图片描述
可见,跳出了第二条记录

内置编辑视图类

对于上网展示的数据,往往需要增,删,改,查等操作,比如提交个人信息给服务端,服务器通过django给数据库进行操作,Djano有四种内置编辑视图类用来实现该功能,分别是:FromView,CreateView,UpdateView,DeleteView

验证数据类

FromView主要用于验证数据,响应验证结果,显示表单数据。(显示提交成功或者出错)
使用前需要导入:

from django.view.generic.edit import FormView

第一步,在background/urls.py中加入:

class GoodsForm(forms.ModelForm):
    class Meta:
        model=goods   #指定模型
        fields='__all__' #获取模型goods的所有属性(字段)
class FormView1(FormView):
    template_name ='FormView.html' #调用视图对应的模板
    form_class =GoodsForm          #用于指定表单类
    success_url ='../OK/'       #用于指定提交成功的重定向路由地址
def ShowOK(request):
    return HttpResponse('数据提交成功!')

第二步,加入模板:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>表单类显示及提交</title>
</head>
<body>
   <form method="post">
   {% csrf_token %}
    <table>
        <tr><th>水果名称</th><td>{{ form.name }}</td></tr>
        <tr><th>数   量</th><td>{{ form.number }}</td></tr>
        <tr><th>单   价</th><td>{{ form.price }}</td></tr>
        <tr><td colspan="2"><input type="submit" value="提交"/></td></tr>
    </table>
    </form>
</body>
</html>

第三步,加入子路由:(必须使用as.view()实例化)

path('fv/',views.FormView1.as_view()),
path('OK/',views.ShowOK,name='OK')

第四步,加入总路由:

path('bg/',include('background.urls'))

最后,输入网址http://127.0.0.1/bg/fv/进行查看:(图中的数据是自己输入的)点我进入
在这里插入图片描述
在这里插入图片描述
不会修改数据库中的数据

新建记录类

CreateView用于指定模型新增记录并返回新建成功提示,需要导入

from django.views.generic.edit import CreateView

第一步,在background/views.py中加入:

class CreateView1(CreateView):
    initial = {'name':'西瓜','number':10,'price':1.2} #初始化的值,会直接显示在界面里
    template_name = 'CreateView.html'  #指定模板的名字
    #form_class =GoodsForm   #指定表单对应的模型类,方法一
    model =goods             #用model、fields指定模型对象,方法二
    fields =['name','number','price'] #指定视图需要的字段
    success_url = '../OK/'     # 指定提交成功路由,

第二步,加入模板:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>为模型对应表增加记录</title>
</head>
<body>
    <h2>请新增水果记录</h2>
    <form method="post">{% csrf_token %}
    {{ form.as_p }}
    <input type="submit" value="保存">
</form>
</body>
</html>

第三步,加入子路由:(必须使用as.view()实例化)

path('OK/',views.ShowOK,name='OK'),
path('c/',views.CreateView1.as_view())

第四步,加入总路由:

path('bg/',include('background.urls'))

最后,我们输入网址 http://127.0.0.1/bg/c/ 会出现 点我进入
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

更新记录类

UpdateView类用于通过表单界面为模型修改数据
使用前需要导入:

from django.views.generic.edit import UpdateView

第一步,在background/urls.py中加入:

class UpdateView1(UpdateView):
    template_name ='UpdateView.html' #指定需要更新操作的模板名称
    model =goods             #指定需要更新的模板名
    fields =['name','number','price'] #指定表单需要显示的字段
    slug_field = 'name'     #指定需要修改的数据的字段(比如姓名)
    slug_url_kwarg ='name'  #指定URL传递变量给slug_field,联合查询
    context_object_name ='goods' #指定传递给模板的模型变量名
    success_url ='../OK/'              #指定提交成功路由
    
    #注意了 我们在之前的代码中使用过了一次success_url = '.../OK/'
    #因此,这里应该更改为 OK/ 否则还是使用 ../OK/ (开发中必须注意)

第二步,加入模板:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>更新记录视图类调用模板</title>
</head>
<body>
    <h2>水果名为:{{goods.name}}</h2>
    <form method="post">{% csrf_token %}
    {{ form.as_p }}
    <input type="submit" value="更新">
</form>
</body>
</html>

第三步,加入子路由:(必须使用as.view()实例化)

from django.urls import path,re_path  #多导入一个re_path
from . import views
path('cc/<name>',views.UpdateView1.as_view()),

第四步,加入总路由:

path('bg/',include('background.urls'))

最后,我们输入网址 http://127.0.0.1/bg/cc/香翅捞饭 会出现 点我进入

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
如果表中有两条同名的记录,会爆出异常,可以向URL中传递唯一的id字段值来解决

删除视图类

DeleteView用于删除模型的记录,使用前需要导入

from django.views.generic.edit import DeleteView

第一步,在background/urls.py中加入:

class DeleteView1(DeleteView):
    template_name ='DeleteView.html' #指定需要删除操作的模板
    model = goods                    #指定需要删除操作的模板名
    context_object_name = 'goods'  # 指定传递给模板的模型变量名
    success_url = 'OK/'  # 指定提交成功路由

第二步,加入模板:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>删除记录视图调用</title>
</head>
<body>
    <form method="post">{% csrf_token %}
    <p>需要删除该记录么?"{{ goods.name }}"?</p>
    <input type="submit" value="删除提交">
    </form>
</body>
</html>

第三步,加入子路由:(必须使用as.view()实例化)

path('<pk>.html',views.DeleteView1.as_view())

第四步,加入总路由:

path('bg/',include('background.urls'))

最后,我们输入 http://127.0.0.1/bg/1.html (序数代表商品的 id ):点我进入
在这里插入图片描述
在这里插入图片描述
我已经删除了第一二条记录啦!

在这里插入图片描述

内置日期视图类

Django支持7个内置日期视图类:
ArchiveView:
YearArchiveView(本章重点介绍):指定需要按年份查询的日期字段,把复合条件的表返回到网页中
使用前需要导入:

from django.views.generic.dates import YearArchiveView

第一步,我们在 background/model.py 下 新加入水果报废模型

class scrap(models.Model):   #水果报废记录模型
    idGoods = models.SmallIntegerField(primary_key=True)#商品ID号
    name = models.CharField(max_length=20)              #报废水果名
    number = models.FloatField()                        #报废数量
    price = models.DecimalField(max_digits=10, decimal_places=3)#报废价格
    BackDate= models.DateTimeField()                    #报废时间

并且创建一些数据:(随便创建就行)
在这里插入图片描述

第二步,加入视图类

from django.views.generic.dates import YearArchiveView
from background.models import scrap
class YearView(YearArchiveView):
    allow_empty = True    #允许表单数据为空
    allow_future = True   #表示表单允许显示当前日期后面的日期记录
    #model =scrap          #指定模型
    date_field = 'BackDate'             #指定查找的日期字段
    year_format = '%Y'                  #指定URL年份变量传递的格式为数字
    queryset =scrap.objects.all()       #查询模型的所有记录
    #context_object_name ='T_scrap'     #传递模型变量给模板
    template_name = 'YearFindView.html' #指定模板
    make_object_list = True             #传递查询结果object_list变量给模板
    #paginate_by =5                     #指定5条记录为一页

第三部,建立模板

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>年查找视图</title>
</head>
<body>
    <h1>水果退货记录</h1>
    <h3>商品编号  水果名称  数量 单价  退货日期</h3>
    <ul>
    {% for date in object_list %}
        <li>{{ date.idGoods }}  {{ date.name}}  {{ date.number}}  {{ date.price}}  {{ date.BackDate}}</li>
    {% endfor %}
    </ul>

</body>
</html>

第四步,完成子路由

path('aa/<int:year>.html',views.YearView.as_view())

我们可能要注释掉这个路由# path(‘/.html’,views.DetailView1.as_view(),name=‘One’),
第五步,完成总路由

path('bg/',include('background.urls')),

最后,输入网址http://127.0.0.1/bg/aa/2023.html 会返回:点我进入
在这里插入图片描述

前端集成Markdown格式文件

视图与数据库事务

事务为数据库同步多次访问操作提供安全可靠的操作的处理功能。使用 transaction模块 进行事务处理。使用前需要导入:

from django.db import transaction
from django.db.models import F

比如我们想要从一个表中 “拿出” 一些给另一个表,我们就可以使用事务操作。
第一步:我们先在 fruits/models,py中加入新的模型:

class Detail(models.Model): #明细表
    name = models.CharField(max_length=20)
    num = models.FloatField()
    cost = models.DecimalField(max_digits=10, decimal_places=3)

别忘了把改变提交到数据库中去

python manage.py makemigrations fruits
python manage.py migrate

我们向数据库中加入一些数据:
在这里插入图片描述
现在,我们想要把 id=1 的 ikun1商品 放3个到上架表中
第二步,在 fruits/view.py 加入代码:

from fruits.models import Detail, goods #首先需要导入这两个模型
def trans1(request):
    goNum=3  #上架商品的数量
    try:
        with transaction.atomic():  #使用事务
            Detail.objects.filter(id=1).update(num=F("num")-goNum) #库存表中减少三个ikun1
            goods.objects.create(name='ikun1',number=goNum,price=2) #上架表中转入3个 ikun1 商品
    except Exception as e:
        return HttpResponse("水果上架失败"+str(e))
    return HttpResponse("水果上架成功!")

第三步,加入子路由:

path('t/',views.trans1)

第四步,加入总路由:

path('fruits/',include('fruits.urls')),

最后,输入网址http://127.0.0.1/fruits/t/查看:点我进入
在这里插入图片描述
现在我们查看数据库,Detail表中减少了三个数据
在这里插入图片描述

goods表新增了三个数据
在这里插入图片描述

  • 23
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值