day04
网页伪静态
将动态网页伪装成静态网页,从而提升网页被搜索引擎收录的概率
案例:
1.在urls.py中添加
# 定义test函数,为了演示方便,直接在urls.py中添加函数了
def test(request):
from django.shortcuts import HttpResponse
return HttpResponse('这是个伪静态')
#添加路由
在urlpatterns中添加path('test.html', test)
2.浏览器输入http://127.0.0.1:8000/test.html
页面显示'这是个伪静态'
准备
1.创建Django项目day58,应用app01
2.settings.py中
MIDDLEWARE中注释掉django.middleware.csrf.CsrfViewMiddleware
TEMPLATES中修改'DIRS': [os.path.join(BASE_DIR, 'templates')],
3.配置静态文件
1.手动在Django项目中创建static目录,并放置jquery和bootstrap文件
2. settings.py中配置
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static')
]
视图层
1.视图函数的返回值问题
'''视图函数必须返回HttpResponse对象'''
注意HttpResponse是一个类
class HttpResponse(HttpResponseBase):
pass
def render():
return HttpResponse(...)
def redirect(to, *args, permanent=False, **kwargs):
redirect_class = HttpResponsePermanentRedirect if permanent else HttpResponseRedirect
return redirect_class(resolve_url(to, *args, **kwargs))
"""入门三件套最后返回的都是HttpResponse对象"""
案例:
1.urls.py中修改
from app01 import views
urlpatterns = [
path('admin/', admin.site.urls),
path('index/', views.index)
]
2.views.py中添加
from django.shortcuts import render,HttpResponse,redirect
def index(request):
return None
3.启动Django,浏览器输入 127.0.0.1:8000/index/ 结果会报错,如下所示:
"""The view app01.views.index didn't return an HttpResponse object. It returned None instead."""
JsonResponse
2.视图函数返回json格式数据
案例:
1.views.py中修改
import json
def index(request):
user_dict = {
'name': 'jason老师',
'pwd': 123,
'hobby': ['read', 'run', 'music']
}
json_str = json.dumps(user_dict, ensure_ascii=False)# ensure_accii取消中文编码
return HttpResponse(json_str)
2.启动Django,浏览器输入 127.0.0.1:8000/index/
浏览器页面显示 json格式的 {"name": "jason老师", "pwd": 123, "hobby": ["read", "run", "music"]}
# Django里封装了个方法 JsonResponse
案例:
1.views.py中修改
from django.http import JsonResponse
def index(request):
user_dict = {
'name': 'jason老师',
'pwd': 123,
'hobby': ['read', 'run', 'music']
}
return JsonResponse(user_dict, json_dumps_params={'ensure_ascii': False})
2.启动Django,浏览器输入 127.0.0.1:8000/index/
浏览器页面显示 json格式的 {"name": "jason老师", "pwd": 123, "hobby": ["read", "run", "music"]}
################################################################################
案例:
1.views.py中修改
from django.http import JsonResponse
def index(request):
user_list = [11, 22, 33, 44, 55, 66, 'jason老师']
return JsonResponse(user_list, json_dumps_params={'ensure_ascii': False})
2.启动Django,浏览器输入 127.0.0.1:8000/index/ 结果会报错
"""In order to allow non-dict objects to be serialized set the safe parameter to False."""
解决:
"""序列化非字典类型的数据还需要指定safe参数为False"""
把index函数,添加safe=False,如下所示:
return JsonResponse(user_list, json_dumps_params={'ensure_ascii': False}, safe=False)
浏览器再次访问,显示正常 [11, 22, 33, 44, 55, 66, "jason老师"]
form表单发送文件
form携带文件数据
1.method属性值必须是post
2.enctype属性值必须是 multipart/form-data
后端获取文件数据的操作:
print('文件数据', request.FILES)
file_obj = request.FILES.get('file') # file来自form的name
# request.FILES.getlist 获取所有文件;get默认是最后1个
file_obj.name # 文件名
#案例:
1.views.py中修改
def index(request):
if request.method == 'POST':
print(request.POST)
return render(request, 'index.html')
2.templates中创建index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
{% load static %}
<script src="{% static 'jquery.js' %}"></script>
<link rel="stylesheet" href="{% static 'bootstrap-3.4.1-dist/css/bootstrap.min.css' %}">
<script src="{% static 'bootstrap-3.4.1-dist/js/bootstrap.min.js' %}"></script>
</head>
<body>
<form action="" method="post">
<p>username:
<input type="text" name="username">
</p>
<p>file:
<input type="file" name="file">
</p>
<input type="submit" value="提交">
</form>
</body>
</html>
3.启动Django,浏览器输入 127.0.0.1:8000/index/ 输入'jason',选择文件 'test.txt',再提交,查看pychrm终端打印
<QueryDict: {'username': ['jason'], 'file': ['test.txt']}>
#修改:
1.views.py中修改
def index(request):
if request.method == 'POST':
print('普通数据', request.POST)
print('文件数据', request.FILES)
return render(request, 'index.html')
2.templates中修改index.html
<form action="" method="post" enctype="multipart/form-data">
3.启动Django,浏览器输入 127.0.0.1:8000/index/ 输入'jason',选择文件 'test.txt',再提交,查看pychrm终端打印
普通数据 <QueryDict: {'username': ['jason']}>
文件数据 <MultiValueDict: {'file': [<InMemoryUploadedFile: test.txt (text/plain)>]}>
#进阶:
1.views.py中修改
def index(request):
if request.method == 'POST':
print('普通数据', request.POST)
print('文件数据', request.FILES)
file_obj = request.FILES.get('file')
print(file_obj.name)
with open(file_obj.name, 'wb') as f:
for line in file_obj:
f.write(line)
return render(request, 'index.html')
3.启动Django,浏览器输入 127.0.0.1:8000/index/ 输入'jason',选择文件 'test.txt',再提交
就能实现浏览器上传文件到后端,在Django下生成test.txt文件
FBV与CBV
FBV:基于函数的视图
1.在views.py中定义函数
def index(request):
return HttpResponse()
2.在urls.py中添加FBV路由
path('index/', views.index),
CBV:基于类的视图
1.在views.py中定义类
from django import views
class MyView(views.View):
def get(self, request):
return HttpResponse('我是CBV里面的get方法')
def post(self, request):
return HttpResponse('我是CBV里面的post方法')
2.在urls.py中添加CBV路由
path('func/', views.MyView.as_view()),
3.启动Django,浏览器输入 127.0.0.1:8000/func/
"""CBV会自动根据请求方式的不同匹配类中定义的方法并自动执行"""
CBV源码分析
源码分析入口
path('func/', views.MyView.as_view()),
pycharm中,ctrl按住,选择as_view点击,就可以调到底层源码
1.绑定给类的as_view方法
def as_view(...):
def view(...):
pass
return view
2.CBV路由匹配本质:跟FBV是一致的
变成了path('func/', views.view),
3.访问func触发view执行
def view(...):
obj = cls()
return obj.dispatch()
'''涉及到对象.名字 一定要确定对象是谁,再确定查找顺序'''
4.研究dispatch方法
def dispatch(...):
func_name = getattr(obj,request.method.lower())
func_name(...)
模板语法传值
方式1:指名道姓 # 通过字典,精确,不浪费资源;但是数据多的时候,字典会很长
案例:
1.在urls.py中添加路由
# 模板层
path('modal/', views.modal),
2.在templates中创建空的modal.html文件
3.在views.py中添加
def modal(request):
name = 'jason'
age = 18
gender = 'male'
return render(request, 'modal.html', {'name': name, 'age': age, 'gender': gender})
方式2:关键字 locals() # 将整个局部名称空间中的名字全部传入,简单快捷
修改view.py
def modal(request):
name = 'jason'
age = 18
gender = 'male'
return render(request, 'modal.html', locals())
模板语法传值特性
# 基本数据类型直接传递使用
"""Django的模板语法在操作容器类型的时候只允许使用句点符"""
案例:
1.在views.py中修改
def modal(request):
i = 123
f = 11.11
s = 'hello world'
l = [11, 22, 33]
d = {'name': 'jason', 'pwd': 123, 'others': [11, {'a': 123, 'b': [111, 222, 333]}, 22]}
t = (11, 22, 33)
se = {11, 22, 33}
b = True
return render(request, 'modal.html', locals())
2.在templates中修改modal.html文件
<body>
<p>{{ i }} </p>
<p>{{ f }} </p>
<p>{{ s }} </p>
<p>{{ l }} </p>
<p>{{ l.2 }} </p>
<p>{{ d }} </p>
<p>{{ d.name }} </p>
<p>{{ d.others.1.b.2 }} </p>
<p>{{ t }} </p>
<p>{{ se }} </p>
<p>{{ b }} </p>
</body>
# 可以使用多个句点符去选择,'{{ d.others.1.b.2 }}',结果是333
3.启动Django,浏览器访问http://127.0.0.1:8000/modal/
# 函数名的传递会自动加括号执行,并将返回值展示到页面
"""注意函数如果有参数,则不会执行,也不会展示,模板语法不支持"""
案例:
1.在views.py中修改
def modal(request):
def func1():
print('哈哈哈')
return ('你到底行不行')
return render(request, 'modal.html', locals())
2.在templates中修改modal.html文件
<body>
<p>{{ func1 }}</p>
</body>
3.启动Django,浏览器访问http://127.0.0.1:8000/modal/ 页面打印'你到底行不行'
# 类名的传递也会自动加括号产生对象并展示到页面上
'''对象的传递则直接使用即可'''
案例:
1.在views.py中修改
def modal(request):
class MyClass(object):
def get_obj(self):
return 'obj'
@classmethod
def get_cls(cls):
return 'cls'
@staticmethod
def get_func():
return 'func'
obj = MyClass()
return render(request, 'modal.html', locals())
2.在templates中修改modal.html文件
<body>
<p>{{ MyClass }}</p>
<p>{{ obj }}</p>
<p>{{ obj.get_cls }}</p>
<p>{{ obj.get_func }}</p>
<p>{{ obj.get_obj }}</p>
</body>
3.启动Django,浏览器访问http://127.0.0.1:8000/modal/ 页面打印
<app01.views.modal.<locals>.MyClass object at 0x000001BB2D91BB90>
<app01.views.modal.<locals>.MyClass object at 0x000001BB2DA82C90>
cls
func
obj
'''模板语法会判断每一个名字是否可以调用,如果可以则调用'''
模板语法过滤器
# 类似于Python的内置函数
案例:
1.在views.py中修改
def modal(request):
i = 123
f = 11.11
s = 'hello world'
l = [11, 22, 33]
d = {'name': 'jason', 'pwd': 123, 'others': [11, {'a': 123, 'b': [111, 222, 333]}, 22]}
t = (11, 22, 33)
se = {11, 22, 33}
b = True
from datetime import datetime
res = datetime.today()
file_size = 21432131 # 一般使用os.path.getsize() 单位是字节
s1 = 'my name is jason my age is 18 hahaha heiheihei hehehe'
script_tag = '<h1>还认识我吗</h1>' # 默认是传什么,就打印什么,不会变成h1样式
from django.utils.safestring import mark_safe
res1 = mark_safe('<h1>还认识我吗</h1>') # 后端也可以用这个模块实现safe
'''html页面上的数据不一定非要在html页面上编写,也可以后端写好传入'''
return render(request, 'modal.html', locals())
2.在templates中修改modal.html文件
<body>
<p>统计长度:{{ s|length }}</p>
<p>加法运算:{{ i|add:123 }},字符加法运算:{{ s|add:'heiheihei' }}</p>
<p>转换时间:{{ res|date:'Y-m-d H:i:s' }}</p>
<p>文件大小:{{ file_size|filesizeformat }}</p>
<p>数据切片:{{ l|slice:'0:2' }}</p>
<p>字符截取前6个:"{{ s1|truncatechars:6 }}</p>
<p>单词截取(空格)前6个:"{{ s1|truncatewords:6 }}</p>
<p>语法转义:{{ script_tag|safe }}</p>
<p>{{ res1 }}</p>
</body>
3.启动Django,浏览器访问http://127.0.0.1:8000/modal/ 页面打印
"""
Django模板语法中的符号就两个,一个{{ }},一个{% %}
需要使用数据的时候 {{ }}
需要使用方法的时候 {% %}
"""
模板语法标签
# 类似于Python流程控制
在templates中修改html文件,条件一般是模板语法传过来的数据,直接写名字即可
# if判断
{% if 条件 %}
条件成立执行的代码
{% elif 条件1 %}
条件1成立执行的代码
{% else %}
条件都不成立执行的代码
{% endif %}
# for循环
{% for i in l %}
{% if forloop.first %}
<p>这是第一次哦</p>
{% elif forloop.last %}
<p>这是最后异常哦</p>
{% else %}
<p>{{ i }}</p>
{% endif %}
{% empty %}
<p>空的,怎么for循环</p>
{% endfor %}
# 别名 给d.others.1.b.2起一个aaa的别名,在里面可以随意调用
{% with d.others.1.b.2 as aaa %}
{{ aaa }}
{% endwith %}
# 目前先了解,之前Django的settings.py要注释MIDDLEWARE中注释掉django.middleware.csrf.CsrfViewMiddleware
# 在form表单里增加这个,跨域访问保护,产生token值.
{% csrf_token %}
模板自定义相关
"""
如果想自定义 必须先做以下三件事
1.在应用下创建名为templatetags文件夹
2.在该文件夹创建容易名称的py文件
3.在该py文件内编写自定义相关代码
"""
# 自定义过滤器,最多只能有2个参数
案例:
1.应用app01下创建templatetags文件夹
2.该文件夹下创建mytag.py文件
from django.template import Library
register = Library()
@register.filter(name='myfilter')
def my_add(a, b):
return a + b # 简单的a+b
3.templates的modal.html修改body
<body>
{% load mytag %}
{{ i|myfilter:1 }}
</body>
4.启动Django,浏览器访问http://127.0.0.1:8000/modal/ 页面打印
# 自定义标签函数,可以传多个参数,*args
案例:
1.mytag.py文件添加
@register.simple_tag(name='mt')
def func(a, b, c, d):
return a + b + c + d
2.templates的modal.html修改body
<body>
{% load mytag %}
{% mt 1 2 3 4 %}
</body>
4.启动Django,浏览器访问http://127.0.0.1:8000/modal/ 页面打印
# 自定义inclusion_tag
案例:
1.mytag.py文件添加
@register.inclusion_tag(filename='it.html')
def index(n):
html = []
for i in range(n):
html.append('第%s页' % i)
return locals()
2.templates中创建it.html #不是完整的html.就只有ul
<ul>
{% for i in html %}
<li>{{ i }}</li>
{% endfor %}
</ul>
3.templates的modal.html修改body
{% index 10 %}
{% index 5 %}
4.启动Django,浏览器访问http://127.0.0.1:8000/modal/ 页面打印
#会根据index后面的数字,找到it.html插入到modal.html中;数字是几,就插入几次.
模板继承
"""在templates中创建子版html文件"""
{% extends '母版html文件名' %}
{% block 名字 %}
替换内容
{% endblock %}
"""在template中修改母板html文件"""
{% block 名字 %}
模板内容
{% endblock %}
'''补充 {{ block.super }} 可以在子版里继承母板,使用母版的内容'''
一般情况母版里有三个区域要加,扩展性更高
css content js # 子版可以替换自己的样式和脚本以及内容
案例:
1.在urls.py中添加路由
path('home/', views.home),
path('register/', views.register),
path('login/', views.login),
2.templates中创建home文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
{% load static %}
<script src="{% static 'jquery.js' %}"></script>
<link rel="stylesheet" href="{% static 'bootstrap-3.4.1-dist/css/bootstrap.min.css' %}">
<script src="{% static 'bootstrap-3.4.1-dist/js/bootstrap.min.js' %}"></script>
{% block css %}
{% endblock %}
</head>
<body>
<nav class="navbar navbar-inverse">
<div class="container-fluid">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse"
data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">Brand</a>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav">
<li class="active"><a href="#">Link <span class="sr-only">(current)</span></a></li>
<li><a href="#">Link</a></li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true"
aria-expanded="false">Dropdown <span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a href="#">Action</a></li>
<li><a href="#">Another action</a></li>
<li><a href="#">Something else here</a></li>
<li role="separator" class="divider"></li>
<li><a href="#">Separated link</a></li>
<li role="separator" class="divider"></li>
<li><a href="#">One more separated link</a></li>
</ul>
</li>
</ul>
<form class="navbar-form navbar-left">
<div class="form-group">
<input type="text" class="form-control" placeholder="Search">
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
<ul class="nav navbar-nav navbar-right">
<li><a href="#">Link</a></li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true"
aria-expanded="false">Dropdown <span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a href="#">Action</a></li>
<li><a href="#">Another action</a></li>
<li><a href="#">Something else here</a></li>
<li role="separator" class="divider"></li>
<li><a href="#">Separated link</a></li>
</ul>
</li>
</ul>
</div><!-- /.navbar-collapse -->
</div><!-- /.container-fluid -->
</nav>
<div class="container-fluid">
<div class="row">
<div class="col-md-3">
<div class="list-group">
<a href="/home/" class="list-group-item active">
首页
</a>
<a href="/login/" class="list-group-item">登录</a>
<a href="/register/" class="list-group-item">注册</a>
<a href="#" class="list-group-item">更多</a>
<a href="#" class="list-group-item">外链</a>
</div>
</div>
<div class="col-md-9">
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title">Panel title</h3>
</div>
<div class="panel-body">
{% block content %}
{# {% include 'menu.html' %}#}
<div class="jumbotron">
<h1>全世界最大的线上学习平台!</h1>
<p>...</p>
<p><a class="btn btn-primary btn-lg" href="#" role="button">Learn more</a></p>
</div>
{% endblock %}
</div>
</div>
</div>
</div>
</div>
{% block js %}
{% endblock %}
</body>
</html>
3.template中创建子版html文件
# register.html文件
{% extends 'home.html' %}
{% block css %}
<style>
h1 {
color: red;
}
</style>
{% endblock %}
{% block content %}
<h1 class="text-center">注册页面</h1>
<form action="">
<p>username:<input type="text" class="form-control"></p>
<p>password:<input type="text" class="form-control"></p>
{{ block.super }}
<input type="submit" class="btn btn-primary btn-block">
</form>
{% endblock %}
{% block js %}
<script>
alert('注册页面独有的脚本')
</script>
{% endblock %}
# login.html文件
{% extends 'home.html' %}
{% block css %}
<style>
h1 {
color: orange;
}
</style>
{% endblock %}
{% block content %}
<h1 class="text-center">登录页面</h1>
<form action="">
<p>username:<input type="text" class="form-control"></p>
<p>password:<input type="text" class="form-control"></p>
<input type="submit" class="btn btn-danger btn-block">
</form>
{% endblock %}
{% block js %}
<script>confirm('下午不要困')</script>
{% endblock %}
4.启动Django,浏览器访问http://127.0.0.1:8000/home/ 点击登录和注册,查看页面
模板导入(了解)
将html页面当做模块的形式导入使用
{% include '模块html文件' %}
案例:
1.template中创建模块html文件
# menu.html文件
<h1>我是一个非常好看的form表单</h1>
2.调用该模板html,例如,register.html导入改模板html
'''在register.html中添加include'''
<form action="">
<p>username:<input type="text" class="form-control"></p>
<p>password:<input type="text" class="form-control"></p>
{% include 'menu.html' %}
{{ block.super }}
<input type="submit" class="btn btn-primary btn-block">
</form>
3.启动Django,浏览器访问http://127.0.0.1:8000/home/ 点击注册,查看页面,多了'我是一个非常好看的form表单'
本文作者:ycmyay
本文链接:https://www.cnblogs.com/ycmyay/p/17383807.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现