python django框架的路由传参,重定向,登陆,前后端不分离开发传参,过滤器,模板标签,继承,自定义过滤器和标签

1 路由传参

在主urls中传递参数,注意格式

from django.contrib import admin
from django.urls import path
from django.conf.urls import url, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('one/', include('one.urls')),
    path('two/', include('two.urls'), {'time': True}),
    path('three/', include('three.urls'))
]

此处我们给名为two的app传入一个name的字典,然后我们到名为two的app下定义函数

from django.shortcuts import render,redirect,reverse
from django.http import HttpResponse
from django.template.loader import get_template
import time
# Create your views here.
def test(request,**kwargs):
    return redirect(reverse('test1'))# 根据named动态获取路由
    message = 'hello world!'
    if kwargs.get('time'):
        message += '<br/>' + time.asctime(time.localtime(time.time()))
    return HttpResponse(message)

def test1(request,**kwargs):
    message = 'hello world! test1'
    if kwargs.get('time'):
        message += '<br/>' + time.asctime(time.localtime(time.time()))
    return HttpResponse(message)

这里我们使用**kwargs接收传过来的参数,然后在函数中使用kwargs.get()方法接收,然后在里面传入键,就会得到值。这样就完成了路由方式的传参。

2重定向

from django.urls import path
from . import views

urlpatterns = [
    path(r'test/', views.test),
    path(r'test1/', views.test1,name='test1'),
    path(r'index/<username>/<password>',views.index)
]

我们直接在路由中给重定向的函数中传入第三个参数,即给他定义一个名字

from django.shortcuts import render,redirect,reverse
from django.http import HttpResponse
from django.template.loader import get_template
import time
# Create your views here.
def test(request,**kwargs):
    return redirect(reverse('test1'))# 根据named动态获取路由
    message = 'hello world!'
    if kwargs.get('time'):
        message += '<br/>' + time.asctime(time.localtime(time.time()))
    return HttpResponse(message)

def test1(request,**kwargs):
    message = 'hello world! test1'
    if kwargs.get('time'):
        message += '<br/>' + time.asctime(time.localtime(time.time()))
    return HttpResponse(message)

这里我们又引入一个方法 reverse,然后直接需要在重定向的函数中,直接ruturn redirect(reverse(‘test1’)).该方法会根据路由中的name动态的获取重定向的路由。

3前后端不分离开发

前后端不分离开发,即把前端代码和前后端交互,以及数据库交互放在一起,那么我们就需要注册一个templates文件,来存放前端html文件夹。首先在settings里面找到

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

我们将template路径放在’DIRS’中,注意格式!
然后在项目文件夹下新建一个templates文件夹,然后创建与app数量相同且与app名称相同的文件夹(主要是为了方便管理)。
然后在同名文件夹中新建模板文件(html文件):

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>test</title>
</head>
<body>
<div>欢迎登陆:<span style="color: red">{{ username }}</span></div>
</body>
</html>

然后在views文件中:

def template_1(request,**kwargs):
    username = 'zjj'
    #render是一个函数,第一个参数传入请求对象request,第二个传入模板地址,第三个参数是传递给模板的一个字典,通过key取值(该参数可省略,即无参数传递时)
    return render(request, 'two/template_1.html', {'username': username})

这里我们使用的是render,而不是Httpresponse,这里的第二个参数用来引入模板html,然后第三个参数用来给模板文件传参,注意:这里使用的键值对格式的字典。
效果:
在这里插入图片描述
当然,这里不仅可以传字符串,还可以传很多值:
在这里插入图片描述

def fun():
    return 'function'
class Student:
    def __init__(self,name):
        self.name = name
    def study(self):
        return 'good'
def template_var(request,**kwargs):
    stu = Student('yige')
    context = {'str_var': 'string',
               'fun_var': fun,
               'student_study_var':stu.study,
               'student_var':stu,
               'list_var': [1,2,3],
               'dict_var':{'a':1,'b':2},
               'int_var':1,
               'tuple_var':('a','b'),
               }
    return render(request, 'two/template_var.html', context)

然后在模板文件中:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>模板变量</title>
</head>
<body>
    <ul>
        <li>这个整数变量:{{ int_var }}</li>
        <li>字符串变量:{{ str_var }}</li>
        <li>函数变量:{{ fun_var }},这里会通过key得到value函数体</li>
        <li>方法变量:{{ student_study_var }}</li>
        <li>实例对象变量:{{ student_var }}</li>
        <li>字典变量:{{ dict_var }}</li>
        <li>元组变量:{{ tuple_var }}</li>
        <li>列表变量:{{ list_var }}</li>
    </ul>
<ul>
    <li>访问对象属性:{{ student_var.name }}</li>
    <li>访问对象方法:{{ student_var.study }}</li>
</ul>
<ul>
    <li>访问列表元素:{{ list_var.1 }}</li>
    <li>访问元组元素:{{ tuple_var.1 }}</li>
    <li>访问字典元素:{{ dict_var.a }}</li>
</ul>
</body>
</html>

这里需要注意的是最后三排

    <li>访问列表元素:{{ list_var.1 }}</li>
    <li>访问元组元素:{{ tuple_var.1 }}</li>
    <li>访问字典元素:{{ dict_var.a }}</li>

这里在定位元素的时候,并不是使用的[],而是使用的. 这里需要注意
效果:
在这里插入图片描述
静态文件的操作:
我们在完成模板html文件的创建后,还需要创建静态文件,比如css,js,图片等,首先当前项目目录下创建,如图
在这里插入图片描述
然后加入到settings目录中,不然我们找不到它

STATIC_URL = '/static/'

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

直接添加在最下方,这样我们才可以找到它,
模板文件引入方式:

{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>静态文件</title>
    <link rel="stylesheet" href="{% static 'css/static_file.css' %}">
</head>
<body>
<img src="{% static 'image/page1.png' %}" alt="">
<script src="{% static 'js/static_file.js' %}"></script>
</body>
</html>

首先在顶端使用{% load static%},表示引入静态文件,名字基于你的命名,然后下面才可以使用{% static ‘’%}来进行文件的引入。
效果:
在这里插入图片描述

4登陆操作

这里我们直接传值尝试,就不用数据库交互了
路由信息:

from django.urls import path
from . import views

urlpatterns = [
    path(r'test/', views.test),
    path(r'test1/', views.test1,name='test1'),
    path(r'template_1', views.template_1),
    path(r'template_var',views.template_var),
    path(r'index/<username>/<password>',views.index)
]

这里最后一排,定义路由的方法需要注意,
视图信息:

def index(request, username, password, **kwargs):
    username_db = 'zjj'
    password_db = '123'
    message = '请先登录'
    context = {
        'username': message,
        'password': message
    }
    if username == username_db and password == password_db:
        context['username'] = username
        context['password'] = password
    return render(request, 'two/index.html', context)

我们直接给路由传递用户,和密码,再看模板

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>首页</title>
</head>
<body>
    <dl>
        <dt>用户信息</dt>
            <li>用户名:{{ username }}</li>
            <li>密码:{{ password }}</li>
    </dl>
</body>
</html>

这里我们直接传递一个context,如果传递太多值,建议使用这种方法,不会看起来很臃肿。
效果:
在这里插入图片描述

5过滤器

过滤器就是模板文件对函数中传递过来的值进行过滤。具体值都可以查

from django.http import HttpResponse, HttpResponseNotFound
from django.shortcuts import redirect, render
from datetime import datetime
# Create your views here.
def filter_var(request):
    context = {'str_var': 'THIS is Python',
               'now': datetime.now,
               'name': '<span style= color:"red">yige</span>',
               }
    return render(request, 'three/filter_var.html', context)

模板:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>过滤器</title>
</head>
<body>
    <div>
        <li>未过滤 {{  str_var  }}</li>
        <li>转小写{{ str_var|lower }}</li>
        <li>获取第一个值{{ str_var|first }}</li>
        <li>最后一个值{{ str_var|last }}</li>
        <li>链式调用:模拟较规范的英文句子{{ str_var|lower|capfirst}}</li>
        <li>去除指定字符(过滤器使用参数){{ str_var|cut:' '}}</li>
        <li>没处理的时间: {{ now }}</li>
        <li>处理一下,date是日期,time是时间: {{ now|date }}</li>
        <li>time过滤器: {{ now|time }}</li>
        <li>xx年xx月xx日 xx:xx:xx24小时制 {{ now|date:'Y年m月d日 H:i:s' }}</li>
        <li>xx:xx:xx12小时制{{ now|time:'H:i:s'}}</li>
        <li>{{ name }}</li>
    </div>
</body>
</html>

这里是使用方法
在这里插入图片描述
效果:
在这里插入图片描述
当然我们可以自己动议过滤器,比如这里的cut:

def cut(str,re):
    return ''.join(str.split(re))

这里我们传入一个字符串,然后使用split方法切割字符串,然后用.join方法拼接起来返回出去,那么我们这个方法就需要传入用什么标志来切割,我们这里传入的是空格,那么出来的字符串就不会有空格。

6模板的标签

6.1if语句

首先定义一个函数:

from django.http import HttpResponse, HttpResponseNotFound
from django.shortcuts import redirect, render
class User:
    def __init__(self, name, age, sex='男'):
        self.name = name
        self.age = age
        self.sex = sex
def template_label(request):
    user = User('周健', 26, 5)
    context = {
        'user': user
    }
    return render(request, 'three/template_label.html', context)

这里我们将值传入模板后,来进行模板标签条件语句的操作:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div class="if-box">
    <h3>if模板标签</h3>
        <p>当前用户信息:</p>
    <ul>
        <li>
            姓名:{{ user.name }}
            {% if user.name == '周健' %}
                good boy
            {% endif %}
        </li>
        <li>
            年龄:{{ user.age }}
            {% if user.age > 10 and user.age < 30 %}
                年轻小伙
            {% endif %}
        </li>
        <li>
            性别:
            {% if user.sex == 0 %}{% elif user.sex == 1 %}{% else %}
                未知
            {% endif %}
        </li>
    </ul>
</div>
</body>
</html>

使用格式:{% if%} {%endif%}
在这个中间可以插入elif,else等,和平常语句差不多,但是要加上{% %},语法才通顺。

6.2for语句与多层for语句

for语句可以对传入模板的参数进行遍历,然后forloop里面保存着循环的一些信息,可以直接.调用属性,forloop有很多属性,如first(第一个),last(最后一个),counter(从1开始的序号),recouter(倒过来的序号),counter0(从0开始的序号),recounter0(倒过来的从0开始序号)。
视图函数:

from django.http import HttpResponse, HttpResponseNotFound
from django.shortcuts import redirect, render
# Create your views here.
def template_label(request):
    context = {
        'course': ['python', 'linux', 'mysql', 'redis'],
        'course_info': ('难点', '周边'),
        'html_text': '<div>有html标签的噢<div>'
    }
    return render(request, 'four/template_label.html', context)

这里传入了几个值,然后再模板文件中,进行for操作,注意:for语句是双标签,不过可以直接for + tap键,快捷键

   <div class="box">
        {{ course }}
    </div>
    <div>forloop里面保存着循环的一些信息,可以直接.调用属性</div>
    <ul>
        {% for i in course %}
            <li>{{ forloop.revcounter }}.{{ i }}</li>
        {% endfor %}
    </ul>
    <ul>
        {% for i in course %}
                <li>{% if forloop.revcounter0 > 2 %}
                    <li> {{ i }}</li>
                {% endif %}
                </li>
            {% endfor %}
    </ul>

这里进行了遍历,然后在参数前面加上序号,这里是反向从1开始的序号,然后下面是对序号做判断,如果大于2才能显示.
效果:
在这里插入图片描述
多层for循环的使用:

<ul class="more-for-box">
    <h3>多层for循环</h3>
    <ul>
        {% for i in course %}
            <li>
                {{ i }}
                {% for j in course_info %}
                    {% if forloop.parentloop.first %}
                        <li style="color: rebeccapurple">
                            {{ j }}<input type="text">
                        </li>
                        {% else %}
                        <li>
                            {{ j }}<input type="text">
                        </li>
                    {% endif %}
                {% endfor %}
            </li>
        {% endfor %}

    </ul>
</ul>

这里嵌套了两层for语句,其实就和python的多层for循环一样,需要注意的就是注意格式{%%},和{{}}的区别,一个是函数使用,一个是接收参数用。
效果:
在这里插入图片描述

6.3url标签

可以实现跳转的标签,是需要在路由文件中添加名字
路由文件:

from django.contrib import admin
from django.urls import path
from . import views

urlpatterns = [
    path(r'template_label', views.template_label, name='template_label'),
    path(r'url_var/<var>', views.url_var, name='url_var'),
    path(r'index/<value>', views.index)
]

这里给两个函数另外命了名。然后

<ul>
    <h3>url模板标签</h3>
    <p>{% url 'template_label' %}</p>
    <p>
        应用:
        <a href="{% url 'template_label' %}">跳转</a>
        <a href="{% url 'url_var' '2' %}">携带参数跳转</a>
    </p>
</ul>

另外这里,还有一个携带参数跳转

def url_var(request, var):
    return render(request, 'four/url_var.html', {'var': var})

这里我们的函数有一个传入参数,然后上面的模板文件中,只需要在后面名字参数后面,添加一个字符串参数,就能把这个参数传递给目标函数,然后跳转的页面就是携带参数的页面。

6.4with标签

with标签可以将变量赋予给新的变量。

<div>
    <h3>with标签</h3>
    {% with course.0 as firstc %}
        <p>{{ firstc }}</p>
    {% endwith %}
</div>

这个用的地方不是很多。

6.5 autoscape模板标签

可以实现页面的自动转义的取消和开启,之前不是说到django是自己带有自动转义,该标签可以取消自动转义。这里的html_text是有标签符号的字符串。

<div class="autoscape-box">
    <h3>outoscape模板标签</h3>
    <ul>
        <li>
            原数据:{{html_text}}
        </li>
        <li>
            过滤器取消转义: {{ html_text|safe }}
        </li>
        <li>
            autoscape取消自动转义:
            {% autoescape off %}
                {{ html_text }}
            {% endautoescape %}
        </li>
    </ul>
</div>

效果:
在这里插入图片描述
这里不加任何处理,就会直接显示

,但是如果加上过滤器处理或者autoscape处理取消自动转义,就可以取消自动转义,但是这样并不安全。

7模板的继承

这样可以省去很多工作量,字类模板可以将父类模板的css,js,等等都可以继承过来,不用自己再写。方法:

{% extends 'four/indexbase.html' %}

比如这里父类模板名字为indexbase.html,然后删除所有子类模板的初始代码,只需要一行代码,就可以将父类所有的东西继承过来。但是没有页面是完全一样的,所以有时候我们需要修改一些东西,所以需要使用block标签。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>父类</title>
    {% block css %}

    {% endblock %}
</head>
<body>
{% block header %},
{% endblock %}
good
{% block center %}
    yxyy
{% endblock %}
</body>
</html>

这里我们在父类中定义了许多个block标签,每一个标签里面的参数都不同,这是为了在继承的时候能区分开,注意这里的上下顺序会延续到子类中,就是说不管子类中写的上下顺序是如何的,最后呈现出来的效果只与父类中的上下顺序一致。然后我们就可以在子类中定义了。

{% extends 'four/indexbase.html' %}

{% block css %}
    直接写就行!
{% endblock %}
{% block center %}
    xxxxxxx
{% endblock %}

{% block header %}
    {{ block.super }}
    <div>yes</div>
{% endblock %}

这里我们需要注意的是,如果我们不定义block,即子类中没有block,直接在子类中加入代码,django是不会渲染的,所以对于哪些是重复的,哪些需要修改要做提早的规划。
然后如果我们添加了block标签,但是我们除了自己修改东西外,我们还想保留父类原来的东西,就需要使用{{ block.super}},如上图代码中所示,这样就可以即保留父类信息,又可以添加信息。

8自定义过滤器

首先自定义过滤器的路径设置,第一步在项目文件夹下新建一个名为common的python包(注意:是python包,python package)(名字可任取),然后在common里面再建一个python包,名字必须是templatetags,注意:名字必须是这个。然后在里面建一个python文件(不是包)。效果如图:
在这里插入图片描述
建立完成后,在settings里面注册它,
在这里插入图片描述
进入新建的sex_change文件,自定义过滤器其实就是新建一个函数,但是这个函数要被html文件接收并且能使用,就需要一些手段。首先导入django里面的template,再得到注册对象。

from django import template
register = template.Library() #得到注册对象

@register.filter
def change(value, args):
    return '未知' if value >= len(args) or value < 0 else args[value]

这里先不管别的,单看这个函数,有两个传入值,一个value,一个args。
然后一个三目运算符,判断如果value的值大于等于args的长度或者小于0,就返回’未知’,否则就返回args中value项。然后使用register.filter进行注册,使用装饰器形式。然后怎么用呢?首先在html文件里面导入我们自定义过滤器所在的文件名

{% load sex_change %}
<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <ul>
        <li>姓名:{{ user.name }}</li>
        <li>年龄:{{ user.age }}</li>
        <li>性别:{{ user.sex | change:sex_li }}</li>

这里在第一排使用{% load 文件夹名%},注意这里不是过滤器的名字,是所在的文件名。
然后在使用的时候还是和过滤器一样。

def custom_filter(request):
    user = User('zj', 18, 1)
    context = {
        'user': user,
        'sex_li': ['男', '女'],
        'label_index': 1,
        'label_list': ['python', 'c', 'c++'],
        'format_string': '1',
        'course': ['a', 'b', 'c', 'd', 'e']
    }
    return render(request, 'five/custom_filter.html', context)

那么我们给change过滤器传入了2个参数,第一个参数是user.sex,然后第二个参数是sex_li.那么把这两个参数传入函数中,会返回sex_li中的1项,即女。

9自定义标签

自定义标签和自定义过滤器形式一样,所以我们直接在sex_change文件里直接进行注册。

@register.simple_tag
def current_time_str():
    return 1

这里需要注意的是,修饰器是@register.simple_tag,而不是@register.filter,当然函数的定义方式是不变的。

<li>当前时间:{% current_time_str %}</li>

当然,自定义标签也可以传入参数,但是传入的参数只能是在views函数中传入html文件的context,那么我们如何接收来自views函数的参数?

@register.simple_tag(takes_context=True)
def current_time_context(context):
    return context['format_string']

这里传入修饰器的参数,takes_context=True.
这样就可以获取context中的参数,当然需要获取context,这里主要是注意格式,即使用键值对形式,用键取值。

另外,比如我们每一次html文件中,每一次遍历参数,都需要使用for标签进行遍历,然后endfor标签结束。那么我们能不能将它封装起来,然后每一次使用,只需要传入参数即可。
首先我们单独定义一个html文件来封装for标签方法。
在这里插入图片描述
然后在sex_change文件中(就是之前我们定义的那个),新建一个自定义标签。

@register.inclusion_tag('five/for_item.html', takes_context=True)
def for_item(context, key):
    li = context.get(key)
    return {'key': li}

这里在修饰器的第一个参数中传入封装for标签的html地址。那么我们的这个标签如何使用呢?

<ul>
    {% for_item 'course' %}
</ul>

这里我们只传入一个course列表,然后调用for_item标签,标签通过context.get(key),获取course的值,key就是传入的course,然后return{‘key’ : li},这里会将这个字典返回到第一个参数的地址,也就是html文件中,然后html文件中的key就是该字典中的键,那么就会获取li,然后开始遍历后,输出。

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值