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