目前对于Python web来说,主流框架是Django和flask.有同学会问,什么是框架呢?打一个比方,就是这个包已经帮你做好了整体的框架(类似于骨架的概念),而你就是在里面缝缝补补,增加细节,一般也都是在settings.py上进行修改配置。
当然了,Python 毕竟是脚本语言,性能上面远达不到我们所需要的要求,但是其用框架搭建网站是十分快捷的。对于学生来说或者一些小项目,可以考虑使用Python的上述两种框架。
当然,对于前端的一些知识,可以在设计开发中慢慢增长,但是基础概念需要掌握的,不过不用在这里耗太久。
而本次的Django框架也仅仅从模版模型表单视图等基本内容为主,后续再持续深入,特别是ORM数据库实例等,倘若还有时间再进行简单的管理系统进行开发。
本次环境 Python 3.10 Pycharm 2022 Django 3.2
简介与创建
django本身基于mvc模型,即model view controller 设计模式。是快速开发网站、设计、部署网站的最佳组合。
model:编写程序应有的功能,负责业务对象与数据库的映射
view:图形界面,负责与用户的交互
controller:负责转发请求,对请求进行处理
pip3 install Django -i https://pypi.tuna.tsinghua.edu.cn/simple
django-admin startproject helloworld
cd helloworld/
或者使用pycharm进行创建(个人推荐使用命令行)
见helloworld文件包,可以看到如上的目录结构
HelloWorld: 项目的容器。
manage.py: 一个实用的命令行工具,可让你以各种方式与该 Django 项目进行交互。
HelloWorld/init.py: 一个空文件,告诉 Python 该目录是一个 Python 包。
HelloWorld/asgi.py: 一个 ASGI 兼容的 Web 服务器的入口,以便运行你的项目。
HelloWorld/settings.py: 该 Django 项目的设置/配置。
HelloWorld/urls.py: 该 Django 项目的 URL 声明; 一份由 Django 驱动的网站“目录“。
HelloWorld/wsgi.py: 一个 WSGI 兼容的 Web 服务器的入口,以便运行你的项目。
python3 manage.py runserver 127.0.0.1:8000
进入到如下界面,就说明已经配置成功了。(说真的,这个比配置tomcat和springboot简单多了,也不愧是快速开发的首选框架)
或者也可以在pycharm配置相应的设置方便快速。
由于创建的helloworld没有views.py文件,所以需要在此目录下创建views.py,并写相应的请求,这里以helloworld为例:
from django.http import HttpResponse
def hello(request):
return HttpResponse("Hello world!");
同时需要在urls.py绑定views.hello,注意views.hello不要加括号
from django.contrib import admin
from django.urls import path
from django.conf.urls import url
from . import views
urlpatterns = [
path('admin/', admin.site.urls),
url(r'^$',views.hello),
# path('hello/', views.hello),
]
Django path()可以接收4个参数,分别是两个必选参数:route 、view 和两个可选参数kwargs、name。
route: 字符串,表示 URL 规则,与之匹配的 URL 会执行对应的第二个参数 view。
view: 用于执行与正则表达式匹配的 URL 请求。
kwargs: 视图使用的字典类型的参数。
name: 用来反向获取 URL。
Django模版
上述内容中将数据与视图混合一起了,不符合MVC思想。而模版是一个文本,用于分离文档的表现形式和内容。
在helloworld目录下创建Templates目录并建立runoob.html文件
<h1>{{ hello world }}</h1>
接下来在settings.py导入位置 ‘DIRS’: [os.path.join(BASE_DIR, ‘templates’)],
修改 views.py,增加一个新的对象,用于向模板提交数据:
其中render用来传递conText填充模版
from django.shortcuts import render
def runoob(request):
context = {}
context['hello'] = 'hello world'
return render(request,'runoob.html',context)
from django.urls import path
from . import views
urlpatterns = [
path('runoob/', views.runoob),
]
再次访问 http://127.0.0.1:8000/runoob即可访问了。
Django模版标签
view: {"html-name" : "views-name"}
HTML: { {变量名} }
return render(request,"runoob.html",{"name":views_name})
# runoob.html:
<p>{ {name} } </p>
列表
# views.py
def runoob(request):
view_list = ["123","456"]
return render(request,"runoob.html",{"views_list":views_list})
# 列表
<p> {{view_list}}</p>
<p> {{view_list.0}} </p>
过滤器
过滤器有lower. upper. truncatewords. addslashes. date length
此处在runoob.html进行过滤
{{变量名 | 过滤器:可选参数 }}
{{name|lower}} # 模版过滤器可以在变量被显示前修改它,过滤器使用管道字符
{{bio|truncatewords:"30"}} # 将显示bio的前三十个词
过滤器的目的就是过滤使得获取到相应的字符内容
下面讲一个safe:
{{ views_str | safe}}
标记为安全不需要转义,保障绝对安全才能用safe
def runoob(request):
views_str = "<a href='https://www.runoob.com/'>点击跳转</a>"
return render(request,"runoob.html",{"views_str":views_str})
# runoob.html:
{{ views_str |safe }}
标签
if / else 标签:
{ % if condition %}
... display
{% endif %}
或者
{ % if condition1 %}
... display1
{% elif condition2 %}
... display2
{% else %}
{ % endif % }
{ % if athlist and coachlist %}
{% endif %}
for标签:
{ % for % }
<ul>
{ % for athlete in athlete_list (reversed)%}
<li> {{ athlete.name }} </li>
{% endfor %}
</ul>
# views.py:
def runoob(request):
views_dict={"name":"cai","age":18}
return render(request,"runoob.html",{"views_dict":views_dict})
# runoob.html:
{ % for i ,j in views_dict.items %}
{{i}} --- {{j}}
{% endfor% }
ifequal/ifnotequal标签:
{ % ifequal %}比较两个值,当他们相等的时候,显示内容:
{% ifequal user currentuser %}
<h1> welcome </h1>
{% else % }
<h1> No </h1>
{% endifequal %}
{ # 这是一个注释 #}
{ % include "nav.html" % }
csrf_token
用于form表单中,作用是跨站请求伪造保护。如果不用的话,再次跳转会抱403权限错误。
自定义标签和过滤器
在应用目录下,建一个templatetags (和templates同级)
在该目录下建一个任意Py文件。
# my_tag.py:
from django import template
register = template.Library() #register名字固定不可改变
其中在settings.py templates下添加libraries配置:
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [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',
],
"libraries":{ # 添加这边三行配置
'my_tags':'templatetags.my_tags' # 添加这边三行配置
} # 添加这边三行配置
},
},
]
在my_tag.py中建立过滤器与自定义标签
注意 {% 没有空格!!!
@register.filter
def my_filter(v1, v2):
return v1 * v2
@register.simple_tag
def my_tag1(v1, v2, v3):
return v1 * v2 * v3
# 在html文件头部导入py文件
{% load my_tag %}
{{ 11|my_filter:22 }}
配置静态文件
在根目录下创建statics目录,在settings最下方配置:
STATIC_URL = '/static/' # 别名
STATICFILES_DIRS = [
os.path.join(BASE_DIR, "statics"),
]
在statics目录下创建css目录 js目录 images目录 plugins目录 分别放css文件 js文件,图片,插件
把bootstrap框架放入插件目录 plugins
在html文件的head标签中引入bootstrap,注意引用路径的配置文件是别名static
<link rel="stylesheet". href="/static/plugins/bootstrap-3.3.7/dist/css/bootstrap.css">
# html:
{% load static %}
{{name}} <img src="{% static 'images/runoob-logo.png'%}" alt="runoob-logo">
模版继承
用继承实现复用,减少冗余内容
父模版 block … endblock 父模版中的预留区域
{% block name %}
预留给子模版的区域,可以设置默认内容
{% endblock name %}
{ % extends "父模版路径" %}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>菜鸟教程(runoob.com)</title>
</head>
<body>
<h1>Hello World!</h1>
<p>菜鸟教程 Django 测试。</p>
{% block mainbody %}
<p>original</p>
{% endblock %}
</body>
</html>
{%extends "base.html" %}
{% block mainbody %}
<p>继承了 base.html 文件</p>
{% endblock %}
Django 模型
Django对数据库提供了很好的支持,提供了统一的调用API,先安装pymysql模块,本次使用的数据库为mysql,同时使用的是阿里云服务器主机ip.
ORM
ORM:对象关系映射,用于实现数据之间的转换。在业务逻辑层和数据库之间充当了桥梁的作用,通过使用描述对象和数据库之间的映射的元数据,将程序中的对象自动持久化到数据库中。
好处:提高了开发效率,不同数据库可以切换,但是需要转换sql语句时,执行效率低。
其中 models:数据表 对象实例:一条记录 属性:字段
*数据库配置
在settings.py文件中找到databases配置项,将信息修改为:
DATABASES = {
'default':
{
'ENGINE': 'django.db.backends.mysql', # 数据库引擎
'NAME': 'runoob', # 数据库名称
'HOST': '127.0.0.1', # 数据库地址,本机 ip 地址 127.0.0.1 ;有服务器就设置自己的服务器
# 服务器记得关闭防火墙,嫌麻烦端口全部打开
'PORT': 3306, # 端口
'USER': 'root', # 数据库用户名
'PASSWORD': '123456', # 数据库密码
}
}
在settings中的__init__.py中引入模块并进行配置:
import pymysql
pymysql.install_as_MySQLdb()
定义模型
使用命令创建app
django-admin startapp TestModel
在TestModel/models.py文件夹下附以下代码:
类名代表数据库表名,继承Model,字段(name),数据类型(CharField) maxlength参数限定长度
from django.db import models
class Test(models.Model):
name = models.CharField(max_length=20)
同时子啊settings.py中找到INSTALLED_APPS这一项,如下:
INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'TestModel', # 添加此项
)
在命令行运行,当然也可以使用数据库工具,创建表TestModel_test
use runoob
create table TestModel_test (
name varchar(20)
)
$ python3 manage.py migrate # 创建表结构
$ python3 manage.py makemigrations TestModel # 让 Django 知道我们在我们的模型有一些变更
$ python3 manage.py migrate TestModel # 创建表结构
*数据库操作
在django框架中,统一都是继承Models,为了兼顾众多数据库不同的语言特性,特此开发出的功能。
下面都是一些常规的增删改查操作,不用特意去记忆,平时敲敲也就记住了,当然重点是前面的步骤没有出现差错。
回到helloworld/urls.py
from django.urls import path
from . import views, testdb
urlpatterns = [
path('runoob/', views.runoob),
path('testdb/', testdb.testdb),
]
from django.http import HttpResponse
from TestModel.models import Test
# 添加数据 (由于我这里在models.py中只设置了name一列)
def testdb(request):
test1 = Test(name='runoob')
test1.save()
return HttpResponse("<p>数据添加成功!</p>")
运行程序,可以看到网页显示数据添加成功,同时可以回到数据工具台,使用select语句 ,看是否成功添加。
获取数据(查找),注意获取的时候需要循环循环for var in list 读取想要的格式,否则会报can only concatenate str (not “QuerySet”) to str错误。
# testdb.py
from django.http import HttpResponse
from TestModel.models import Test
# 数据库操作
def testdb(request):
# 初始化
response = ""
response1 = ""
# 通过objects这个模型管理器的all()获得所有数据行,相当于SQL中的SELECT * FROM
list = Test.objects.all()
# filter相当于SQL中的WHERE,可设置条件过滤结果
response2 = Test.objects.filter(name="jacin")
# 获取单个对象
response3 = Test.objects.get(id=1)
# 限制返回的数据 相当于 SQL 中的 OFFSET 0 LIMIT 2;
Test.objects.order_by('name')[0:2]
# 数据排序
Test.objects.order_by("id")
# 上面的方法可以连锁使用
Test.objects.filter(name="runoob").order_by("id")
# 输出所有数据
for var in list:
response1 += var.name + " "
# response = response1
for var in response2:
response += var.name + " "
return HttpResponse("<p>" + response + "</p>")
# -*- coding: utf-8 -*-
# -*- coding: utf-8 -*-
from django.http import HttpResponse
from TestModel.models import Test
# 数据库操作
def testdb(request):
# 修改其中一个id=1的name字段,再save,相当于SQL中的UPDATE
test1 = Test.objects.get(id=1)
test1.name = 'Google'
test1.save()
# 另外一种方式
# Test.objects.filter(id=1).update(name='Google')
# 修改所有的列
# Test.objects.all().update(name='Google')
re=Test.objects.filter(id=1)
str=""
for var in re:
str += var.name
return HttpResponse("<p>"+str+" 修改成功</p>")
删除数据
from django.http import HttpResponse
from TestModel.models import Test
# 数据库操作
def testdb(request):
# 删除id=1的数据
test1 = Test.objects.get(id=1)
test1.delete()
# 另外一种方式
# Test.objects.filter(id=1).delete()
# 删除所有数据
# Test.objects.all().delete()
return HttpResponse("<p>删除成功</p>")
Django表单
html表单是网站交互性的经典方式。可以查看此处链接点击此处
http协议以请求-回复 方式工作的,发送请求的时候可以附加数据,服务器通过解析请求,可以获得传来的数据,并根据url来提供特定的服务。
GET方法
helloworld/helloworld/search.py
from django.http import HttpResponse
from django.shortcuts import render
# 表单
def search_form(request):
return render(request, 'search_form.html')
# 接收请求数据
def search(request):
request.encoding='utf-8'
if 'q' in request.GET and request.GET['q']:
message = '你搜索的内容为: ' + request.GET['q']
else:
message = '你提交了空表单'
return HttpResponse(message)
/helloworld/templates/search_form.html
注意action 属性是提交的位置,这里的search下面url跳转的地址
<form action="/search/" method="get">
<input type="text" name="q">
<input type="submit" value="搜索">
</form>
/urls.py
from django.conf.urls import url
from . import views,testdb,search
urlpatterns = [
url(r'^hello/$', views.runoob),
url(r'^testdb/$', testdb.testdb),
url(r'^search-form/$', search.search_form),
url(r'^search/$', search.search),
]
POST方法
get:视图显示和请求处理分成两个函数处理
其实提交数据更常使用post,使用url+处理函数
/helloworld/templates/post.html:
csrf_token:django提供的防止伪装提交的功能,post方法提交的表格,必须有此标签
<form action="/search-post/" method="post">
{% csrf_token %}
<input type="text" name="q">
<input type="submit" value="搜索">
</form>
<p>{{ rlt }}</p> <!--预留位置,为表格处理结果预留-->
/helloworld/helloworld/search2.py
# -*- coding: utf-8 -*-
from django.shortcuts import render
from django.views.decorators import csrf
# 接收POST请求数据
def search_post(request):
ctx = {}
if request.POST:
ctx['rlt'] = request.POST['q']
return render(request, "post.html", ctx)
强调一下,需要加上search-post后面的斜杠,否则读取不到
# urls.py +
path('search-post/',search2.search_post),
get和post的区别
get: 提交的数据小于1024字节,表单提交时表单数据将在地址栏显示
post:传递数量不限制,提交数据会隐藏,安全性能较高,对信息也做了隐藏。
Request 对象
from django.http import HttpResponse
def runoob(request):
return HttpResponse("hello world")
path : 请求页面的全路径,不包括域名
method : repuest.method == ‘GET’ ‘POST’
cookies: 包含所有cookies的标准python字典对象
meta:包含所有http头部信息的字典
session:唯一可读写的属性
Django视图
视图函数,接受web请求并返回web响应。响应可以是html页面等。
视图有两个重要的对象,分别是请求对象 request 与 HttpResponse
请求对象 (HttpRequest对象)
GET
数据类型是QuerDict,类似于字典的对象,取值格式: 对象.方法,get()
def runoob(request):
name = request.GET.get("name")
return HttpResponse('name:{}'.format(name))
POST
数据类型和GET一致
def runoob(request):
name = request.POST.get("name")
return HttpResponse('name:{}'.format(name))
path
def runoob(request):
name=request.path
print(name)
return HttpResponse("name")
method
def runoob(request):
name = request.method
print(name)
return HttpResponse("name")
Django路由
路由就是根据用户请求的URL来判断对应的处理程序,并返回处理结果,即URL与Django的视图建立映射关系
path:普通路径,不需要自己手动添加正则首位限制符号,底层添加
re_path: 正则路径 ,需要手动添加正则首位限制符号
无名分组
正则路径的无名分组,按位置传参,一一对应
views除了request ,其他行参数量与urls中的分组数量一致
下面的路径就是index/year(具体的日期)
# views.py
from django.shortcuts import HttpResponse
def index(request,year):
print(year)
return HttpResponse("name")
# urls.py
urlpatterns = [
path('admin/',admin.site.urls),
re_path("^index/[0-9]{4}/$",view.index),
]
有名分组
(?P<组名> 正则表达式)
# views.py
from django.shortcuts import HttpResponse
def index(request, year, month):
print(year,month) # 一个形参代表路径中一个分组的内容,按关键字对应匹配
return HttpResponse('name')
# urls.py
re_path("^index/(?P[0-9]{4}/(?P[0-9]{2}/$",views.index)
路由分发(include)
问题:django 项目多个app目录使用一个urls会造成混淆,后期维护也不方便
解决:使用路由转发,每个app目录都有urls
from app01 import views
# urls.py
path("app01/",include("app01.urls"))
反向解析
随着功能的增加,路由层的url发生变化,需要修改对应的视图层和模版层的url,比较麻烦
可以利用反向解析,当url发生变化可以反向解析,一般用在模版中的超链接及视图中的重定向
普通连接
#
path("login1/",view.login,name="login")
# 在views.py ,从urls 引入reverse
return redirect(reverse("login"))
#templates/ .html
<form action="{% url 'login' %}" method="post">
# urls.py
re_path(r"^login/([0-9]{2})/$",views.login,name="login")
# views.py
# 引入reverse 利用reverse("路由别名“,args=(符合正则匹配的参数,))
return redirect(reverse("login",args=(10,)))
#/templates/ .html
<form action={% url 'login' 10 %}" method="post">
正则路径(有名分组)
# urls.py
re_path(r"^login/(?<year>[0-9]{4}/$",views.login,name="login")
# views.py
return redirect(reverse("login",kwargs={"year":3333}))
# html
<form action="{% url 'login' year=3333 %}" method="post">
命名空间
include(("app名称:urls","app名称"))
原文地址:https://blog.csdn.net/QAZJOU/article/details/125989130
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.7code.cn/show_23192.html
如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除!