Skip to content

url传参

url中的参数设置

Django中有两种的url的传参方式:

  • url后边用?开始,键与值用等号连接,每对键值用&号进行区分,如:http://localhost:8000/index?name=jlc&age=24

    这种方式就是在url中进行参数的传递,其传递的值会传递到我们的服务器上面去(通过浏览器传递了nameage参数给我们的网站后台)

    url中设置参数,我们需要在views.py文件中进行参数的配置:

    py
    from django.shortcuts import render
    from django.http import HttpResponse  # 专门去返回一些字符串的包
    
    # 创建视图函数
    def index(request):
        name = request.GET.get('name', '')
        age = request.GET.get('age', 10)   # 设置了默认值为10
        # 我们需要将传递的值进行一个打印
        print(name, age)
        return HttpResponse('hello django')

    同时在子路由的urls.py也需要进行一定的配置:

    py
    from django.urls import path
    from .views import index  # 将视图函数进行导入
    
    urlpatterns = [
        path('index', index),  # 调用index函数
    ]

    这样,我们在网站中通过url传递的参数:

    http://localhost:8000/index?name=jlc&age=24就可以传递到后端中了

  • 路由传参使用分格符分开,如:

    http://localhost:8000/index/jlc/24

    通过这种方式获取url传递的参数,我们需要对views.py文件中进行以下的配置:

    py
    from django.shortcuts import render
    from django.http import HttpResponse  # 专门去返回一些字符串的包
    
    # 创建视图函数
    def index(request, name, age):
        # 我们需要将传递的值进行一个打印
        print(name, age)
        return HttpResponse('hello django')

    同时在子路由的urls.py也需要进行一定的配置:

    py
    from django.urls import path
    from .views import index  # 将视图函数进行导入
    
    urlpatterns = [
        # 设置需要传递参数的类型
        path('index/<str:name>/<int:age>', index),  # 调用index函数
    ]
    
    # django的url的变量类型
    # 字符串类型,匹配任何非空字符串,但不包含斜杠:<str:name>
    # 整形,匹配0和正整数:<int:age>
    # 注释类型,后缀或附属等概念:<slug:day>
    # uuid格式的对象:<uuid:uid>   uuid类似的格式是:xxx-xx-xx

url传参时,建议使用第二种传参方式,第二种传参方式比较简单明了


视图View

视图对应在Django中是views.py这个文件

视图的工作流程:

  1. 用户使用浏览器向网站发送请求,传入一个request参数

    我们可以通过print(dir(request))来查看request有哪些具体的方法

    request常见的对象方法有:

    • request.GET:获取url上以?形式的参数
    • request.POST:获取post提交的数据
    • request.path:请求的路径,如:127.0.0.1/test/1,这个参数就是/test/1/
    • request.method:获取请求的方法,如:getpost
    • request.COOKIES:获取请求过来的cookies
    • request.user:请求的用户对象,可以来判断用户是否登录,并获取用户信息
    • request.session:一个既可以读又可以写的类似与字典的对象,表示当前会话
    • request.META:一个标准的python字典,包含所有的HTTP首部,具体的头部信息取决于客户端和服务器,里面保存的都是一些http协议
  2. 对用户的请求做出相应的处理handler

  3. 将处理后的数据返回格浏览器,返还一个response对象

常用的返回对象:

  • HttpResponse:可以直接返回一些字符串内容

    导入方式:from django.http import HttpResponse

  • render:将数据在模板中渲染并显示

    导入方式:from django.shortcuts import render

  • JsonResponse:返回一个json类型,通常用于与前端进行ajax交互

    导入方式:from django.http import JsonResponse

视图面向对象的写法:(之前写的都是基于函数的写法,但是通过面向对象类的方法进行编写,对后续扩展更加有利,可阅读性也更强),小案例:将路由传递过来的参数显示到网页上面去:

py
from django.views.generic import View  # 导入通用摄图
from django.http import HttpResponse

class Message(View):  # 类继承于View
    def get(self, request):   # 重写类当中的方法
        naem = request.GET.get('name', '')
        age = request.GET.get('age', 10)
        return HttpResponse('My name is {}, age is {}'.format(name,age))

同时在子路由的urls.py也需要进行一定的配置:

py
from django.urls import path
from .views import Message  # 将视图函数进行导入

urlpatterns = [
    path('message', Message,as_view()),
]

在网址上输入urlhttp://localhost:8000/message?name=jlc&age=24回车后,在网页上就会渲染以下的字符串:My name is jlc, age is 24


restful规范

restfulurl定位资源,通过一个url地址可以让我们知道这个地址所要提供的功能是什么,如:127.0.0.1/add/user我们可以看出这个url要做的是添加一个用户

目前的网站的架构是前后端分离的,浏览器一开始先去访问前端服务器,前端的服务器接收到用户的请求后,会继续访问后端的服务器(网站服务器),如用户发送了一个get请求给前端服务器,前端服务器会发送一个http请求给后端,内容为get user 1,后端服务器会访问我们的数据库sql,目前,后端服务器只需要提供给前端服务器API(数据接口),一开始存在API定义的方式不统一,不利于前端的使用,后面推出了restful规范,这个规则是提供给前端工程师去看的,有了这个规范,方便前端工程师去调用接口

restful常用的方法

  • Get:获取资源的使用,如查看一个网页
  • Post:提交资源的使用,如注册一个用户提交的内容
  • Put:修改资源,如用户修改自己的基本信息
  • Delete:删除资源,如用户注销账号

模板Template

Template模板可以动态的生成HTML网页,包括部分html代码和特殊的语法

一般Template模板存放在templates目录(该目录与manage.py同级)中,通过在项目的SettingsTEMPLATESDIRS列表中添加对应的路径即可,如:os.path.join(BASE_DIR, 'TEMPLATES')

Template与视图的绑定

我们在tempaltes的文件夹下创建一个index.html的文件,文件的内容如下:

html
<!DOCT html>
<html lang="en">
<head>
	<meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>hello django</h1>
</body>
</html>

在应用文件里的views.py进行绑定:

py
from django.shortcuts import render  # render的主要功能是返回一个html页面
from django.views.generic import View

class Index(View):
    def get(self, request):
        # 绑定视图
        return render(request, 'index.html')

在应用文件的子路由中进行绑定:

py
from django.urls import path
from .views import Index  # 将视图函数进行导入

urlpatterns = [
    path('', Index,as_view()),
]

在项目文件的根路由中将子路由绑定进来:

py
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('app.urls')),
]

这样就能加载index.html文件中的内容了

Template展示渲染的数据

html中以为标示,在双括号中传入视图中传入的数据

html中渲染一个用户传入过来的值:

我们在tempaltes的文件夹下创建一个index.html的文件,文件的内容如下:

html
<!DOCT html>
<html lang="en">
<head>
	<meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>hello {{ name }}</h1>
</body>
</html>

在应用文件里的views.py进行绑定:

py
from django.shortcuts import render  # render的主要功能是返回一个html页面
from django.views.generic import View

class Index(View):
    def get(self, request, name):
        # 绑定视图
        return render(request, 'index.html', {'name': name})

在应用文件的子路由中进行绑定:

py
from django.urls import path
from .views import Index  # 将视图函数进行导入

urlpatterns = [
    path('<str:name>', Index,as_view()),
]

在项目文件的根路由中将子路由绑定进来:与之前步骤一致

这样我们在url中输入localhost:8000/jlc,传入的值就会渲染到html页面中,在网页中进行展示,实现了在页面中进行传参

变量与标签

变量:使用进行包裹,我们后端渲染过来的数据,用双大括号来包裹,如:

内置标签:用{% %}大括号,左右各一个百分号包裹,常见的内置标签有:

txt
{% for %}  {% endfor %} 遍历输出的内容,前面部分表示开始循环,后面部分表示结束循环
{% if %}  {% elif %}  {% endif %}  对变量进行条件判断
{% url name args %}   引用路由配置名
{% load %}  加载django的标签库  如加载静态库:{% load static %}

{% static static_path %}   读取静态资源
{% extends base_template %}   模板继承
{% block data %}   {% endblock %}  重写父模板的代码
{% csrf_token %}  跨域密钥,一般在表单(form)中使用

for标签模板

txt
forloop.counter     从1开始计算获取当前索引
forloop.counter0    从0开始计算获取当前索引
forloop.revcounter  索引从最大数递减到1
forloop.revcounter0 索引从最大数递减到0
forloop.first       当前元素是否是第一个
forloop.last        当前元素是否为最后一个
empty               为空的情况

变量与标签的简单使用:

在应用文件里的views.py进行变量的声明和传递:

py
from django.shortcuts import render  # render的主要功能是返回一个html页面
from django.views.generic import View

class Index(View):
    def get(self, request):
        list_data = range(3)
        # 绑定视图
        return render(request, 'index.html', {'list_data': list_data})

index.html的文件中使用传递过来的列表数据,我们可以对其做循环:

html
<!DOCT html>
<html lang="en">
<head>
	<meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    {% for item in list_data %}
    	<li>{{ item }} -- {{ forloop.counter }} -- {{ forloop.counter0 }} -- {{ forloop.revcounter }} -- {{ forloop.revcounter0 }}</li>
    
    	{% if forloop.first %}
    		this is first
    	{% elif forloop.last %}
    		this is last
    	{% endif %}
    	
    	{% empty %}
    		当前列表没有元素
    {% endfor %}
</body>
</html>

在应用文件的子路由中进行绑定:

py
from django.urls import path
from .views import Index  # 将视图函数进行导入

urlpatterns = [
    path('', Index,as_view()),
]

在项目文件的根路由中将子路由绑定进来:

py
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('app.urls')),
]

在浏览器中的结果显示为:

txt
0 -- 1 -- 0 -- 3 -- 2
this is first
1 -- 2 -- 1 -- 2 -- 1
2 -- 3 -- 2 -- 1 -- 0
this is last

静态文件的配置

静态文件:CSS样式文件,Javascript文件,Image图片文件

templates文件夹下,一般只是存放.html的文件,静态文件不会存放在这个地方,需要在项目的根目录下创建static文件夹(与templates文件夹同级),用来存放静态文件

同时在settings.py文件中进行相关的配置(需要在settings.py文件下另起一个配置项),其内容为:

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

其中DIRS表示我们的文件夹

简单案例:将我们的图片资源可以在浏览器中进行显示

  • 我们先要在static资源文件夹中创建一个图片文件夹images,再将需要的图片拖到文件夹之下

  • index.html的文件中写入静态文件标签{% load staticfiles %},使静态文件可以在模板中进行显示

    html
    {% load staticfiles %}
    <!DOCT html>
    <html lang="en">
    <head>
    	<meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <img src="{% static 'images/1.png' %}">
    </body>
    </html>
  • 其他文件的操作可以参考之前的配置

过滤器

html模板中,对于渲染过的数据进行二次处理操作,过滤器就是用来处理这些数据模板引擎中使用的函数

常用的内置过滤器
过滤器使用(用两个大括号包裹)说明
addvalue|add:10value的值加10
datevalue|date:"Y-m-d H:i:s"把日期格式按照规定的格式进行显示
cutvalue|cut:'-'value中的-删除
catfirstvalue|catfirstvalue的首字母大写
defaultvalue|default:'xx'值为False时使用默认值xx
default_if_nonevalue|default_if_none:'xx'值为None时使用默认值xx
dictsortvalue|dictsort:'key'值值为字典列表,按照key排序
dictsortreversedvalue|dictsortreversed:'key'值为字典列表,按照key反向排序
firstvalue|first返回列表中的第一个索引值
lastvalue|last返回列表中的最后一个索引值
floatformatvalue|floatformat:2保留小数点后2位小数
joinvalue|join:"-"使用-进行连接
lengthvalue|length返回值的长度
divisblebyvalue|divisibleby:2如果值可以被2整除即返回true
length_isvalue|length_is:'2'如果长度值为2即返回true
safevalue|safe将字符串中的html标签在前端安全展示,不添加这个过滤器时只会显示前端代码这行字符串
randomvalue|random随机返回列表中的一个值
slicevalue|silce:'2'截取前两个字符
slugifyvalue|slugify值小写,单词用-分隔
uppervalue|upper字符串大写
urlizevalue|urlize字符串中的链接可点击
wordcountvalue|wordcount字符串中的单词数
timeuntilvalue|timeuntil距离当前日期的天数和小时数(未来时间)

简单使用:

  • views.py文件中进行参数的声明和传递

    py
    from django.shortcuts import render  # render的主要功能是返回一个html页面
    from django.views.generic import View
    import datetime   # 引入时间
    
    class Index(View):
        def get(self, request):
            data = {}
            data['count'] = 20
            data['time'] = datetime.datetime.now()
            data['cut_str'] = 'hello-boy'
            data['first_big'] = 'hello django'
            data['result'] = False
            data['if_none'] = None
            data['dist_list'] = [{'name': 'jlc', 'age': 24}, {'name': 'JLC', 'age': 20}]
            data['float_num'] = 3.1415926
            data['array'] = range(3)
            data['html_str'] = '<div style="background-color:red;width:50px;height:50px"></div>'
            data['url_str'] = '请看 www.baidu.com'
            data['feature'] = data['time'] + datetime.timedelta(days=5)
            return render(request, 'index.html', data)
  • index.html的文件中进行编写对应的过滤器

    html
    <!DOCT html>
    <html lang="en">
    <head>
    	<meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        add: {{ count|add:10 }}
        <br>
        time: {{ time|data:"Y-m-d H:i:s" }}
        <br>
        cut: {{ cut_str|cut:"-" }}
        <br>
        catfirst: {{ first_big|capfirst }}
        <br>
        default: {{ result|default:"空" }}
        <br>
        default_if_none: {{ if_none|default_if_none:"none是空" }}]
        <br>
        dictsort: {{ dict_list|dictsort:"age" }}
        <br>
        dictsortreversed: {{ dict_list|dictsortreversed:"age" }}
        <br>
        first: {{ dict_list|first }}
        <br>
        last: {{ dict_list|last }}
        <br>
        floatformat: {{ float_num|floatformat:2 }}
        <br>
        join: {{ array|join:"-" }}
        <br>
        length: {{ dict_list|length }}
        <br>
        divisibleby: {{ count|divisibleby:2 }}
        <br>
        length_is: {{ dict_list|length_is:3 }}
        <br>
        safe: {{ html_str|safe }}
        <br>
        random: {{ array|random }}
        <br>
        slice: {{ html_str|slice:":6" }}
        <br>
        urlize: {{ url_str|urlize }}
        <br>
        wordcount: {{ first_big|wordcount }}
        <br>
        timeuntil: {{ feature|timeuntil }}
    </body>
    </html>
  • 网页中的结果显示为:

    txt
    add: 30
    time: 2024-09-04 11:09:20
    cut: helloboy
    catfirst: Hello django
    default: 空  // 如果在views.py中传入的result值为True,网页中就展示True
    default_if_none: none是空  // 如果传入的if_none值为1,网页中就展示1
    dictsort: [{'age': 20, 'name': 'JLC'}, {'age': 24}, 'name': 'jlc']
    dictsortreversed: [{'age': 24, 'name': 'jlc'}, {'age': 20, 'name': 'JLC'}]
    first: {'age': 24, 'name': 'jlc'}
    last: {'age': 20, 'name': 'JLC'}
    floatformat: 3.14
    join: 0-1-2
    length: 2
    divisibleby: True
    length_is: False
    random: 2   // 随机返回数组中的某个值
    slice: <div s
    urlize: 请看 www.baidu.com   // 后面的链接变的可以点击跳转
    wordcount: 2
    timeuntil: 4 日 23 小时

    if_none的值None和空字符串‘’,是不等价的,传入‘’,在网页中不显示默认值,显示的内容是空字符串(不显示东西),也就是说空字符串不为空

自定义过滤器

Django中有些内置的过滤器可能不太符合我们的应用场景,我们往往需要自定义过滤器,自定义过滤器的步骤为:

  1. 在应用文件下创建一个Python Package的包,命名为templatetags

  2. 在这个包中创建一个Python文件,命名为myfilter.py

  3. myfilter.py中进行自定义过滤器的编写

    py
    from django import template
    
    # 自定义过滤器
    register = template.Library()
    @register.filter
    def test_filter(value, args):  # value是用户传入的值
        return value * args
  4. 在模板中去使用:

    html
    {% load myfilter %}   <!--导入自定义的过滤器-->
    <!DOCT html>
    <html lang="en">
    <head>
    	<meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    	自定义: {{count|test_filter:3}}
    </body>
    </html>

    编写完自定义过滤器后,需要进行后端的重启,这个自定义过滤器才能生效


其他常用模板

JinJa2

JinJa2是一套模仿Django模板的模板引擎,由Flask开发者开发,使用场景与Django相似,速度较快,被广泛使用

JinJa2提倡让Html设计者和后端Python开发工作分离

模板的配置
  1. 我们需要先创建一个Django项目,在项目的应用文件中创建一个子路由urls.py,其内容为:

    py
    from django.urls import path
    from .views import Index
    urlpatterns = [
        path('', Index.as_view())
    ]

    在根路由与子路由进行绑定:

    py
    from django.contrib import admin
    from django.urls import path, include
    urlpatterns = [
        path('admin/', admin.site.urls),
        path('', include('app.urls')),
    ]
  2. 在项目的根目录下创建两个文件夹:templatesstatic,在templates文件夹中创建一个index.html文件,其文件内容为:

    html
    <!DOCT html>
    <html lang="en">
    <head>
    	<meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    	自定义: {{count|test_filter:3}}
    </body>
    </html>
  3. 在项目文件夹下的settings.py下做相应的配置

  4. 在应用文件夹内创建一个Python文件:base_jinja2.py

  5. 在终端中下载jinja2的插件:pip install jinja2

  6. 在文件base_jinja2.py中进行以下的配置:

    py
    from jinja2 import Environment
    from django.contrib.staticfiles.storage import staticfiles_storage
    from django.urls import reverse
    
    def environment(**options):
        env = Environment(**options)
        env.globals.update({
            'static': staticfiles_storage.url,
            'url': reverse
        })
        return env
  7. 在应用文件的视图views.py文件中创建视图函数:

    py
    from django.shortcuts import render
    from django.views.generic import View
    
    class Index(View):
        def get(self, request):
            data = {'name': 'jlc', 'age': 24}
            return render(request, 'index.html', data)
常用的系统过滤器
过滤器说明
safe渲染时不转义
capitalize把值的首字母转换为大写,其他字母转换为小写
lower把值转换成小写的形式
upper把值转换成大写的形式
title把值中每个单词的首字母都转换成大写
trim把值的首尾空格去掉
striptags渲染前把值中所有的HTML标签都删掉
自定义过滤器

直接在应用文件下创建一个myfilter.py的文件,在这个文件下编写自定义过滤器:

py
def test(value, args):
    return value * args

base_jinja2.py文件中配置自定义过滤器:

py
from jinja2 import Environment
from django.contrib.staticfiles.storage import staticfiles_storage
from django.urls import reverse
from .myfilter import test

def environment(**options):
    env = Environment(**options)
    env.globals.update({
        'static': staticfiles_storage.url,
        'url': reverse
    })
    env.filters['test'] = test
    return env

在项目文件的settings.py文件中的TEMPLATES中修改配置信息:将BACKEND改为:

py
'BACKEND': 'django.template.backends.jinja2.Jinja2'
'OPTIONS': {
    'CONTEXT_PROCESSORS': [
        ...
    ],
    'environment': 'app.base_jinja2.environment'#只是使用系统过滤器不需要配置
},

通过以上的配置(不管是系统过滤器还是自定义过滤器都需要进行配置),我们jinja2自定义的过滤器就可以使用了,在index.html文件,其文件内容为:

html
<!DOCT html>
<html lang="en">
<head>
	<meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
	{{ name|title }}  <!---系统过滤器:将首字母进行大写-->
	<br>
    {{ age|test(2) }}   <!---自定义过滤器:乘2-->
</body>
</html>
配置静态文件

static文件夹内创建一个css样式文件:test.css,其内容为:

css
* {
    background-color: red;
}

Django模板中在html文件中导入静态文件需要在顶部写{% load staticfiles %},但是在Jinja2中不需要,我们可以直接在<link>标签中进行导入:

html
<!DOCT html>
<html lang="en">
<head>
	<meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
	<link rel="stylesheet" href="/static/test.css">
</body>
</html>

Mako

Mako模板比Jinja2有更快的解析速度和更多的语法支持,可以允许开发者在HTML中随意书写Python代码

模板的配置
  1. 下载makopip install mako

  2. 配置路由,子路由,settings.pystatictemplates文件参考Jinja2的配置

  3. 在应用文件夹下创建mako的配置文件:base_render.py,其内容为:

    py
    from mako.lookup import TemplateLookup
    from django.template import RequestContext
    from django.conf import settings
    from django.template.context import Context
    from django.http import HttpResponse
    
    def render_to_response(request, template, data=None):
        context_instance = RequestContext(request)
        path = settings.TEMPLATES[0]['DIRS'][0]
        lookup = TemplateLookup(
        	directories=[path],
            output_encoding='utf-8',
            input_encoding='utf-8'
        )
        mako_template = lookup.get_template(template)
        
        if not data:
            data = {}
            
        if context_instance:
            context_instance.update(data)
        else:
            context_instance = Context(data)
         
        result = {}
        for d in context_instance:
            result.update(d)
            
        result['csrf_token'] = '<input type="hidden" name="csrfmiddlewaretoken" value="{}" />'.format(request.META.get('CSRF_COOKIE', ''))
        return HttpResponse(mako_template.render(**result))

枚举文件

枚举是一个数据类型,相当于一个字典,我们在这个字典中去选择相应的键,这个键对应着一个值

一般在app应用文件夹下创建枚举文件consts.py,该文件的内容格式如下:

py
from enum import Enum

class MessageType(Enum):
    info = 'info'
    warning = 'warning'
    error = 'error'
    danger = 'danger'
    
# 定义内容和颜色
MessageType.info.label = '信息'
MessageType.warning.label = '警告'
MessageType.error.label = '错误'
MessageType.danger.label = '危险'

MessageType.info.color = 'green'
MessageType.warning.color = 'orange'
MessageType.error.color = 'gray'
MessageType.danger.color = 'red'

python自身是没有枚举类型的,在python3.4之后引入了枚举包Enum

之后在编写我们的视图函数views.py(在应用程序文件夹下):

py
from django.shortcuts import render
from django.view.generic import View
from .consts import MessageType   # 导入当前路径下consts.py文件中的类

# 定义类视图
class Message(View):
    def get(self, request, message_type):
        data = {}
        # 用户路由传参传过来值的类型,传入的枚举类型必须是已经被定义的,否则进行异常处理
        try:
            # 接收message_type
            message_type_obj = MessageType[message_type]
        except:
            data['error'] = '没有这个消息类型'
            return render(request, 'message.html', data)
        
        # 获取用户传递过来的message的值
        message = request.GET.get('message', '')
        if not message:
            data['error'] = '消息不可为空'
            return render(request, 'message.html', data)
        data['message'] = message
        data['message_type'] = message_type_obj
        return render(request, 'message.html', data)

在模板文件夹中创建一个message.html的文件:

html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
{% if error %}
    <h3>error: {{ error }}</h3>
{% else %}
    <span style="color:{{message_type.color}}">{{message}}</span>
{% endif %}
</body>
</html>

在应用文件夹中创建子路由urls.py

py
from django.urls import path
from .views import Message

urlpatterns = [
    path('message/<str:message_type>', Message.as_view()),
]

在项目文件夹下的主路由中进行绑定子路由:

py
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('app.urls')),
]

在浏览器中输入localhost: 8000/message/danger?message=aaa

会在网页中渲染对应枚举类型颜色的aaa样式

Released under the MIT License.