一、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则是对应的值。-->