一、Model连表操作
一对一和一对多
表结构如下:
1
2
3
4
5
6
7
8
9
10
|
class
user_type(models.Model):
name
=
models.CharField(max_length
=
50
)
class
user(models.Model):
username
=
models.CharField(max_length
=
50
)
password
=
models.CharField(max_length
=
50
)
email
=
models.EmailField()
usertype
=
models.ForeignKey(user_type)
user.objects.
filter
(usertype__id
=
1
).values(
'username'
)
|
示例
1
2
3
4
5
6
7
8
|
# 查询user表中,用户类型为管理员的所有用户
data
=
user.objects.
filter
(usertype__name
=
'管理员'
)
# 取单字段(比如只取username字段)
data
=
user.objects.
filter
(usertype__name
=
'管理员'
).values(
'username'
)
# 大于条件
data
=
user.objects.
filter
(usertype__id__gt
=
3
)
|
这里通过__(双下划线)表示连表查询,比如usertype__name相当于操作到了user_type表的name字段。
多对多关系
表结构如下:
1
2
3
4
5
6
7
8
9
|
class
user(models.Model):
username
=
models.CharField(max_length
=
50
)
password
=
models.CharField(max_length
=
50
)
email
=
models.EmailField()
usertype
=
models.ForeignKey(user_type)
class
groups(models.Model):
gname
=
models.CharField(max_length
=
255
)
guser
=
models.ManyToManyField(
'user'
)
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
|
user_obj
=
models.user.objects.get(name
=
u
'tuchao'
)
user_objs
=
models.user.objects.
all
()
group_obj
=
models.groups.objects.get(gname
=
'dev'
)
group_objs
=
models.groups.objects.
all
()
# 添加数据
#group_obj.guser.add(user_obj)
#group_obj.guser.add.add(*user_objs)
# 删除数据
#group_obj.guser.remove(user_obj)
#group_obj.guser.remove(*user_objs)
# 这里有点绕,用户表的对象.组表的名称(与用户相关系的表其中有定义与用户表的多对多关系)_set.add(组表的对象)
# 添加数据
#user_obj.groups_set.add(group_obj)
#user_obj.groups_set.add(*group_objs)
# 删除数据
#user_obj.groups_set.remove(group_obj)
#user_obj.groups_set.remove(*group_objs)
# 获取数据
#print group_obj.guser.all()
#print group_obj.guser.all().filter(id=1)
# 获取数据
#print user_obj.groups_set.all()
#print user_obj.groups_set.all().filter(gname='tuchao')
#print user_obj.groups_set.all().filter(gname='tyz')
# 使用MySQL事务的方式完成多对多关系的数据插入,当使用事务方式的时候,在同一个事务中的语句要么全部执行成功,要么一个都不会执行,保证了数据的完整性。
#导入相关库
from
django.db
import
connection,transaction
try
:
''' 启动事务 '''
with transaction.atomic():
''' 先给用户信息表插入数据 '''
user.objects.create(username
=
username,password
=
password,realname
=
realname,email
=
email,ugid
=
group_id)
''' 然后通过用户名获取该条记录的数据,取出对应关系的ID值插入到关系表 '''
d1
=
user.objects.get(username
=
username)
uuid
=
d1.uid
ugid
=
d1.ugid
userandgroup.objects.create(gid
=
ugid,uid
=
uuid)
except
Exception,err:
print
(err)
|
二、Form 创建自定义错误信息
forms.py的文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
class
RegisterForm(forms.Form):
username
=
forms.CharField(widget
=
forms.TextInput(attrs
=
{
'class'
:
'user_name'
,
'placeholder'
:
'用户名'
}),help_text
=
'100 characters max.'
)
password
=
forms.CharField(widget
=
forms.PasswordInput(attrs
=
{
'class'
:
'pwd'
,
'placeholder'
:
'密码'
}))
real_name
=
forms.CharField(widget
=
forms.TextInput(attrs
=
{
'placeholder'
:
'真实姓名'
}))
email
=
forms.CharField(widget
=
forms.EmailInput(attrs
=
{
'placeholder'
:
'Email'
}))
gender
=
forms.BooleanField()
# 这里的'placeholder':'用户名' 是input里面的参数。 如: <input name="hostname" placeholder="hostname" />
class
AdminHostAdd(forms.Form):
othername
=
forms.CharField(widget
=
forms.TextInput(attrs
=
{
'class'
:
'othername'
}),error_messages
=
{
'required'
:(
'业务名不能为空'
),
'invalid'
:
'业务名格式错误'
})
hostname
=
forms.CharField(widget
=
forms.TextInput(attrs
=
{
'class'
:
'hostname'
}),error_messages
=
{
'required'
:(
'主机名不能为空'
),
'invalid'
:
'主机名格式错误'
})
hardconfig
=
forms.CharField(widget
=
forms.TextInput(attrs
=
{
'class'
:
'hardconfig'
}),error_messages
=
{
'required'
:(
'硬件配置信息不能为空'
)})
wip
=
forms.IPAddressField(error_messages
=
{
'required'
:(
'外网IP不能为空'
),
'invalid'
:
'IP格式错误'
})
lip
=
forms.IPAddressField(error_messages
=
{
'required'
:(
'内网IP不能为空'
),
'invalid'
:
'IP格式错误'
})
# error_messages:required对应的是当提交内容为空所提示的信息,invalid则表示提交的数据格式错误所提示的信息。
# 在页面中输出自定义错误信息
# 在功能函数中截取的部分代码,获取自定义错误信息
ret
=
{
'data'
:
None
,
'error'
:
'None'
}
ret[
'data'
]
=
form
firstmessage
=
form.errors.as_data()
# 将获取的错误信息传给字典,key为error
ret[
'error'
]
=
firstmessage.values()[
0
][
0
].messages[
0
]
# 在输出信息的时候返回页面和字典
return
render_to_response(
'admin-host-add.html'
,ret)
# 在Html中获取返回的字典数据
<span
class
=
"hostaddstatus"
>{{ error }}<
/
span>
|
三、学习使用Ajax
Ajax的基本语法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
/* 首先引入Jquery */
<script src=
"/static/assets/js/jquery-1.12.0.js"
></script>
<script type=
"text/javascript"
>
function
DoAjax(){
/* 获取选定元素的数据 */
var
temp = $(
'#text01'
).val();
$.ajax({
/* 提交请求的url */
url:
'/ops01/ad/'
,
/* 提交请求的方式 */
type:
'POST'
,
/* 返回的数据,key:value */
data:{data:temp},
/* 请求成功所执行的方法 */
success:
function
(arg){
console.log(
'success'
);
},
/* 请求失败所执行的方法 */
error:
function
(){
console.log(
'failed'
)
}
});
}
</script>
|
功能实战
实现登陆页面在没有登陆的情况下检测用户名是否存在,然后通过Ajax实现密码错误检测和登陆跳转。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
# Python 后端功能代码实现
#!/usr/local/python27/bin/python2.7
# coding=utf8
# noinspection PyUnresolvedReferences
from
django.shortcuts
import
render
from
ops01.forms
import
RegisterForm,AdminHostAdd,CreateGroups
from
django.http
import
HttpResponse
from
django.shortcuts
import
render_to_response
from
ops01.models
import
*
from
django.db
import
connection,transaction
import
json
def
Login(request):
if
request.method
=
=
'POST'
:
username
=
request.POST.get(
'u'
,
None
)
password
=
request.POST.get(
'p'
,
None
)
code
=
request.POST.get(
's'
,
None
)
print
(username,password,code)
data
=
{
'statuscode'
:
0
,
'status'
:
'ok'
}
''' 当code=0 时表示检查用户名是否存在,当code=1 时表示尝试登陆'''
if
code
=
=
'0'
:
un
=
user.objects.
filter
(username
=
username)
if
un:
return
HttpResponse(json.dumps(data))
else
:
data[
'statuscode'
]
=
1
data[
'status'
]
=
'failed'
return
HttpResponse(json.dumps(data))
else
:
un
=
user.objects.
filter
(username
=
username)
data
=
un.values()[
0
]
print
data.get(
'password'
)
if
data.get(
'password'
)
=
=
password:
data
=
{
'statuscode'
:
0
,
'status'
:
'ok'
}
return
HttpResponse(json.dumps(data))
else
:
data[
'statuscode'
]
=
1
data[
'status'
]
=
'failed'
''' 返回一个json格式的字典数据 '''
return
HttpResponse(json.dumps(data))
return
render_to_response(
'login.html'
,{})
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
|
/* 前端javascript代码实现 */
<script src=
"/static/assets/js/jquery-1.12.0.js"
></script>
<script type=
"text/javascript"
>
$(
function
(){
$(
'#email'
).blur(
function
(){
var
temp = $(
'#email'
).val();
$.ajax({
url:
'/ops01/login/'
,
type:
'POST'
,
/* 将从元素中获取到的数据传到后端,这里的s=0是用于后端代码判断前端的需求是要执行检测用户名还是要登陆 */
data:{u:temp,s:0},
success:
function
(arg){
/* 将后端传过来的字典转换成javascript能识别的字典 */
var
obj = jQuery.parseJSON(arg)
/* 通过后端返回的状态码判断结果,然后通过Jquery更改样式的方式控制是否显示之前定义好的提示信息 */
if
(obj.statuscode == 1){
/* */
$(
'#chk_pCn7em'
).attr({style:
"display: inline"
})
console.log(obj.statuscode)
}
else
{
$(
'#chk_pCn7em'
).attr({style:
"display: none"
})
}
},
error:
function
(){
console.log(
'failed'
)
}
});
})
$(
'#denglu'
).click(
function
(){
var
u = $(
'#email'
).val();
var
p = $(
'#password'
).val();
$.ajax({
url:
'/ops01/login/'
,
type:
'POST'
,
data:{u:u,p:p,s:1},
success:
function
(arg){
var
obj = jQuery.parseJSON(arg)
if
(obj.statuscode == 0){
/* 页面跳转 */
window.location.href=
'http://localhost/ops01/adminindex/'
}
else
{
$(
'#promptid'
).attr({style:
"display: inline"
})
}
},
error:
function
(){
console.log(
'failed'
)
}
})
})
})
/* 提示: 还可以通过设置属性的方式修改样式 例如: $('#stipid').attr('class','stip') */
/* 修改选中元素的文本内容 $('#stipid').text('创建成功!') */
</script>
|
Ajax的好处是整个请求过程是异步的,在不刷新页面的情况下完成向后端服务器的请求。
通过后端代码、模版语言、<select>标签实现灵活的下拉列表
1
2
3
4
5
|
# Python后端代码
#获取groups表中的所有数据
gd
=
groups.objects.
all
()
return
render_to_response(
'user-add.html'
,{
'form'
:cuser,
'gop'
:gd})
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
<!-- Html前端代码 -->
<
p
>
<
select
name
=
"group_id"
class
=
"gse"
>
{% for i in gop %}
<
option
value
=
"{{ i.gid }}"
>{{ i.gname }}</
option
>
{% endfor %}
</
select
>
</
p
>
<!-- 编写思路 -->
<!-- 后端会返回一个{ 'gop':gd } 的字典,gd是一个列表里面保存的是groups表取出来的数据对象,每行数据对应一个对象; gd放入了字典里,并设置key为'gop'通过返回字典给前端,前端将可以通过key('gop')得到gd列表,然后通过模版语言循环列表则得到了里面的每行数据的对象。 -->
<!-- <select>标签的name属性是定义返回给后端程序接收的变量名,而<option>标签中的value则是对应的值。-->
|
本文转自qw87112 51CTO博客,原文链接:http://blog.51cto.com/tchuairen/1759548