环境配置
A.在/etc/httpd/conf.d/python.conf要加上
<Directory /var/www/html/n8test> 此处决定路径
AddHandler mod_python .py 注意此处的空格
PythonHandler mptest python文件名 方法名由前面PythonHandler 后的Handler决定
PythonDebug On
</Directory>
然后重启apache。在文件中可以有多个容器,即多个项目,但只能有一个 .py 文件
B. /etc/selinux/config中将第七行 SELINUX=disabled
然后重启电脑
C.在 /var/www/html/n8test/中创建mptest.py文件
D. 创建mptest.py
from mod_python import apache,util 导入两个模块
def handler(req):
req.content_type=’text/html’ 使python能解析html
var = util.FieldStorage(req).get(‘var’, ‘default_value’)
得到html中url的提交的参数,第一个参数是变量名,第二个参数为,没有得到变量值时的值
req.write(‘hello world’) 此函数的参数不能是int和None,但可以是空字符串
f = file(‘/var/www/html/n8test/index.html’, ‘r’) 注意此处要写绝对路径
html = f.read()
req.write(html) 将html内容写入
return apache.OK 返回200标识,即正常状态
7.
反复用到的路径要用一个变量来替代
8.
将python中的数据传入到html到要在html文件中%s(位置与html中引号没有关系)格式化,然后再python中%传入
9.
执行顺序是先加载python命令,然后才执行html中的js
10.
在用mod_python写程序时一般约定
在url?act=disp add del edit 等操作,即在获取变量值的不同来决定显示和执行的程序。
{‘disp’: disp, 字典在书写时注意冒号后有空格,且最好一组
‘add’: add, 值一行
‘del’: del, 最后习惯加行逗号
}[act](req) 注意此处习惯将req传进去,这样在函数内就可以用请求对象的方法
注意一般此时要注意写的函数要有return值。写函数时要加上形参req
11.
对于与数据相关的标签如<td><a><li> 等要写在python中
巧用%s传入数据
12.
按键在点击时可以同时提交多个变量,以实现对程序的灵活控制
<input type=’button’ onclick = “ location.href=’?var1=value1&var2=value2’ ” />注意当此时html本身会刷新,里面js代码会初始化
在页面提交时还可以设置隐藏提交
<input type=’hidden’ name=’act’ value=’save’ />
这样就可以控制,主变量,使程序调用另一个函数,即在提交后,改变跳转到当前页的变量
13.
form指定method=‘get’
14.
MVC Model View Controller 模型视图 控制
一种软件设计典范,用于组织代码用一种业务逻辑和数据显示分离的方法,这个方法的假设前提是如果业务逻辑被聚集到一个部件里面,而且界面和用户围绕数据的交互能被改进和个性化定制而不需要重新编写业务逻辑MVC被独特的发展起来用于映射传统的输入、处理和输出功能在一个逻辑的图形化用户界面的结构中。
第三天
1.
在django download 官网下载
Django-1.4.3.tar.gz 安装包
django-docs-14-en 手册,html版
加压缩安装包后在终端python setup.py install 安装
如果原来有旧版本,要删除
/usr/lib/python2.6/site-packages中有Django-1.3删除,其中还有个django的文件夹也要删除。
然后再安装新版本。
手册是zip压缩的,右键点解压缩即可。也可用命令如下
unzip *.zip -d 新目录名 解压缩到新建的目录下
import django
print django.VERSION 打印版本号
用来检验是否安装成功
2.
Django:
开发框架(固定的开发应用平台),支持MVC ,纯python
3.
A.django-admin.py startproject mysite 创建一个工程,在终端直接输入
python manage.py runserver 启动开发服务器
可通过127.0.0.1:8000来访问
也可改变端口 python manage.py runserver 8080
改变Ip python manage.py runserver 0.0.0.0:8000
在创建库表时(1.4.4版本出错),如果出错,则将settings.py中
INSTALLED_APPS内的 django.contrib.sessions 给注释掉即可
B. 设置settings数据库
sqlite3 要写name为路径,直接创建文件即可,注意此处创建的文件一定要有’ .db ’做为后缀名
mysql 的name为库名,要提前先建立一个库
C.python manage.py syncdb 创建相应的库
D. python manage.py startapp polls 建立应用polls
E. 在polls中的models.py中加入
from django.db import models
class Poll(models.Model):
question= models.CharField(max_length=200)
CharField字符串字段,单行输入,用于较短的字符串,如要保存大量文本, 使用 TextField,CharField有一个必填参数
pub_date = models.DateTimeField(‘date published’)
DateTimeField 日期字段
class Choice(models.Model):
poll = models.Foreignkey(Poll)
choice =models.CharField(max_lengrh=200)
votes = models.IntegerField() 用于保存一个整数
F. 将polls加入到settings.py 中的INSTALLEN_APP中。激活应用,然后再python manage.py syncdb同步数据库
4.
API 应用程序接口
运行应用
python manage.py shell 进入python解释器,这样当前站点相关信息环境变量都导入进去,使用 django 和项目资源
from polls.models import Poll, Choice 导入在polls文件夹下的models.py文件中的两个类
Poll.objects.all() 显示所有数据,注意此时只显示对象
要在polls.models.py中加上
classPoll(models.Model):
def __unicode__(self):
return self.question
class Choice(models.Model):
def__unicode__(self):
return self.choice
以后再用Poll.objects.all()时即可显示内容。(重新进python环境) __unicode__与__string__作用相似,但范围要广,兼顾所有unicode编码
from django.utils import timezone
p =Poll(question=”what’s new?”, pub_date=timezone.now()) 插入一条数据
p.save() 保存插入的数据
p.question 返回内容 p.question=’newdata’ 可直接改值
p.pub_date 返回内容
filter 方法是从数据库的取得匹配的结果,返回一个对象列表,如果记录不存在返回’[]
get 方法是从数据库中缺的一个匹配的结果,返回一个对象,如果记录不存在的话,报错
Poll.objects.filter(id=1) 可以用primary-key 即 pk=1
此时返回仍是个列表
p=Poll.objects.get(id=1)
p.was_published_recently()
5.
括号中’=’两边无’ ’空格
6.
datetime.timedelta(days=1):表示时间间隔,即两个时间点之间的长度. 间隔一天时间
from django.utils import timezone
import datetime
def was_published_recently(self):
return self.pub_date >= timezone.now() – datetime.timedelta(days=1) 最近一天内访问的返回为True
7.
后台admin
将 urls.py中第4,5,16行注释去掉使url()生效
在应用程序目录中创建admin.py写入下面内容
from polls.models import Poll 引入应用表
from django.contrib import admin
admin.site.register(Poll) 将表加入到后台
将settings.py 中119行。。。。admin注释去掉
python manage.py syncdb 同步数据库
python manage.py runserver 重新运行服务
浏览器访问127.0.0.1:8000/admin
8.
使得应用APP可以运行,先建立blog应用
第一步 setting.py 的INSTALLED_APPS加上‘blog’
第二步url.py 加上 url(r'^blog/fun/$', ‘blog.views.fun’),
第一个参数是url,方法后一定要加 ’/’,第二个参数是处理方法
第三步建立blog/views.py
from django.http import HttpResponse
def fun(req): req为请求信息对象
return HttpResponse(‘hello world’)
返回处理信息 注意此方法可以直接输入字符串,但传html时要渲染
第四步启动服务 python manage.py runserver
9.
在上面第三步中
from django.http import HttpResponse
from django.template import loader, Context
def fun(req):
t =loader.get_template(‘index.html’) 加载模板
c =Context( {‘uname’: ‘tom’, ‘age’: ‘25’} ) 在字典中给出变量值。相当于格式化
html = t.render(c) 渲染数据,传入变量,注意是加载模板对象的方法
return HttpResponse(html)
注意模板的路径一定要是应用目录下的templates
且在模板中 变量要放入双大括号中
<h1>{{uname }}</h1> {{ age }}
第四天
1.
在urls.py中urlpatterns 中每一项url表示地址的映射,
url(正则表达式,匹配后用处理方法)
r’ …. ’ 字符串中的原始形式,即使特殊符号,失去意义
第一个参数 r’^blog/index/$’ 可写任意字符串,只需在浏览器中输入相同的url即可 注意 blog前不能加 ’/’ django会自动加一个,但index后面必须加 ’/ ’
不同的url可以用相同的处理方法
相同的url定义不同的处理方法时,定义在前面的处理方法有效。
2.
url模板,映射试图处理方法
1. 全字符串形式,即普通形式
2. 方法对象
在urls.py中导入 from blog.views import index1
然后再在后面加上url(r’….’, index1) 此时第二个参数不用加前面的那些,并且不用加引号,是个对象,不是字符串
3.前缀字符串
在urls.py 中下面再写一个
urlpatterns += {‘blog.views’, url()} 即可以累加使上下两个都起作用
urlpatterns中第一字参数是空字符串,如果将其加上
‘blog.views’ 则在下面的的方法中就不用加前面直接写
url(r‘….’, ‘index1’)
4.使用include加载urls
url(r’^blog/’, include(‘blog.urls’)),
在应用目录blog下建立urls.py 在其中写urlpatterns()
注意此时写的 url(r‘index/$’, ‘blog.views.index’)
其中正则与源urls.py相叠加,同时作用,在浏览器写url时要注意写全。应是(正则表达式的规则决定因其中有^和$):blog/index/
3.
静态文件放在应用程序blog下的static中。且访问时url要加’ /static/’ 由配置文件settings决定。如果在模板html中要外部引入图片 , js , css时这些文件一定要放在此目录中
<style>import url(‘/static/1.css’)</style>
<img src=’/static/1.jpg’>
其中前缀由setting中63行决定STATIC_URL
目录还可设置为下面的STATICFILES_DIRS中,注意此时路径为绝对路径,且html引入时前缀仍然不变仍为‘/static/’
STATICFILES_DIRS=(
‘/home/mystatic/’ , 注意此时不可丢最后的’/’和后面的‘,’
)
注意应用目录下的/static/仍然可用,如果在以上两个文件夹里有相同名的文件,且引入就是这个文件,则系统无法引入,谁也不起作用
并且在目录下仍然可见建立子目录如img css 等引入时只需
‘/static/img/i.jpg’ 加上即可
4.
注意在html中有url提交时,如表单的action 或者location。href等写的一定要在前面加‘/’,否则url后自动加到当前url后面去
如 action=’/index1/’ 则会跳转到8000/index1
而如果 action=’index1/’ 如果当前是index 那url会变成 8000/index/index1/
5.
在views.py中,读取html文件时,即使里面没有变量,也要经过渲染才能传值
t = loader.get_template(‘1.html’)
c = Context( {} ) 空字典
return HttpResponse(t.render(c))
6.
mv test/1.txt . 这里点代表当前路径
7.
<!- -div>test</div- -> 注释掉标签,及里面的内容
<!- -input - ->
8.
一个工程可以有多个应用blog1 blog2…
9.
1. url参数传递,form method=’’
get方式: url?…..
def index(req):
在views.py中, req.GET 是url请求时传递过来的参数,返回一个字典
可以用req.GET.get(‘age’, ‘20’) 字典的get方法取值
req.GET[‘uname’] 得到变量uname的值
post方式:
action=’/index1/’ 注意在post时必须后面加’/’
将settings中的93行 的django.middleware….注释掉
def index(req): 此时不需要形参,提交的值应该在req内一起传递过来
req.POST 也是返回一个字典
req.POST[‘uname’] 注意此处常写错为括号,返回变量名为uname的值
2. url路径方式传递,即在浏览器处传递。尽量用此方法
正则表达式分组作用是提取一部分信息
在urls中 url(r’^index/ (\w{3,6}) /(\w{3,6})/$’, ‘blog.views.index’)
def index(req, var1, var2): 注意此处对应的加两个变量
优点是:更加安全,提交后只显示值,不显示变量
在传递时直接在浏览器的url传值
http:127.0.0.1:8000/index/tom/jim 便会直接将值传到当前页面
10.
a. 位置参数与位置有关,传值时要注意先后顺序 def fun(x, y):
b. 关键字参数,与位置无关。def fun(x=1, y=2):
1.在url路径传值时,对分组进行命名,使变量值不会乱.格式是
在分组内加上?P<var1>,则当前组传入的值就会送给变量var1
url(r’^index/( ?P<var1>\w{3, 6} )/(?P<var2>\d{0, 3} )$’, ‘blog.views.index’) 第一个输入的值会送给var1,。。此处决定写入的值送给哪个变量
def index(req, var1, var2): 定义的方法接收的变量名必须与上面一致,此时两参数的位置可以随意变。
2.默认值传值
url( r’^index1/$’, ‘blog.views.show’, { ‘tempname ’: ‘index1.html’} ),注意此时极易丢逗号,这是大元组中的一项
url( r’^index2/$’, ‘blog.views.show’, { ‘tempname ’: ‘index2.html’} ),
def show(req, tempname):
t = loader.get_template( tempname )
此时可实现,不同的url调用同一处理方法,且显示页面不同。
在url后面给的那个字典,是在浏览器输入url时直接传递给后台处理方法。
3分组后直接在浏览器url位置控制显示
url( r’^(?P<tempname>\w.*)$’, ‘blog.views.show’ ),
直接将分组内的数据送给后台
def show(req, tempname):
return HttpResponse( tempname)
注意分组变量名不要与默认值变量名相同,
url(r’^index/(?P<tempname>\w.*)$’, ‘blog.views.show’,{ ‘tempname ’: ‘default_value’ } ), 如果相同时,则默认值有效
tempname的值为default_value
14.
HttpResponse(u’测试’) 此方法要传中文就要在前面加个u
第五天
1.
为什么使用模板系统
一般的,PY代码编写和HTML设计是两项不同的工作, 设计人员和HTML/CSS编写人员不应该去编辑PY代码来完成自己的工作;
其次,分离的显示和逻辑代码,会使得整个开发任务得以并行进行。
再次,一般系统对于底层代码的修改频度远远低于对界面的修改,分离的显示和底层,对于修改界面是有益处的
第一创建Template对象
第二调用Template对象的render()方法,并提供给它变量
它将返回一个完整的模块字符串内容,包含了所有标签块和变量解析后的内容
模板的渲染:一旦创建了Template对象,就可以用context来传递数据。Context:模板用它来赋值模板变量标签和执行块标签
调用Template对象的render()方法并传递context来填充模板
2.
模板组成:html css js
模板变量 : {{ uname }}
模板标签:{% 模板标签%}
3.
a= {‘name’:’tom’} 在模板中{{a.name}}
b = [‘aa’,’bb’] 在模板中 {{b.0}}
索引都用点
4.
{%for x in list%}
<li>{{x}}</li> 变量用双花括号
{%endfor%} 封装
5.
#-*-coding:utf8 -*- 与#coding:uft8区别
6.
遍历字典要注意
{%for x,y in dict.items%} 用字典本身的属性来转化后遍历 不能直接{%for x in dict%} 此处遍历的是key
7.
在模板中通过点访问 ‘ . ’ 字典,属性, 方法, 索引
注意此处有优先级问题,按上面写的顺序,优先级逐渐降低
访问的方法不能有传入参数,因在访问方法时括号都不写
8.
c= Context({‘var’:’value’}) 返回是一个列表中只有一个元素即字典。直接 c[‘age’]= 23就能将变量加进去,此处不同于普通的数据操作,普通的是应该加上c[0][‘age’]
9.
‘aaa’.upper() 转换为大写 ‘AAA’
‘AAA’.lower() 转换为小写 “aaa”
‘aa’.isdigit() False 判断是否为数值型字符串
10.
没有为变量传来值时,模板会将此变量处理为空字符串
11.
{%if%} 支持and,or,not 但不能让 and和or同时用.注意内部定义的变量,为局部变量,适用范围在endif上
{%else%} 目前版本只有两个分支,没有elif 应该有了
{%endif%}
12.
{{forloop.counter}} 在for循环内使用,为每次执行显示标号从1开始{{forloop.counter0}}从0开始
{{forloop.revcounter}} 倒序
注意此属性只能在for循环内使用
{{forloop.parentloop.counter}}.{{forloop.counter}} 可实现1.1 1.2 2.1 2.2 前面属性是指向当前循环的上一层for 循环
13.
ls | wc -l 终端中显示行数
14.
Filters 筛选 注意’|’ 两端无空格
{{ list|length}} 变量内共有多少个字符串或元素
15.
遍历复合数据
{{for x in var.0.key}} 注意仍然用点索引
16.
{# 注释内容 #} 注释方式
17.
Filter中 {{var|add:‘1’}} 1. ‘|’两端无空格
2.并且参数’1’前与冒号间也无空格
add 加
addslashes 增加’\’对’ ;’进行转义
capfirst 首字母大写
center 居中
cut:‘’切除
date 时间
views.py中 import datetime
t= datetime.datetime.now() 建立datetime对象
在模板{{ t|date:’Y m d’}} 年月日注意中间用空格隔开
dictsort
对于数据是列表的,且里面的每一项是字典,且字典都具有相同的key则可用此过滤进行排序
{{var|truncatwords:20}} 显示前20个单词,注意汉字没空格和标点的话,一句话会认为是一个单词
truncatechars :9 固定长度,字符串长度
{{var|default:’nothing’}} 如果变量值能转化为bool为False,则显示nothing
{{var|default_if_none:’it is None’}} 如果变量的值为None
则显示后面的内容
18.
在程序中的写print 会显示在服务器运行的终端页面上python manager.py runserver
19.
<hr /> 横线
20.
在views中处理数据和在模板中处理数据无差别,因均在服务器端处理
21.
from django.template import Template
t= Template(‘<html>this is a html</html>’) 动态创建模板生成模板对象,与loader.get_template同样得 到模板对象
22.
from django.shortcuts import render_to_response
return render_to_response(‘index.html’, {‘uname’: ‘tom’})
省去: loader.get_template context render HttpResponse
第一个参数是模板路径,第二个参数是传递渲染的变量。
如果没有变量则第二个参数可以不写
23.
locals() 将所有局部变量转化为字典,
a = ‘11’ locals() 返回值就是 {‘a’: ‘11’} 注意变量名也变成了字符串
24.
{%include ‘index2.html’%} 这样此模板里就可加载其它模板的页面了
25.
模板继承
第一步定义基础模板
在test.html中
<div id=’main’>
{%block 名%}
Test value
{%endblock%} 必须要封装结尾
</div>
第二步定义要嵌套的子模板 注意是个空文件,和js,css似得,但要是html的 son.html
{%extends ‘test.html’ %} 找到母模板.这句话必须是子模板的第一句话
{%block 名%} 在相对应的位置写入内容,注意会替代旧内容
重写的新内容
{%endblock%}
a如果在模板中使用 {% extends %} ,必须保证其为模板中的第一个模板标记。否则,模板继承将不起作用。
b一般来说,基础模板中的 {% block %} 标签越多越好。记住,子模板不必定义父模板中所有的代码块,因此你可以用合理的缺省值对一些代码块进行填充,然后只对子模板所需的代码块进行(重)定义。俗话说,钩子越多越好。
c如果发觉自己在多个模板之间拷贝代码,你应该考虑将该代码段放置到父模板的某个 {% block %} 中。
d如果需要获得父模板中代码块的内容,可以使用 {{ block.super }} 变量。如果只想在上级代码块基础上添加内容,而不是全部重载,该变量就显得非常有用了
{%block 名%}
{{ block.super}}
添加的新内容
{%endblock%}
e不可同一个模板中定义多个同名 {% block %} ,存在这样的限制是因为block 标签的工作方式是双向的,也就是说,block 标签不仅挖了一个要填的坑,也定义了在 父 模板中这个坑所填充的内容,如果模板中出现了两个相同名称{% block %} ,父模板将无从得知要使用哪个;
f {% extends %} 对所传入模板名称使用的加载方法和 get_template() 相同。也就数说,会将模板名称被添加到TEMPLATE_DIRS 设置之后。
g 多数情况下, {% extends %} 的参数应该是字符串,但是如果直到运行时方能确定父模板名,这个参数也可以是个变量。这使得你能够实现一些很酷的动态功能。
第六天
1.
Django中 MVC 变成MVT 原C变成v,原v由T代替
Models views templates
2.
数据库的模式发展: 网状型,层次型,关系型
在django中:model解决数据库由面向过程转向面向对象
发展出:对象型数据库 orm (object relation model)
Django通过类,对象进行db操作
数据库管理系统, 数据库, 库, 表, 记录字段
3.
MySQL 的port 3306
4.
应用目录中的model.py 进行数据库的创建
from django.db import models (默认给出)
sex_choices= ( (‘F’, ‘female’), (‘M’, ‘male’), ) 元组形式,每一个小元组是一个选项,小元组的第一个值是存储到数据库中的值,第二个值是下拉菜单显示的值。
类的每一个属性是数据库的一列
class Author(models.Model): 继承父类
name= models.CharField(max_length=30) 里面的这个参数是必须要有的
sex= models.CharField(max_length=1, choices=sex_choices)
此参数会变成一个下拉菜单形式值在上面定义
birthday= models.DateField() 以日期的形式保存,且adim在前台查看时显示日期图
def __unicode__(self):
return self.name 在查询时能够显示具体的值
5.
同步数据库后models中类建的表名为 应用程序名_类名
blog_author 小写的
插入数据 python manage.py shell
方式一. from blog.models import Author 引入刚写的类
import datetime 插入日期时要用
p=Author(name=’tom’, sex=’F’,birthday=datetime.date(1990,1,1))
p.save() 一定要保存
方式二. 数据对象 = 类()
数据对象.字段属性=字段值
数据对象.save()
注意此时如果 数据对象.新字段属性 =字段值
此时可以用,但数据库中不会增加列,用来写views方法时,可以不必再传值,将值与数据对象一块传过去
方式三. 类名.objects.create(name=’tom’, sex=’F’,birthday=datetime.date(1990,1,1))
此时不用save()
6.
Filed type 1.列的类型2.映射到form中的类型3.验证信息
7.
objects 可以理解为对象数据管理器类似于cursor游标
8.
对象的查询:
p=类.objects.all() 所有数据对象,返回为 QuerySet数据类型, p.count() len(p) 均能得出总共几条记录
count()的性能好,len()是把对象全加载到内存中,所以用count,之前记错了
可当做列表进行索引
类.objects.get(name=’tom’) 必须返回一条记录,如果记录不存在或有多条记录时,都会抛出异常。常和异常处理try结合使用
类.objects.filter(Filedlookups) 同样返回queryset类型,一条记录也是,即使返回一条但仍是queryset,不会抛出异常
Filed lookups 形式是 字段名_ _lookups = ‘ ’
exact 精确查询 name_ _exact= ‘jim’
iexact 忽略大小写。
注意MySQL此处两者无区别
contains 包含 name__contains = ‘i’ name中有i的注意是内部开头和结尾都算
icontains 查询忽略大小写,此MySQL中就有区别了
in 是否在范围内 name_ _in = [‘tom’,‘jack’]
gt 大于 birthday__gt = datetime.date(1990,1,1) 此处是数值上大于,年龄上小于
gte 大于等于
lt 小于
lte 小于等于
startwith 以。。开头 istartwith 忽略大小写
endwith 以。。结尾 iendwith 忽略大小写
range 范围内 (开头, 结尾)
year month day 年月日
weekday 星期注意1是Sunday 7是Saturday
__isnull = True 是否为空
serch regex Avg 求和 count 计数 max min stdDev
类.objects.exclude(Field lookups) 除外与filter相反
9.
链式查询 a =Author.objects.all()
a.filter(lookups).filter(lookups)…
逐级查找
Author.objects.filter(lookup1, lookup2….) 与链式查询效果相同但没有链式查询功能强大
10.
删除 a=Author.objects.filter(sex=‘f’) a.delete()
多行删除也可
11.
修改
单条 对象.name=’newname’
对象.save()
多条
i=对象.update(name=’aaa ’,age=’20’) 将数据库中所name端和age端全改为aa和20。 返回值为操作的行数
12.
写views.py时先引入写的类 from blog.models import Author
在python内如没有age字段 a.age = 20 可直接加到Author里,但传值时会一并传过去,但数据库中并没有多出一列来
13.
from django.http import HttpResponseRedirect
return HttpResponseRedirect(‘/index/’) 会直接返回到url为/index/的处理方法上
14.
a为 queryset a= a[1:2] 允许 ,列表也可以
15.
在views.py中
id=21
Author.objects.get(id=id) 可以这样用
第七天
1.
A.数据排序
Author.objects.order_by(‘name’) 按acsII码排序升序
…………………………………….(‘- name’ ) 降序排列
可以有多个参数
Author.objects.order_by(‘name’, ‘age’)
B.在数据定义中默认排序 在models.py中
class Author(models.Model):
name= …..
class Meta: 内部类实现对类更好的控制,此处无括号和参数
ordering= [‘name’] 规定按name排序
一般用order_by(‘-p_time’)来排序,上述内部类Meta的排序,有时如外键关系的话,不会让整体数据进行排序,如发微博,会先按外键用户排序,然后用户的微博按时间排序
链式反应
User.objects.filter(title=‘a’).order_by(‘name’)
先过滤后排序
2.
限制查询的数量
note =Note.objects.all[0:3] 其实就是切片操作
3.
批量删除
n1 = Note.objects.filter(title=‘o’) # 查询
n1.delete() 删除查到的所有对象
4.
常见的模型字段API
CharField(max_length=30) 字符串字段,适用于中小长度的字符串, max_length 必需参数
BooleanField(default=True): 一个布尔字段, 里面的参数可选,在前台表现为一个点击选中的小框,设置默认为True后,则默认选中
在数据库中存储是以tinyint型存储 0代表False 1代表True
CommaSeparatedIntegerField(max_length=10) 一个用逗号分割开的整数字段。其中max_length是必需的
DateField(auto_now=False,auto_now_add=False)输出日期,可选参数:
auto_now 每次保存时,自动设置为当前日期,一般用来产生最后一次修改时间。可用于完成最后一次登录功能
auto_now_add 对象第一次产生时字段设置为当前日期,一般用来产生对象的建立时间,可用于完成注册时间
DateTimeField([auto_now=False, auto_now_add=False])
与DataField一样使用,输出时间日期 。能显示时间10:34
EmailField([max_length=75]) 一个能检查值是否是有效的电子邮件地址的 CharField 。不接受 max_length参数,它的 max_length被自动设置为75
file=FileField(upload_to=’blog/static/’[, max_length=100]) 一个文件上传字段。它有一个必需的参数.
在数据库中存储upload_to + 文件名的字符串,注意没有’ ./ ’
有属性name: file.name返回将MEDIA_ROOT为根的绝对路径,如果是空,则是将工程目录作为根的路径的字符串(包含文件名),既与数据库存储内容相同。
upload_to:一个本地的文件系统路径,决定上传后文件的放在的地址,写的目录如果不存在,则会自动创建。被附加到你的setting.py文件中 MEDIA_ROOT 设置后面
在模型中使用 FileField 或者 ImageField 时,要有以下的步骤:
1. 如果定义了settings中的MEDIA_ROOT,如
MEDIA_ROOT=/my/ 则图片upload_to会将/my/当做根,
如果upload_to=’blog/static’那么图片的实际在系统的位置是
/my/blog/static. 如果不定义MEDIA_ROOT那么upload_to只能用将工程目录作为根的相对路径upload_to=’blog/static’ 不能用系统绝对路径即如/my则会报错。
在settings文件中需定义 MEDIA_ROOT ,它是要保存上传文件的目录的全路径。还要定义 MEDIA_URL ,刚才那个目录对外的访问URL。
2. 在模型中添加 FileField 或者 ImageField ,务必要定义 upload_to 选项,这样Django才知道把上传的文件写到MEDIA_ROOT 的哪个子目录中。
3. 保存到数据库中的只有文件(相对于 MEDIA_ROOT )的路径。
TextField() 大文本框
5.
Fieldoptions
TextField(blank=True) blank 与null都是允许为空,
null=True 在数据空中存储为null,
blank与 null 不同。 null 纯粹是数据库范畴的,而blank 是数据验证范畴的。如果一个字段的blank=True,Django 的管理后台在做数据验证时,会允许该字段是空值。如果字段的blank=False ,该字段就是必填的。
6.
修改model.py中表的结构后,同步无用,
1. 要到数据库中手动修改,一般直接删掉表,然后再同步数据库syncdb
2. python manager reset blog 重新创建blog应用的表,原内容消失
7.
关系数据库的强大,是建立在数据表之间的关联上,比excel要强大的多。左关联,右关联。
数据库表之间的关系包含了三种:
many-to-one
many-to-many
one-to-one
8.
settings.py配置后要重启runserver
9.
import os
os.path.basename(‘/home/1.txt’) 返回值为’1.txt’
要用此方法,不要切片字符串,这样代码灵活性强
10.
习惯上要先将settings.py的93行 middleware。。注释掉
many to one
在many方定义个属性外键
user= models.ForeignKey(User) 括号内为one方的类名
这样在many方类对象中就会有个user属性,用来直接得到one方的数据对象
如 note = Note.objects.get(id=1)
note.user 就是one方的数据对象,然后可对one方进行操作
先创建one对象
p=User.objects.create(name=’alen’)
note_set 相当于objects 同样可以理解为对象数据管理器类
是 many类名_set 注意为小写
p.note_set.create(title=’a’, content=’aaaa’) 可由one对象直接对many对象进行操作
p.note_set.all() 查看many类中所有数据
12.
.schema blog_note 在sqlite3中查看表blog_note的结构,注意此命令无分号’;’
可发现数据最后多了一列,此为one对象的id
13.
many 类在加入值时,必须要给外键id赋值,且必须是one类存在的id,或者对象user
Note.objects.create(title=’a’,content=’a’, user_id=1)
或者
a = Userobjects.get(id=1).
Note.objects.create(title=’a’,content=’a’, user=a)
指定one方对象
外键属性名_id=one表中的id
第八天
1.
many to one 中如果one方删除数据,那么many方的属于one方的数据也会相应删除,称之为级联删除
如a = User.objects.get(id=1) a.delete()
么many中 Note里所有属a的数据都会删除
2.
many to many 形式是只需在一个里面定义,双方操作相通
class A(..):
name=…
class B(..):
name=…
authors=models.ManyToManyField(A)
同步数据库,时会生成3张表,
blog_a blog_b blog_a_b通过第三张表完成表间关系记录
a=A() b=B()
两表可以分别独立的添加数据,且独自添加时可以先暂时不写关键键的字段,与ForeignKey不同
写了关键键的是主表,此处B是主表
没写Many那个键的找写有那个关键键的
用 a.b表名_set b小写
写了关键键的找没写的直接用属性
b.authors 属性名
均相当于objects
均有方法add(),remove(), all(), create()
增加关联 b.authors.add(a)
移除关联关系 b.authors.remove(a)
查看所有关联此对象的 b.authors.all()
给A表增加内容 b.authors.create(…..),增加的当然默认与b关联
a. b_set 仍然具备上述方法
一般的操作都是在主表中,直接访问定义的字段,b.authors 一般不通过 类名_set 从副表查询主表.
当副表建立数据后,要立刻 用主表对象的字段.add()来添加附表数据对象。所以副表在建立时都要用一个变量来接受返回的变量
副表 a = A.objects.create(x=’1’)
某主表对象是b b.a.add(a) 立刻将副表数据加入主表数据对象中
副表数据删除,直接 副表数据对象.delete() 即可,主表中与其关联会自动消失 a.delete() 即可
3.
echo $LANG 显示当前编码
有 zh_CN.UTF-8 en_US.UTF-8
LANG=en_US.UTF-8 设置编码
4.
在设置数据库中的字段是密码的要把长度设长,因一般是经过密码编码的
passwd=models.CharField(max_length=200)
5.
Django在form提交时的流程,要用post提交,先将settings中
的第93行注释掉
from blog.models import User 一定要先导入类表
A.自定义form
if req.method == ‘POST’:
表单数据提交处理数据
return HttpResponse(‘ok’)
或 return HttpResponseRedirect(‘/login/’)
else:
渲染到模板中,表单呈现
return render_to_response(‘index.html’, {})
B. django的form
在views.py中
from django import forms
class UserForm(forms.Form):
uname=forms.CharField(max_length=30)
passwd=forms.CharField(widget=forms.PasswordInput)
widget决定在页面上显示的标签类型
def index(req):
if req.method==’POST’:
mf=UserForm(req.POST) 传入数据用来bound绑定,为了下面的验证
if mf.is_valid() 如果验证通过为True,否则False
uname=mf.cleaned_data[‘uname’] 得到的仍为字典形式的变量集合,和GET POST得到数据类型相同
return HttpResponse(‘ok’)
else:
mf= UserForm() 只传入空值,即没有验证
return render_to_response(‘index.html’, {‘mf’: mf})
注意此处return 与大if else 相同等级,此处用来如果验证失败,则会重新显示
注意在模板中只需传入实例化类的对象即可
<table><form method=’post’>
{{mf}}
<tr><td><input type=’submit’ value=’ok’ /><td></tr>
</form></table>
即可在页面上显示出views中定义的类UserForm的每一个属性
自定义的缺点:数据从模板提交到后台后,要进行数据的转化和验证才能往数据库中存储如需要转换的:
字符串转换为datetime,import datetimedatetime.datetime.strptime(‘1990-1-1’, ‘%Y-%m-%d’)
Checkbox 要转化为bool值,checkbox 点中时,在python中的数据是on
验证是否是邮箱格式,正则匹配
Django forms 是forms.Form 的子类
1. form widgets 提供了form中的组件
2. 自动验证,是否满足
3. 不满足,会重新显示
4. 数据会自动转换为需要的类型
5.
<form>不写action时默认跳转到本身,此处要写method=’post’
网页在开始加载时都是get方法获取数据
在提交时基本原则都是用post
6.
import hashlib
pwd =hashlib.sha1(‘123123’) 将123123编码成sha1类型
pwd =hashlib.md5(‘123123’) 将123123编码成md5类型
然后
Passwd=pwd.hexdigest() 得到编码后的值,用来存储
9.
mf=UserForm()
print mf
会显示<tr><th><input type=’’ >…
有属性 mf.as_p 以放入<p>标签
mf.as_ul 以<li> 标签呈现
mf.as_table 以 <tr><td>盛放(默认项),但无<table>,要在模板中手动添加<table> 否则无法形成表格
可在模板中用,如{{mf.as_ul}}
mf1= UserForm({‘uname’: ‘tom’}) 注意传入值为字典
print mf1
会发现其中的input 多了value属性
会显示<tr><th><input type=’’ value=’tom’… >…
有传入值后,即是bound 此时验证才可能通过即
mf1.is_valid() 在输入的数据满足要求时才是True
传入的数据会自动转化为需要的类型,放在
mf1.cleaned_data中,是个字典,通过变量名进行索引得到值如mf1.cleaned_data[‘uname’]
而GET和POST得到的只能是字符串或者None
10.
在get查询数据库时接受的异常有
Try: 类表名.objects.get(name=’tom’)
except 类表名.objects.model.DoesNotExist, msg: pass 没有得到数据
except 类表名.objects.model.MultipleObjectsReturned, msg: pass
得到多个数据
第九天
1.
name=forms.CharField(widget=….)
前面的CharField为数据类型约束条件
widget定义input表现类型
2.
f = forms.CharField() 记得前面加forms
f.clean( ‘aaa’) 用来验证信息,并抛出出现的异常,可以用来测试数据是否合格。在终端中操作。
数据类型有
BooleanField 布尔值
CharField 注意此参数可以不写max_length,与models中的区别
ChoiceField 默认的widget是Select传入值用参数choices接受二元元组
下拉列表
a= ( (‘f’, ‘female’), (‘m’, ‘male’) )
sex=forms.ChoiceField(choices=a )
小元组的第一个值为提交的值,第二个值为html中option的值
单选sex=forms.ChoiceField(widget=forms.RadioSelect ,choices=a)
DateField 数据要是datetime.date类型
DateTimeField
EmailField 邮箱
FileField 上传文件,图片
ImageField 上传图片
还有很多见手册Built-in Field classes
3.
Field的参数设置。Core field arguments
required=False 此时对应数据项可以不填写,如果不写此参数
默认是True,即必填项
label=’姓名’
在html中<label>类属性名</label>
name=forms.CharField(label=’姓名’) 不加label时在前台只显示类的属性名,加此参数后,就显示参数的值
initial 初始化数据
name=forms.CharField(initial=’alen’) 相当于bound,注意赋初值了,如果没填,则验证也能通过
help_text 设置提示信息,在页面显示时就显示在对应的数据框下方 help_text=’请输入。。。’
error_messages 修改默认验证没通过时的提示信息,值为字典,只接受django内默认的异常
name=forms.Char.Field(error_messages={‘required’:‘ 此项必须填’}) key为本身自带的验证机制的异常,可见于手册的
Form fields 里的Built-in Field classes 里的每一项有个Error message keys 。只能用其中的异常
validators 追加校验,值为列表,每一项是函数名
可以直接forms.ValidationError(‘错误’) 这样就不用引入下模块了
from django.core.exceptions import ValidationError
def fun(value): 要有形参来接收 数据
if value.isdigit():
raise ValidationError(‘ 不能是纯数字 ’)
最后一定要抛出异常,括号中的内容是验证不满足后出现的提示信息。是error_messages 出现在前台的相同位置
class 中passwd=forms.CharField(validators=[fun1, fun2,…])
4.
f =UserForm(req.POST)
f =UserForm({‘name’: ‘tom’}) 此时皆是往里传值,req.POST也是类似字典的数据,故两者都是bound
5.
重定向
Django: HttpResponseRedirect(‘/index/’)
Js: window.location.href=’’ location.assgin(‘url’) location.replace(‘url’) history.forward() history.back() history.go()
HTML : <a> <form> <meta http_equiv=’refresh’
content=’5;url=http://www.baidu.com’ />
数据的传递
Js àHTMLàDjango 客户端到服务器
DjangoàHTMLàJs 服务器向客户端发送数据
当然ajax是特例,它是直接由js提交
6.
‘123’.isdigit() 返回True 判断是否是数值型字符串
‘abc’.isalpha() 返回True 判断是否是无数字的字符串,即全字母
7.
自定义django中的form结构
mf=UserForm()如果不自定义只需将mf传入模板即可自动生成类中所有属性定义的input项
自定义只需拆开自己写即可,但一定要注意id name 与属性的对应关系
如class UserForm(forms.Form)
uname=forms.CharField()
在html中可以写
<form method=’post’>
{{mf.non_field_errors}}
<div>
{{mf.uname.errors}} 错误提示
<label for=’id_uname’>Uname:</label>
{{mf.uname}} 类中的属性
</div>
8.
文件上传:
客户端在<form>中必须要设置
method=’post’
enctype=’multipart/form-data’
服务端
req.POST 普通表单的数据存放的类似字典的数据
req.FILES 上传的文件数据存放的类似字典的数据
REQUEST通配POST和GET得到的数据也是类字典的数据类型
name=req.REQUEST[‘name’] 可得到POST和GET的数据
file=req.FILES[‘file’] 得到上传的数据对象,UploaderdFile类型。req.FILES本身为类似字典的数据类型
file=mf.cleaned_data[‘file’] 当然也能得到上传数据对象,此处数据无需转换,所以与req.FILES通用,cleaned_data中的数据应该是验证后且由django转换过的数据,
而req.POST应该是没有转换的数据
mf=UserForm(req.POST, req.FILES) 如果在views.py中类有
headimg=forms.FileField() 这个上传文件的数据项,那么在bound这个类时一定还要传 req.FiLES这个参数
上传后的数据同样存放在mf.cleaned_data这个类似字典的数据中
headimg=mf.cleaned_data[‘headimg’]
得到源文件名(不包含路径)的属性 filename=headimg.name
读取上传文件的方法read()
x=headimg.read() 返回字符串,可以读取图片
再写入文件即可
file(filename , ‘wb’).write(x)
上传的文件名义放在内存中,但实际是放在临时文件中,故此时对文件读写,会耗费大量的内存资源,因此用下办法,将文件保存
chunks() 生成一个上传的文件的generator生成器,然后用循环来写入数据
f=file(filename, ‘wb’)
for chunk in headimg.chunks():
f.write(chunk) 循环写入节省内存
f.close()
headimg.multiple_chunks() 如果上传文件大于2.5M则返回True,(大小可修改),一般用于判断,如果文件大,用上面的chunks()来保存数据
9.
Widget
sex=forms.ChoiceField(choices=sex_lib,
widget=forms.RadioSelect)
写上此参数后就形成单选,不写则是select下拉菜单形式
多选????
Callable
第十天
1.
ModelForm的作用是直接通过models中的表直接生成form,不必再自定义form里的每一个属性。
先在models中建立一个表User,然后再views中
from blog.models import User
from django import forms
classUserForm(forms.ModelForm):
birthday=forms.DateField() 此项为自定义的属性,可以再前台显示,注意并不能保存到User数据库中,某些情况下并不是要将提交的信息全部保存到数据库中,或者保存到另外的一张数据库表中
class Meta:
model=User 直接生成models表对应的form
然后在处理方法中
fields=(‘name’, ‘passwd’) 如果写了这个属性,有连个作用一个是,在生成forms时只显示元组内的字段名,而且还起到排序的作用,按元组内的顺序进行显示
exclude=(‘birthday’, ) 于fields相反,不显示的项
widgets={ 用来重新决定models中的字段名的类型
‘passwd’: forms.PasswordInput(), 括号写不写都行
} 一般只用于将密码改为不直接显示显示
def index(req):
if req.method == ‘POST’:
uf= UserForm(req.POST, req.FILES) 有上传文件也要有此参数
if uf.is_valid():
uf.save() 只有调用了此方法数据库才能保存数据,models的特性
return 。。。。。
数据库仍然按照models中对上传文件的保存规则,保存路径
但此处上传的文件会直接上传到upload_to指定的路径上,不必在手动保存
2.
u1=User.objects.get(pk=1)
uf=UserForm(initial=u1)
uf=UseForm(initial={‘name’:‘tom’})
使前台呈现有初值,应该用于else中,使具有初值
3.
models中某项的属性blank=True,则想对应的再forms中验证时就相当于required=False
4.
在models中,改生成form后的前台显示的变量名
name=models.CharField(max_length=30, verbose_name=’姓名’ ) 相当于forms中的label
也有help_text=’ 输入格式’ 作用forms中的help_text相同
5.
dir(a1) 返回以列表的形式的a1对象的全部属性和方法
6.
重新保存得到的数据到数据库,一般用于对密码进行处理
不能用 uf.cleaned_data[‘passwd’] =’abc’ 此只是对后台的数据进行了修改在uf.save()后,并不能保存进数据库,应该用
uf.instance.passwd=’abc’ 对数据实例进行修改
uf.save() 保存修改后的数据到数据库
其中的uf.instance相当于数据对象如u1=User.objects.get(pk=1)
中的u1
将密码编码后保存如数据库
passwd=uf.cleaned_data[‘passwd’]
uf.instance.passwd=hashlib.sha1(passwd).hexdigest
uf.save()
7.
自定义校验
class UserForm(forms.Form):
def clean_字段名(self):
name=self.cleaned_data[‘name’]
……..
例如用于双密码验证
def clean_repassword(self): 用下面的密码字段
password = self.cleaned_data[‘password’]
repassword = self.cleaned_data[‘repassword’]
if password != repassword:
raise ValidationError(‘两次输入不一致’)
8.
模板错误,有时要重启runserver
9.
客户端 : cookie
Server: session
10.
BàS: request server获取cookie,从request获取
SàB: response response设定客户端的cookie
11.
response=HttpResponseRedirect(‘/shop/’) 获取response对象
response.set_cookie(‘name’, ‘tom’, max_age=60)
设置客户端的cookie
return response
12.
在浏览器---编辑---首选项---隐私---使用自定义历史设置—显示cookie 查看设置的cookie
13.
HttpResponse HttpResponseRedirect render_to_response
均是response对象
14.
response.set_cookie(key, value, max_age=60 )
key是变量的名
value是变量的值
max_age 是cookie保存的时间,单位是秒
在上面的显示cookie项下面有个过期时间可查看
15.
name=req.COOKIES(‘name’) 获取cookies
16.
打开一个url时,浏览器检查本地是否有对应站点的cookie,如果有,连同cookie发送到site ,服务器通过
request对象.COOKIES 进行获取
response对象.set_cookie(key, value, max_age=) 进行设定
获取时注意,只要是相同站点的都会获取到,如只要是127.0.0.1的就会都获取到。
response对象.delete_cookie(‘name’)清除指定cookie参数
只能清除一个参数,且如果没有也不会抛出异常
第十一天
1.
t=loader.get_template(‘1.html’)
c=Context()
c[‘name’]=’Tom’
html=t.render(c)
return HttpResponse(html)
此处还可以用write方法往里渲染
response=HttpResponse()
response.write(t.render(c)) 可多次写入数据
return response
2.
def fun(a): def fun(a=’’):
均是位置参数,即必须要传值
3.
response.delete_cookie(‘name’) 删除cookie中变量name
4.
用session,服务器端储存信息,储存到数据库中,表名是django_session,即在settings中114行默认是打开的
5.
request 是Request的对象
response是HttpResponse的对象
6.
在views中
def userLogin(req):
req.session[‘name’]=’tom’ request对象来设置session,注意session为小写 用于自己定义的用户登录,先创建储存用户信息的表UserModel ,注册时将用户信息写入表中 ,登录时将用户名保存到session中,后就可以当做是用户已登录,以后再其它模板中就可以直接显示用户名,相当于系统自带User的login。注销用
req.session.clear()
def shop(req):
name=req.session[‘name’] 读出服务器中session的内容
注意在客户端的cookie中有了一个sessionid ,与服务器中的表
django_session 中的session_key相同,一定是唯一的
7.
req.session.set_expiry()
设置有效期: 数值300单位是秒
Datetime类型数据
0 关闭浏览器时清除session,一般设此项
req.session.clear() 用于自定义的用户注销
清楚session 清除后会看到。在django_session中的内容与清楚之前不同,虽然浏览器还会保有之前的sessionid,但已经无法对应的上
如果手动清楚浏览器中的sessionid即cookie则同样无法连接的上
8.
Python中 a != 1 也可以写 a is not 1
9.
如何创建auth用户即相当于root
from django.contrib.auth.models import User
引入系统自带的User表,此表储存用户信息可用admin来登陆
user=User.objects.create_user(username, email=None, password=None )
注意此处三个参数的顺序不可错
此命令用往数据库中添加信息,即创建admin用户
注意与普通的表操作不太一样
在数据库中表名为 auth_user
此处在写入密码时不必转码,会自动编码后写入数据库中
此时在admin登陆后。在User表中的新增的一项中,把里面的staffstatus点上即可登陆
10.
后台验证
from django.contrib.auth import authenticate
user=authenticate(username=’jim’, password=’123456’)
如果两个参数都匹配,则返回user数据对象,如果不匹配则返回user为None
11.
用户登陆,用户会话
from django.contrib.auth import login
login(req, user) 在方法内直接用即可,此处req为传入到方法中的参数req,user为10条中产生的数据对象。保存user的id到session中,当然在settings中的session middleware开启,应该是92行(默认是开启的),注意不是post注释掉的那行
user=authenticate(username=’jim’, password=’123456’)
if user is not None: 如果验证通过了
login(req, user) 登陆
return ……….
else:
return HttpResponseRedirect(‘/login/’)
一定要先验证然后再login因为,login需要验证时产生的数据对象user。如果user为None则login会抛出异常
注意自己写的方法就不要再用login了,会重名重定义
12.
req.user 即django自带的User的数据对象,当前登陆的对象
req.user.is_authenticated() 验证用户正常登陆返回True,没有登陆返回False。即看前面是否有log(req, user),执行成功,就是True,没有login则为False。注意此处的req.user中的user是django中User的对象,并非是我们自己手动如10中产生的。为当前登陆的User的数据对象
req.user.username username字段即用户名
13.
User本质上还是session,只是对session进行了高级的封装
14.
from django.contrib.auth import logout
logout(req) 退出,注意只有一个request对象参数
如果没有登陆,也不会抛出异常
def uLogout(req): 注意方法名不要用logout与系统重名
logout(req) 即可退出删除session
return HttpResponse(‘Bye’)
15.
用ModelForm写User的form
class UserForm(forms.ModelForm):
username=forms.CharField() 此处重载username的目的是去除,一开始就显示出来的text_help。注意重载后仍然能够保存到User中
class Meta:
model = User 生成form
fields = (‘username’, ‘email’,‘password’) 限定显示的项
widgets={‘password’: forms.PasswordInput} 隐去密码
16.
修改密码
u=User.objects.get(username_ _exact=’jim’)
u.set_password(‘newpassword’) 设定新密码
u.save() 保存
注意只有set_password 没有set_username其它的
第十二天
1.
Auth User扩展
User表内的信息量有限,为了拓展每个user的信息存储量
1. 直接修改User表。 有局限性,需要root权限
2. 建立一个从表
2.
建立User从表
settings中加上
AUTH_PROFILE_MODULE= ‘blog.UserProfile’ 加引号
注意是module不是model,后面的第一个是应用名,第二个是models中的表名,注意中间没有models
这条指令的主要作用是使主表get_profile()方法可以用来当数据资源管理器,类似于objects,得到UserProfile中单独的一个对象,注意此处其实是 one to one
在models中
from django.contrib.auth.models import User 先引入User表
class UserProfile(models.Model):
headimg=models.FileField(upload_to=’blog/static’)增加的新字段
user=models.ForeignKey(User, unique=True) 用外键与User建立关联
在views中
from blog.models import UserProfile
from django.contrib.auth.models import User
user=User.objects.create_user(username, email, password) 先保存User中的字段
UserProfile.objects.create(user=user, headimg=headimg)
一定要给user字段传上面的User的对象,
3.
在models中headimg=models.FileField(upload_to=’blog/static/’)
此处会自动创建目录
在forms中headimg=forms.FileField(),当在models中有FileField时,
UserProfile.objects.create(headimg=headimg) 保存时,图片会自动上传到upload_to目录下,不必在手动保存
4.
user=User.objects.create_user(username, email, password)
user.get_profile()找到user相关联的UserProfile表中的数据对象
相当于objects
user.get_profile().tel 找到关联表中tel字段的值
user.get_profile().headimg 关联表中headimg字段的值,为文件对象
5.
非root用户,的用户对象们
users=User.objects.exclude(username__exact=’root’)
6.
DoesNotExist 出现此异常,可能是User表与UserProfile表的数据不统一所致的,只要将两表里除root外的所有数据删除即可,可能是因为主表中有的用户在从表中没有对应的数据,在取值时,出现异常
也可能是用User.objects.get(id=id)数据没找到
7.
Apache运行django
安装mod_wsgi 光盘packages中有rpm包,也可yum安装
8
a. 先python manager runserver 运行没有异常后
b. /etc/http/conf.d/wsgi.conf 如果之前配置了mod_python那会有python.conf,要先将此文件删除,或改后缀
WSGIScriptAlias / /root/web01/web01/wsgi.py
加载wsgi模块,使apche支持python,后面是直接到工程下的此文件的全部目录
WSGIPythonPath /root/web01/
访问指定的目录时,将控制权交给wsgi,后面是工程目录路径
最好放在为/var/www/html/web01/web01
不知为何下列有时能成功,但绝不能放在root下,下例路径仅为参考,一般不正确
<Directory /root/web01/web01> 到wsgi.py所在的目录
<Files wsgi.py>
Order deny,allow
Allow from all
</Files>
</Directory>
上几行为ACL 即Access Control List 访问控制列表,是路由器和交换机接口的指令列表,用来控制端口进出的数据包
设置静态文件路径
Alias /static/ /root/web01/sitestatic/
别名 引用的url,图片引用等会需要url前缀时 工程下创建的一个目录,用来存放静态文件
<Directory /root/web01/sitestatic> 静态目录路径
Order deny,allow
Allow from all
</Directory>
然后要settings.py中设置
59行STATIC_ROOT=’/root/web01/sitestatic/’ 设绝对路径与上路径一致
运行 python manage.py collectstatic 会将应用级别的工程目录下的所有静态文件复制到定义的目录下
c.重启apache服务,浏览器直接输入
127.0.0.1/index url为urls.py设置的,此时不必加8000端口,通过apache服务来运行django
d. 设置错误页面在templates模板目录下建立文件名为
404.html 500.html 且将settings.py中第三行DEBUG=False
9.
uname -a 看系统版本
编外篇
1.
翻页只需解决当点击页面上的链接或按钮时,实现在python程序代码内一个变量,持续累加或累减。
思路:在模板内对数据加一或减一,然后将处理后的数据提交到python代码中,然后再传入到模板上,实现数据的连续性
Django翻页
{%if page == last_page %} 在模板中判断边界简单
{%elif last_page == ‘0’%} 消除当一条也没有时显示下一页 链接的bug
{%else%} 注意在判断page==’1’ 或last_page注意两边数据类型要相同,都要是str,从模板中提取的可能是unicode类型,但是没关系,可以作为str类型,且能相等
<a href=”?page={{page|add:’1’}} ”>下一页</a> 注意此时变量在引号内部
{%endif%}
在python内
now_page = req.GET.get(‘now_page’, ‘1’) 得到提交的变量值
if now_page == None:
now_page = ‘1’ 字符串的1
x =divmod(共条, 每页条)
if x[1] ==0: last_page=x[0]
else: last_page=x[0]+1 得到最大页
i = 2 每页显示几条内容
start=(int(now_page )-1)*i 每页起始的条索引
users =usersall[start: start+i] 切片
render_to_response(‘index.html’, {‘users’: users, ‘now_page’: now_page, ‘last_page’: last_page})
Mod_python翻页
在js中 up.onclick = function(){
page+= 1 处理数据
this.href= ’?page=’+page 页面url提交变量到python
}
在python中
page=util.FieldStorage(req).get(‘page’,‘1’) 得到url提交的变量
req.write(html%page) 再将变量传入到html中
在html内
<input type=’text’ id=’txt’ value=%s> 此处接收从python中传入的page
js内 page = parseInt( txt.value ) 将值赋给page作为初值
在js中判断边界,django用post提交时用
直接在js中写
If(now_page== ‘1’){
up_button.disabled= ‘disabled’;
}
If(now_page ==last_page){
next_button.disabled = ‘disabled’;
}
js翻页代码:
up_button.οnclick= function(){
page_i.value =parseInt(page_i.value) - 1;
form_id.submit(); 调用表单对象的submit()方法提交
}
next_button.οnclick= function(){
page_i.value=parseInt(page_i.value) +1;
form_id.submit();
}
在页面每次加载时js都会初始化,如果条件不满足,则不会执行if中的程序,即若不满足条件,按钮都是可用的,不用考虑设置了disable后,再使按钮可用的问题。
2.
字典,元组,列表多行写时,注意将最后的括号与名对齐
Aaa = {
‘aaa’: ‘222” 数据缩进
}
字典套字典时也要对齐
‘aaa’:{
……
}
3.
中文做字典的key时前面要加u,否则可能传输不了信息
4.
注意模板中调用方法不用加(),容易和python中混
如 {{dic.items}} 在python中应dic.items()
5.
在模板中的代码执行要有连续性,比如在for循环内执行时不能同事进行python中传值
6.
信息可以
1.大分类如经济文化作为key,里面的新闻标题以元组形式作为value,然后将所有的新闻标题放在一个字典里。
2. 可以全都放在一个字典里,字典的套字典
nav = {
key1‘js’:{
key2‘j20’:‘成功试飞’,
}
}
点key1选中子标题,并显示子标题,点key2选中内容,并显示内容。
关键的步骤是,在点key2时如如何向python中传递第一步中的key1的值。可以这样:
<a href=’?key1={{key1}}&key2={{key2}}’>子标题</a>
注意此处变量{{key1}}的值,是在第一次点key1时,由python转传回到模板中的,以实现,对上一层目录的保存,然后再点选key2时,便可同时将上一次点的key1传到python中。
7.
return 有时出现缩进错误时并不会报缩进错误,如果
ruturn HttpResponse出现缩进错误时,会说没有HttpResponse对象
8.
在模板中的变量之间直接写即可,不必用‘+’相连
9.
在python中变量是什么数据类型, {{var}} 模板中也是相同的数据类型。
Python获取模板提交的变量 req.GET 得到的是字符串
10.
安装python编程软件,解压后进去
python setup.py install
11.
将代码放入linux脚本中实现一键启动
#!/bin/bash
python manage.py runserver
firefox 127.0.0.1:8000/index/
但注意此时服务器开启后后台运行,关闭时需要手动kill
12.
Django中的变量不能写到js中,且当js和django同时向一个value赋值时,js有效,既js最后执行。提交值时,js最先执行
13.
req.POST req.GET req.REQUEST 是页面提交的信息,数据类型为QueryDict
uf=UserForm(req.POST) uf.is_valid() uf.cleaned_data 是验证后转换为forms格式后的数据如datetime.date(),数据类型为字典 ,且之前一定要有 uf.is_valid()
14.
如果出现ViewDoesNotExit 错误,则很有可能是views,py中定义的类form中出现了错误,既Field type 写错了如
name= test_error_forms.CharField() 这类错误就会出现上述情况
参数如widget写错也会报错
15.
定义的方法内出现错误,在方法被调用前,系统不会检查到错误
16.
对form初始化方法的区别
Uf= UserForm( {‘name’: ‘tom’} ) 这样初始化的话,django会直接显示其它字段的 required错误:This field is required
Uf=UserForm( initial={‘name’: ‘tom’} ) 这样初始化就不会出现required的错误,要用这种方法
17.
注销后,req.user.username=’’ 在模板中可以用来判断是否是登录
正规用 {% ifreq.user.is_authenticated() %} 来判断是否登录
如python中 user=req.user 将user传入模板中
{%if user.username == ‘’ %}
{%else%}
<ahref=..>注销</a>
{%endif%}
18.
类间的引用,如models.ForeignKey(UserForm) 则只能引用在本身类上面的类,既有先后顺序
19.
类是先加载属性,然后才运行def __init__(self)
20.
from blog.models import *
引入全部的类
21.
在一对多是ManyToManyField ,在从副表找主表时一定要注意,找到的是个列表型数据,当然列表中只有一个主表数据,在模板中一定注意
{{postdata.user_set. all. 0.username}} 极易丢all.0
而在django代码中 postdata.user_set.all()[0].username
() [0] 易错
22.
模板继承{%extends ‘base.html’%} 只需写在模板代码前即可,且子模板,可以独自定义自己的css,但是<style></style>一定要在
{%extends ‘base.html’%}上面
子模板在block外的添加标签无效,如在{%block nav%} 外添加<h1>test</h1> 则不会显示
23.
子模板中实现背景图片随着内容变,
<div id=’img1’><img src= ‘ /static/{{imgname}} width=’500px’ ></div>
将此div设为 #img1 { position:absolute; z-index: -1;} 从文档流中删除,然后沉底
24.
副表找主表数据字段时注意
25.
uname -a 看系统版本
26.
不能往模板中这样传值 {‘req.user’: req.user} 既变量不能有点
27
在模板判断当前用户登录与否用用户名来判断如
{%if user.username == ‘’ %} 看是否为空。User为req.user传入值
28.
模板中 ‘=’ 两端必须有空格 如 user.username == ‘ alen’
模板汇总当值为布尔值时不能 {%if x == True%} 无效
应直接 {% if x%}
在模板中一个变量如果没有得到值那么就是None,而不是‘’空字符串, 例如没有渲染的变量var
{%if var == ‘’%} (不能{%if var%} 无效)
test 不会显示test
{%endif%}
{%if var == None%} (None也不能{%if var%} 无效)
test 则会显示test
{%endif%}
29.
Get取值时url不能识别看 ‘?’ 是否不是英文格式
30.
恢复邮件
If req.method == ‘POST’:
Pass
Else:
ef=EmailForm(initial={‘foruser’: foruser}) 初始化即可
31.
u=User.objects.all()
u[0].username= ‘jom’ 是无法改变p[0].username 的值的
应该 t=u[0] t.username = ‘jom’ 才可以赋值,记得最后
t.save()
32.
参数get提交时最好用url路径传值,省事 r’index/(\d+)/’
33.
<form action= ‘ . ’> 都要写上action,因有些浏览器不认,写上后兼容性强
34
当一个页面有两个以上功能时,如有显示和提交时,提交的action不要写当前的url,数据会乱,要写到另一个url上,处理完再跳转回来即可
35.
上次登录时间??????
36.
主从表的判断,是从项目目的为出发点的。将关键键写在主表中
37.
postdata =forms.ForeignKey(‘ PostData’) 将类名加引号,既可关联到定义在主表下方的副表了
注意django系统的User表不能加引号
38.
对副表的操作,一般都是从主表对象开始,这样不容易乱
39.
自定义校验 def clean_password(self): 一般用于form各字段间关系的校验, 利用 self.clean_data[‘ ’] 来得到本表单的字段提交的值。
追加校验,一般用于,对字段本省的要求如,必须是字母数字下滑线
均不能再校验方法内用 req的方法属性如 req.user req.session[]
40.
动态更新下拉列表
将数据渲染进模板,不要用form
render_to_response(‘index.html’, {‘sortdatas’: sortdates})
模板中
<select name=’sort’ id=’id_sort’ >
<option value=’’> --</option> 可以提交空值时,此value属性必写,不然会提交 ‘--’
{%for x in sortdatas%}
<option value=’{{x.sort}}’>{{x.sort}}</option> 动态生成下拉项
{%endfor%}
</select>
Views中 sort=req.POST[‘sort’]不能用clean_data
动态生成多选
依然将数据渲染进去
{%for x in sortdatas%}
<input type=’checkbox’ name=’sort[]’ value={{x.sort}} id=’{{x.id}}’/>+
<label for=’{{x.id}}’> {{x.sort}}</label>
<endfor>
在views中
sort= req.POST.getlist(‘sort[]’) 此方法可以得到提交的多个值的列表,注意此处是POST,因渲染进去,不是用的forms不能用
clean_data
41.
用apache发布时图片的url最后不能加 ‘/’
如 <img src=’/static/{{imgname}}’ /> 可以
但 <img src=’/static/{{imgname}}/ ’ />不可以
42.
Wsgi apache 发布
1. 将工程放在 /var/www/html/中
2. 改用户为apache 改权限为777
3. Settings中的 MEDIA_ROOT 设置为据对路径可以直接设为
/var/www/html/lt1/blog/static/
4.
在wsgi.py apahe配置中静态文件也可以直接设置为
/var/www/html/lt1/blog/static/
5.
在不用admin时,就不必收集静态文件了,最好也不设置
STATIC_ROOT
43.
MEDIA_ROOT=os.path.join(os.path.dirname(__file_ _), ‘/mymedia/’).replace(‘\\’, ‘/’)
如果工程为 weibo 应用为 appweibo ,应用要放在weibo/weibo
中 INSTALLED_APPS中是 ‘weibo.appweibo’
设置上传目录到 weibo/weibo/mymedia ,与appweibo 统计目录
TEMPLATE_DIRS = (
os.path.join(os.path.dirname(__file_ _), ‘/templates/’).replace(‘\\’, ‘/’),
)
模板目录设置为与appweibo 和mymedia同级目录