Web.py
一、Templetor模板对象
(1)模板系统使用方式
在工程同级目录下创建templates
文件夹,在该文件夹内创建hello.html
文档,内容如下:
$def with (name)
Hello $name!
使用模板系统引用hello.html
文档方法:
# 方法一
render = web.template.render('templates')
print render.hello('world')
# 方法二
hello = web.template.frender('templates/hello.html')
print hello('world')
此外还有一个便捷方式:
# 方法三
template = "$def with (name)\nHello $name"
hello = web.template.Template(template)
print hello('world')
(2)语法注意事项
-
模板中Python语句要以
$
开头; -
传入模板的参数如果是html格式,如果想正常显示效果,引用该参数要用
$:
如:render.hello('<em>world</em>')
模板中是Hello $name!
,结果:hello <em>world</em>!
模板中是Hello $:name!
,结果:hello world! -
需要显示
$
时,在web.py 0.2 templates中用$$
,之后版本也可用\$
-
添加注释用
$#
,注释一直至本行末 -
模板中的控制结构,例如:
$for i in range(10):
I like $i
$for i in range(10): I like $i
$while a:
hello $a.pop()
$if times > max:
Stop! In the name of love.
$else:
Keep on, you can do it.
其中循环结构中有个特定语法loop
可以使用:
loop.index: the iteration of the loop (1-indexed) ,表示当前循环体所在循环次数,由1开始计算
loop.index0: the iteration of the loop (0-indexed),表示当前循环体所在循环次数,由0开始计算
loop.first: True if first iteration,判断当前循环是否为首次循环
loop.last: True if last iteration,判断当前循环是否为末次循环
loop.odd: True if an odd iteration,表示当前循环体是否为第奇次循环,首次为奇数次,返回True
loop.even: True if an even iteration,表示当前循环体是否为第偶次循环
loop.parity: "odd" or "even" depending on which is true,当前循环体为奇数次返回odd,偶数次为even
loop.parent: the loop above this in nested loops,本循环的外层循环对象
例如:
<table>
$for c in ["a", "b", "c", "d"]:
<tr class="$loop.parity">
<td>$loop.index</td>
<td>$c</td>
</tr>
</table>
- 模板中定义函数
$def
$def tr(values):
<tr>
$for v in values:
<td>$v</td>
</tr>
$def table(rows):
<table>
$for row in rows:
$:row
</table>
$ data = [['a', 'b', 'c'], [1, 2, 3], [2, 4, 6], [3, 6, 9] ]
$:table([tr(d) for d in data])
- 模板中定义代码块
$code:
:
$code:
x = "you can write any python code here"
y = x.title() $# 每个单词首字母大写
def limit(s, width=10):
"""limits a string to the given width"""
if len(s) >= width:
return s[:width] + "..."
else:
return s
$limit(x) $# 结果:you can wr...
$limit(y) $# 结果:You Can Wr...
$z $#结果:68
- 模板中定义额外的属性,字符串类型:
$def with (title, body)
$var title: $title
$var content_type: text/html
<div id="body">
$body
</div>
可以用模板对象引用这些属性,模板名为page.html
:
>>> out = render.page('hello', 'hello world')
>>> out.title
u'hello'
>>> out.content_type
u'text/html'
>>> str(out)
'\n\n<div>\nhello world\n</div>\n'
- 设置模板的全局变量,适用于所有模板:
$# web.py 0.2 版本
render = web.template.render("templates/",globals={"user":"123"})
$# 之后版本还可以
render = web.template.render("templates/")
web.template.Template.globals = {"user":"123"}
在其他文档中使用$user
即可调用123
- 模板复用
当多个页面有着相同的结构框架的时候,可以将这个框架整合在一个模板中,通过模板复用的方式公用这个框架。
render=web.template.render(“templates”,base=”layout”)
这里传入base
参数设置复用模板,layout
是templates下的layout.html
模板,其中代码如下,参数content
用于接收其他模板的结果对象。
$def with (content)
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Strict//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd”>
<html xmlns=”http://www.w3.org/1999/xhtml”>
<head>
<meta http-equiv=”Content-Type” content=”text/html; charset=utf-8″ />
<title>Layout</title>
</head>
<body>
$:content
</body>
</html>
$def with(gname, fname)
Hi, $(gname) $(fname)
运行render.index(“Lisa”, “Hayes”)
,页面上打印Hi, Lisa Hayes
,查看代码会发现最终代码就是index.html
和layout.html
合并在一起的结果,index.html
中的内容被嵌入到layout.html
中的$:conten
t处。
在layout.html
模板中还可以引用index.html
中定义的var变量,这为程序带来了更多的灵活性,比如我们希望在不同的页面在使用同一个layout模板的时候能有不同的title,可以在使用layout的模板中定义如下一个var变量:
$var title:This is index.html
然后在layout.html中的title处修改为:
<title>$content.title</title>
这样,访问index.html时显示在浏览器上的title就是This is index.html,而不是原来的Layout了。
二、Form Library表单
- 需要引入包:
from web import form
# input类:
Textbox - free form single line input (input type="text")
Password - free form single line that hides input (input type="password")
Textarea - free form multi line input (textarea)
Dropdown - mutually exclusive input for lists (select and options)
Radio - mutually exclusive input for a few options (input type="radio")
Checkbox - binary input (input type="checkbox")
Button - submit the form (button)
- 简单使用:
login = form.Form(
form.Textbox('username'),
form.Password('password'),
form.Button('Login'),
)
f = login()
print f.render()
等价于:
<table>
<tr><th><label for="username">username</label></th><td><input type="text" id="username" name="username"/><div class="post" style="display: none;"></div></td></tr>
<tr><th><label for="password">password</label></th><td><input type="password" id="password" name="password"/><div class="post" style="display: none;"></div></td></tr>
<tr><th><label for="Login"></label></th><td><button id="Login" name="Login">Login</button><div class="post" style="display: none;"></div></td></tr>
</table>
- 控件属性
form.textbox("firstname",
form.notnull, #put validators first followed by optional attributes
class_="textEntry", #gives a class name to the text box -- note the underscore
pre="pre", #directly before the text box
post="post", #directly after the text box
description="please enter your name", #describes field, defaults to form name ("firstname")
value="bob", #default value
id="nameid", #specify the id
)
以及其他html的相关属性:
myform2 = form.Form(
form.textbox('phonenumber',
size="12",
maxlength="12" )
)
三、使用子应用
例如:在blog.py
中
import web
urls = (
"", "reblog",
"/(.*)", "blog"
)
class reblog:
def GET(self): raise web.seeother('/')
class blog:
def GET(self, path):
return "blog " + path
app_blog = web.application(urls, locals())
当前的主应用code.py
import web
import blog
urls = (
"/blog", blog.app_blog,
"/(.*)", "index"
)
class index:
def GET(self, path):
return "hello " + path
app = web.application(urls, locals())
if __name__ == "__main__":
app.run()
四、获取客户端信息web.ctx
web.ctx
基于threadeddict类,又被叫做ThreadDict。这个类创建了一个类似字典(dictionary-like)的对象,对象中的值都是与线程id相对应的。这样做很妙,因为很多用户同时访问系统时,这个字典对象能做到仅为某一特定的HTTP请求提供数据(因为没有数据共享,所以对象是线程安全的)
例如:访问某页面的用户是从哪个网页跳转而来的
class example:
def GET(self):
referer = web.ctx.env.get('HTTP_REFERER', 'http://google.com')
raise web.seeother(referer)
上述代码用web.ctx.env获取HTTP_REFERER的值。如果HTTP_REFERER不存在,就会将google.com做为默认值。接下来,用户就会被重定向回到之前的来源页面。
web.ctx另一个特性,是它可以被loadhook赋值。例如:当一个请求被处理时,会话(Session)就会被设置并保存在web.ctx中。由于web.ctx是线程安全的,所以我们可以象使用普通的python对象一样,来操作会话(Session)。
ctx
中的数据成员:Request
-
environ
又被写做. env – 包含标准WSGI环境变量的字典。 -
home
– 应用的http根路径(译注:可以理解为应用的起始网址,协议+站点域名+应用所在路径)例:http://example.org/admin -
homedomain
– 应用所在站点(可以理解为协议+域名) http://example.org -
homepath
– 当前应用所在的路径,例如: /admin -
host
– 主机名(域名)+用户请求的端口(如果没有的话,就是默认的80端口),例如: example.org, example.org:8080 -
ip
– 用户的IP地址,例如: xxx.xxx.xxx.xxx -
method
– 所用的HTTP方法,例如: GET -
path
– 用户请求路径,它是基于当前应用的相对路径。在子应用中,匹配外部应用的那部分网址将被去掉。例如:主应用在code.py中,而子应用在admin.py中。在code.py中, 我们将/admin关联到admin.app。 在admin.py中, 将/stories关联到stories类。在 stories中, web.ctx.path就是/stories, 而非/admin/stories。形如: /articles/845 -
protocol
– 所用协议,例如: https -
query
– 跟在'?'字符后面的查询字符串。如果不存在查询参数,它就是一个空字符串。例如: ?fourlegs=good&twolegs=bad -
fullpath
可以视为 path + query – 包含查询参数的请求路径,但不包括'homepath'。例如:/articles/845?fourlegs=good&twolegs=bad
Response
-
status
– HTTP状态码(默认是'200 OK') 401 Unauthorized 未经授权 -
headers
– 包含HTTP头信息(headers)的二元组列表。 -
output
– 包含响应实体的字符串。
五、应用处理器
加载钩子(loadhook)和卸载钩子(unloadhook)分别在请求开始之前和结束之后执行
def my_loadhook():
print "my load hook"
def my_unloadhook():
print "my unload hook"
app.add_processor(web.loadhook(my_loadhook))
app.add_processor(web.unloadhook(my_unloadhook))
在eclipse中无显示效果,可在命令行中运行python xxx.py
,装有两版Python输入py -2 xxx.py
:
![](https://img.haomeiwen.com/i4986739/6c56ad6574d3f541.png)
六、自定义NotFound消息
设置自定义的NotFound消息:
def notfound():
return web.notfound("Sorry, the page you were looking for was not found.")
# You can use template result like below, either is ok:
#return web.notfound(render.notfound())
#return web.notfound(str(render.notfound()))
app.notfound = notfound
返回自定义的NotFound消息:
class example:
def GET(self):
raise web.notfound()
自定义500错误信息:
def internalerror():
return web.internalerror("Bad, bad server. No donut for you.")
app.internalerror = internalerror
六、流传输大文件
import web
import time
urls = (
"/", "count_holder",
"/(.*)", "count_down",
)
app = web.application(urls, globals())
class count_down:
def GET(self,count):
# These headers make it work in browsers
web.header('Content-type','text/html')
web.header('Transfer-Encoding','chunked')
yield '<h2>Prepare for Launch!</h2>'
j = '<li>Liftoff in %s...</li>'
yield '<ul>'
count = int(count)
for i in range(count,0,-1):
out = j % i
time.sleep(1)
yield out
yield '</ul>'
time.sleep(1)
yield '<h1>Lift off</h1>'
class count_holder:
def GET(self):
web.header('Content-type','text/html')
web.header('Transfer-Encoding','chunked')
boxes = 4
delay = 3
countdown = 10
for i in range(boxes):
output = '<iframe src="/%d" width="200" height="500"></iframe>' % (countdown - i)
yield output
time.sleep(delay)
if __name__ == "__main__":
app.run()
要流传输大文件,需要添加传输译码(Transfer-Encoding)区块头,这样才能一边下载一边显示。否则,浏览器将缓冲所有数据直到下载完毕才显示。
Django
一、环境
- 参考:Django官网
- 安装:
pip install Django==xxx
二、应用
(1)创建工程
django-admin startproject myblog(项目名)
![](https://img.haomeiwen.com/i4986739/21e2d865e66cacbc.png)
-
manage.py
:项目管理器。项目进行交互的命令行工具集入口 -
myblog
:项目的一个容器,包含项目最基本的配置,不建议修改目录名称 -
wsgi.py
:Python服务器网关接口,Python应用与Web服务器之间的接口,与Web服务器通讯的关键,使Web服务器识别Python应用 -
url.py
:URL配置文件 -
settings.py
:项目核心配置文件
import os
# 项目根目录
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# 项目安全码,自动生成
SECRET_KEY = '4jj(2(rmtrek@fmq$qgo#r^_^^#1c8d)64**hfr(0@)%+sz-j_'
# 调试设置
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
# 设置允许访问的地址,当DEBUG = False时需要设置
ALLOWED_HOSTS = []
# 已安装的应用。自定义的应用需包含在里面才可使用
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
# 中间件,Django自带的工具集
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
# URL根配置文件
ROOT_URLCONF = 'myblog.urls'
# 模板配置,模板就是一个个HTML
TEMPLATES = [
{
# 模板引擎
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'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',
],
},
},
]
WSGI_APPLICATION = 'myblog.wsgi.application'
# Database
# https://docs.djangoproject.com/en/1.11/ref/settings/#databases
# 数据库配置,默认sqlite3,使用其他数据库参考上方网站
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
# Password validation
# https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validators
# 密码认证
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
# Internationalization
# https://docs.djangoproject.com/en/1.11/topics/i18n/
# 美式英语
LANGUAGE_CODE = 'en-us'
# 时区
TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.11/howto/static-files/
# 静态文件地址
STATIC_URL = '/static/'
python manage.py runserver [端口号]
:设置端口号启动服务,无端口号设置默认时为8000
![](https://img.haomeiwen.com/i4986739/2257f4829f1fbdb0.png)
(2)创建应用
python manage.py startapp blog(应用名)
或django-admin startapp blog(应用)
注意: 应用需要添加到setting.py中的INSTALLED_APPS中,才可使用
![](https://img.haomeiwen.com/i4986739/4bdd0d30f3a6a10a.png)
-
migrations
:数据移植(迁移)模块,内容自动生成 -
admin.py
:当前应用的后台管理系统配置 -
apps.py
:当前应用的配置 -
models.py
:数据模块 -
tests.py
:自动化测试模块 -
views.py
:执行响应的代码
# 1、settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'blog'
]
# 2、views.py
from django.http import HttpResponse
def index(request):
return HttpResponse("Hello,world!")
编辑 views.py:
- 每个响应对应一个函数,函数必须返回一个响应
- 函数必须存在一个参数,一般约定为requset
- 每个响应对应一个URL
# 3、urls.py
from django.conf.urls import url
from django.contrib import admin
import blog.views as bv
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^index/', bv.index)
]
三、Templates
参考: Django之模板语言
(1)应用URL设置
# 1、在根urls.py 中引入include
from django.conf.urls import url, include
from django.contrib import admin
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^blog/', include("blog.urls"))
]
# 2、在APP(blog)目录下新建urls.py,格式和根urls.py相同
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^$', views.index)
]
配置URL时注意正则表达式尾部符号
$
和/
,^$
限制空字符,最后应该由/
结尾
(2)Templates
- Templates:HTML文件,使用Django模板语言(DTL),也支持第三方模板(如Jinja2)
- DTL初使用:
rander()
函数支持传入dic类型参数,该参数是后台传递给模板的参数,键为参数名。在模板中使用{{参数名}}
来使用
# 1、在应用目录下创建templates目录,并在该目录内创建index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>{{hello}}</h1>
</body>
</html>
# 2、修改应用views.py,返回render()
from django.shortcuts import render
def index(request):
# 主要传入:URL请求request,模板名(,传递给模板的参数,...)
return render(request, "index.html", {"hello": "HELLO,BLOG"})
- 注意:模板目录必须以
templates
命名,否则无法识别
- 问题:Django查找Templates时,按照INSTALLED_APPS中的添加顺序查找Template。不同APP下Template目录中的同名HTML文件会发生冲突
- 解决方法:在APP的Templates目录下创建以APP名为名称的目录,将html文件放入该目录下,
render()
中参数改为render(request, "blog/index.html", {"hello": "HELLO,BLOG"})
四、Models
一个Model对应数据库的一张数据表,Django中Models以类的形式表示,它包含了一些基本字段以及数据的一些行为。
ORM:对象关系映射,实现了对象和数据库之间的映射,隐藏了数据访问的细节,不需要编写SQL语句。
(1)创建Models
# APP目录下models.py
from django.db import models
class Article(models.Model):
title = models.CharField(max_length=32, default="Title")
content = models.TextField(null=True)
(2)生成数据表
- 1、迁移准备:
python manage.py makemigrations [APP名]
没有指定APP名时,默认为该项目下所有应用都执行数据迁移 - 2、迁移生成:
python manage.py migrate
![](https://img.haomeiwen.com/i4986739/9f2ef0802e23937c.png)
# migrations目录下自动生成0001_initial.py
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='Article',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('title', models.CharField(default='Title', max_length=32)),
('content', models.TextField(null=True)),
],
),
]
models中没设置主键时自动创建
id
字段作为主键
- 查看SQL生成语句:
python manage.py sqlmigrate 应用名 文件id
![](https://img.haomeiwen.com/i4986739/856633c2ba2a5456.png)
默认在SQLite3数据库下生成,在项目根目录下
db.sqlite3
(3)调用数据表
# views.py
from django.shortcuts import render
# 1、引入models
from . import models
def index(request):
# 数据表中获取主键为1的数据等价于`id=1`
article = models.Article.objects.get(pk=1)
# 传入数据对象
return render(request, "blog/index.html", {"article": article})
# index.html,通过“对象.属性”调用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>{{article.title}}</h1>
<h2>{{article.content}}</h2>
</body>
</html>
# index.html中的for循环
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>
<a href="">新文章</a>
</h1>
{% for article in articles %}
<a href="" >{{ article.title }}</a>
<br/>
{% endfor %}
</body>
</html>
(4)配置MySQL
- 1、安装
mysqlclient
(步骤2后runserver
,如果提示安装,按提示安装相应库)
# Command "python setup.py egg_info" failed with error code 1 in /tmp/pip-install-g778k6pj/mysqlclient/
# apt-get install libmysql-dev
# apt-get install libmysqlclient-dev
# apt-get install python-dev
pip install mysqlclient
- 2、Django中的设置
# settings.py
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'app_data',
'USER': 'root',
'PASSWORD': '1234',
'HOST': '127.0.0.1',
'PORT': '3306'
}
}
- 3、MySQL数据库中已有的数据表映射到Django应用的
models.py
中(如果数据库中已经设计了表结构的时候):
python manage.py inspectdb > myapp/models.py
- 4、Django应用所需的数据表迁移到MySQL数据库内(包含Django自带应用中的数据表):
python manage.py migrate
五、Admin
Django自带的一个功能强大的自动化数据管理界面,被授权的用户可以直接在Admin中管理数据库,并且可以定制功能。
- 创建超级用户:
python manage.py createsuperuser
密码要求:8字符以上,不能是简单密码 - Admin入口:
localhost:8000/admin/
- 设置Admin页文字,在
setting.py
中修改LANGUAGE_CODE = 'zh_Hans'(简体)/'zh_Hant(繁体)'
- 配置应用:
# 1、在应用下admin.py中引入自身的models模块
from django.contrib import admin
from .models import Article
# 2、Admin注册
admin.site.register(Article)
引入同级模块:
from . import 模块名
引入同级模块下的类:from .模块名 import 类名
- 修改数据的默认显示类型:
# models.py下修改类方法
class Article(models.Model):
title = models.CharField(max_length=32, default="Title")
content = models.TextField(null=True)
def __str__(self):
return self.title
Python2.x使用
__unicode__(self)
,Python3.x使用__str__(self)
- Admin配置类:
from django.contrib import admin
from .models import Article
class ArticleAdmin(admin.ModelAdmin):
# 实现列表多字段显示
list_display = ('title', 'content', 'pub_time')
# 设置列表过滤
list_filter = ('pub_time',)
# 绑定配置类
admin.site.register(Article, ArticleAdmin)
list_display
支持tuple
和list
。tuple
中只有一个元素时元素后加",
"
六、简单博客
(1)URL传参
# 1、应用中的urls.py,正则表达式中组名设置
urlpatterns = [
url(r'^article/(?P<article_id>[0-9]+)$', views.article_page)
]
# 2、应用中的views.py,函数添加参数,与上方组名一致
def article_page(request, article_id):
article = models.Article.objects.get(pk=article_id)
return render(request, "blog/article_page.html", {"article": article})
URL中设置正则表达式的组名,该组名需要与对应函数中的参数名一致,才可传递参数
(2)模板添加超链接
# 1、根urls.py,给应用添加命名空间
urlpatterns = [
url(r'^blog/', include("blog.urls", namespace='blog'))
]
# 2、应用url.py,给URL添加名称
urlpatterns = [
url(r'^article/(?P<article_id>[0-9]+)$', views.article_page, name="article_page")
]
# 3、HTML下添加href超链接部分
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Article Page</title>
</head>
<body>
<h1>{{ article.title }}</h1>
<br/>
<h3>{{ article.content }}</h3>
<br/>
<br/>
<a href="{% url 'blog:edit_page' article.id %}">修改文章</a>
</body>
</html>
模板中超链接目标地址格式:
{% url 'app_name:url_name' [参数] %}
app_name
:
根urls.py
,写在include()
中,namespace='app_name'
url_name
:
应用urls.py
,写在url()
中,name='url_name'
(3)表单设置
# 表单页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="{% url 'blog:edit_action'%}" method="post">
{% csrf_token %}
<label>文章标题:
<input type="text" name="title"/>
</label>
<br/>
<label>文章内容:
<input type="text" name="content"/>
</label>
<br/>
<input type="submit" value="提交">
</form>
</body>
form
中请求方法action='目标URL'
,请求方式mathod='post'
form
中{% csrf_token %}
能防止使用post
提交表单时出现禁止访问(403):CSRF验证失败
# 应用中的views.py
def edit_action(request):
title = request.POST.get('title', 'TITLE')
content = request.POST.get('content', 'CONTENT')
models.Article.objects.create(title=title, content=content)
# articles = models.Article.objects.all()
# return render(request, "blog/index.html", {"articles": articles})
return HttpResponseRedirect('/blog/article/')
request.POST['参数名']
或request.POST.get('参数名', '默认值')
获取post
表单相应数据return HttpResponseRedirect('/blog/article/')
重定向URL
数据库相应操作可通过操作Model对象完成:
models.Model对象类.objects.create(对象属性)
创建Model对象,相应数据库添加数据models.Model对象类.objects.get(对象属性='属性名')
获取Model对象,修改该对象属性后,Model对象.save()
保存修改,相应数据在数据库中被修改
七、补充内容
(1)Templates过滤器
修改模板中的变量,从而显示不同的内容
格式:{{value|filter|...}}
例如:{{value|default:'0'}}
:设置value默认值为“0”
(2)Django Shell
一种Python的交互式命令行程序,并自动引入了项目环境,可与项目进行交互
作用:测试未知方法
启动交互环境:python manage.py shell
from blog.models import Article
# 查看所有Article对象
Article.objects.all()
网友评论