zoukankan      html  css  js  c++  java
  • Django Web补充

    一、今日内容

    一、Django ORM连表操作

    Q,F

    二、Form表单验证

      面向对象

       正则

    三、Session框架

        面向对象

        cookie

        toanado扩展

    二、Django ORM一对多数据创建和查找

    1、数据创建

    对于不是外键关联的表,可以直接创建

    对于通过外键关联的表,可以通过两种方式创建数据:

      方式a:通过id添加数据

    def user_info(request):
        dic = {'username':'xx','age':88,'user_type_id':1}   #通过id添加数据
        models.UserInfo.objects.create(**dic)
        result = models.UserInfo.objects.all()
        for item in result:
            print item.username,item.age,item.user_type.caption    #对象访问属性

      方式b:

        dic = {'username':'alex','age':73,'user_type':models.UserType.objects.get(id=1)}
        models.UserInfo.objects.create(**dic)
        result = models.UserInfo.objects.all()
        for item in result:
            print item.username,item.age,item.user_type.caption    #对象访问属性

    2、数据正向查找

    对于不是外键关联的数据,直接通过如下方式查找

    models.UserInfo.objects.filter(username='alex') #不是外键关联的数据

    对于外键关联的数据,通过"__"双下划线如下的方式查找:

        result = models.UserInfo.objects.filter(user_type__caption="CEO")    #通过外键关联的数据的查找方式
        for item in result:
            print item.username,item.age,item.user_type.caption
        return HttpResponse("OK")

     3、数据反向查找

    首先看一下表结构

    from django.db import models
    class UserType(models.Model):
        caption = models.CharField(max_length=32)
    
    class UserInfo(models.Model):
        user_type = models.ForeignKey(UserType)
        #在创建数据的时候,需要下来创建选择用户类型,这种情况下需要是一对多
        username = models.CharField(max_length=32)
        age = models.IntegerField()

    可以看到UserType是通过外键被UserInfo表关联的表,所以,通过Usertype查找UserInfo表中的数据,称为反向查找

    现在有如下需求:要求获取某个人的用户类型,并计算出该用户类型的用户的数量

                     分析:用户类型存在于UserType表中,但是用户名存在于UserInfo表中,可以直接通过正向查找,在Usertype表中获取指定用户的用户类型,因为用户名是跨表的,需要通过双下划线表示

            通过在UserType表中创建用户类型的对象,利用_set反向关联UserInfo表,查找到对应用户的数量;

        user_type_obj =models.UserType.objects.get(userinfo__username='alex')    #对象(UserType)
        print user_type_obj.caption                 #实例
        print user_type_obj.userinfo_set.all().count()
        return HttpResponse("OK")

    在举一个栗子:

       在前面的BBS项目中,如果要获取所有文章的点赞的个数,该如何实现呢?首先请看下面的表结构:

    class MyUser(models.Model):
        username = models.CharField(max_length=32)
        password = models.CharField(max_length=64)
        def __unicode__(self):
            return self.username
    
    class NEWs(models.Model):
        title = models.CharField(max_length=32)
        content = models.CharField(max_length=32)
        def __unicode__(self):
            return self.title
    
    class Favor(models.Model):
        user_obj = models.ForeignKey(MyUser)
        new_obj = models.ForeignKey(NEWs)
        def __unicode__(self):
            return "%s --> %s" %(self.user_obj.username,self.new_obj.title)

    从上面的表结构可以看出,点赞的表Favor通过外键关联NEWs表和MyUser表,通过NEWs表,获取Favor表中的数据的个数,需要通过反向查找获取,如下:

        new_list = models.NEWs.objects.all()    #获取文章的实例
        for item in new_list:
            print item.title
            print "#############"
            print item.content
            print item.favor_set.all().count()    #反向查找

    接下来需求改变,要求查找dali赞过的文章的个数;

    分析:如果从NEWs表中开始查找,创建对象的时候需要通过双下划线跨表查询NEWs-->Favor-->MyUser,直到找到条件username=dali为止;

        new_list = models.NEWs.objects.filter(favor__user_obj__username='dali')  #filter返回的是列表,没有返回为[]
    for item in new_list: print item.title print "#############" print item.content print item.favor_set.all().count()

    注意:在创建对象的时候,如果是条件查询,需要使用到filter和get,注意区别是:get返回的是字典,无需循环,通过.直接获取需要的字段,并且如果返回值的不唯一或为空,就会报错;而对于filter返回的则是列表,返回值不唯一不会报错,并且如果值为空,返回[],注意获取字段的时候,需要循环; all()返回的也是列表;

     4、好了,现在将数据查找的两种方式总结如下:

        正向查找: filter(跨表)   对象__跨表的字段

                        line.对象.跨表的字段

        反向查找:filter(跨表)    自动创建一个与表名相同的对象__跨表的字段

                       line.自动创建一个与表名相同的对象__set.filter()/all()[0:1]

    二、Django ORM多对多数据创建和查找

    1、正向添加数据

    首先看一下表结构,对于多对多来讲,外键关联的字段HostAdmin/host可以放在任何一张表中,只不过这时候需要注意正向和反向即可

    class Host(models.Model):
        hostname = models.CharField(max_length=32)
        port = models.IntegerField()
    
    class HostAdmin(models.Model):
        username = models.CharField(max_length=32)
        email = models.CharField(max_length=32)
        host=models.ManyToManyField(Host)

    接下来创建数据

      models.Host.objects.create(hostname='c1',port=80)
      models.Host.objects.create(hostname='c2',port=80)
      models.Host.objects.create(hostname='c3',port=80)
      models.HostAdmin.objects.create(username='alex',email='1@live.com')
      models.HostAdmin.objects.create(username='root',email='2@live.com')
      models.HostAdmin.objects.create(username='dali',email='3@live.com')
      models.HostAdmin.objects.create(username='haojie',email='4@live.com')

    数据内容如下所示:

    现在需要在关联的表host表中创建数据如下:

    正向创建数据

        admin_obj=models.HostAdmin.objects.get(username='dali')    #创建username的对象
        host_list=models.Host.objects.filter(id__lt=3)     #创建主机id小于3的对象
        admin_obj.host.add(*host_list)                      #添加数据
        return HttpResponse("OK")

     2、反向数据添加

        host_obj =models.Host.objects.get(id=3)    
        admin_list = models.HostAdmin.objects.filter(id__gt=1)   #id值大于1
        host_obj.hostadmin_set.add(*admin_list)             #反向数据添加

    总结:正向数据添加还是反向数据添加,取决于多对多的关联的字段存在于哪个表中;相同点是:都是一张表中的一个固定的值对另外一张表的多个值;

    3、Django 多对多自定义第三张关系表

    如下三张表,对于第三张关系表,第一张表和第二张表是第三张表的外键,其表中的字段全部通过外键关联其他的表,那么可不可以让第三张表中存在其他的字段呢?答案是可以的

    看下面:Django 多对多ORM创建第三张自定义的关系表,通过through参数实现;

    class Host1(models.Model):
        hostname = models.CharField(max_length=32)
        port = models.IntegerField()
    
    class HostAdmin1(models.Model):
        username = models.CharField(max_length=32)
        email = models.CharField(max_length=32)
        host=models.ManyToManyField(Host1,through='HostRelation')
    
    class HostRelation(models.Model):
        c1=models.ForeignKey(Host1)
        C2=models.ForeignKey(HostAdmin1)    
    #可以在下面继续增加其他的字段,如果需要的话

    那问题来了?自定义的第三张表有了,数据如何写入呢?

    事实上,此时在第三张表中写入数据,是写入的id的值,有两种方式:通过查询对象写入和直接写入,看下面

    #通过查询对象写入,需要查询之后执行数据库操作    
    models.HostRelation.objects.create( c1
    =models.Host1.objects.get(id=1), C2=models.HostAdmin1.objects.get(id=2) )
    #直接写入,无需查询,推荐的方式;    
    models.HostRelation.objects.create( #0次数据库查询,一次数据库插入 c1_id
    =2, C2_id=1, )

    4、Django ORM多对多数据查询的两种方式

    方式1:

        #正向查
        admin_obj =models.HostAdmin.objects.get(id=1)
        admin_obj.host.all()
    
        #反向查
        host_obj =models.Host.objects.get(id=1)
        host_obj.hostadmin_set.all()

    方式2:通过自定义的第三张表查询(推荐)

        relation_list = models.HostRelation.objects.all()
        for item in relation_list:
            print item.c1.hostname
            print item.C2.username
    
        relation_list1 = models.HostRelation.objects.filter(C2__username='alex')
        for item in relation_list1:
            print item.c1.hostname
            print item.C2.username

    比较:第二种方式可以查询所有的数据,并且操作数据库的次数少,,并且便于扩展(添加新的字段)推荐使用;

    5、ORM查询使用select_related()

    ret = models.UserInfo.objects.all()
     print ret.query

    SQL为:
    SELECT "app01_userinfo"."id", 
      "app01_userinfo"."user_type_id",
      "app01_userinfo"."username",
      "app01_userinfo"."age"
    FROM "app01_userinfo"
    
    
    ret = models.UserInfo.objects.all().select_related() 
    print ret.query SQL为: SELECT
    "app01_userinfo"."id", "app01_userinfo"."user_type_id", "app01_userinfo"."username", "app01_userinfo"."age", "app01_usertype"."id", "app01_usertype"."caption" FROM "app01_userinfo" INNER JOIN "app01_usertype" ON ( "app01_userinfo"."user_type_id" = "app01_usertype"."id" )

    select_related()会将外键关联的表进行关联查询,会将全部Foreignkey加载到内存;

    6、ORM之F和ORM之Q

    需求:将数据库中age字段的值都加以 model.tb.object.all().update(age=F('age')+1)    #F表示当前行的数据

    一般对于使用ORM filter查询数据的时候,只能添加一个条件,那么如果需要添加多个条件呢?

    ORM Q可以创建多个条件供filter查询

    现在要求查询:主机名为c1或c2或c3或c4并且状态都为在线的主机
    from django.db.models import Q
    con=Q()
    主机名:c1,c2,c3,c4 ===> q1 =Q()
    q1=Q()
    q1.connector="OR"
    q1.children.append(('hostname',"c1"))    #此处的主机名可以使用双下划线进行跨表关联
    q1.children.append(('hostname',"c2"))
    q1.children.append(('hostname',"c3"))
    q1.children.append(('hostname',"c4"))
    
    状态:上线,上架 ===>q2 ==Q()
    q2=Q()
    q2.connector="OR"
    q2.children.append(('status',"online"))
    q2.children.append(('status',"online2"))
    
    con.add((q1,'ADD'))
    con.add((q2,'ADD'))
    models.TB1.objects.filter(con)

    就是将q1和q2两个条件一起放到con条件下面,产生多个条件;

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    
    import json
    
    from backend.response.base_response import BaseResponse
    from django.db import transaction
    from web_manage.dal import asset
    from web_manage.dal import user_profile
    from web_manage.dal import contract
    from web_manage.dal import idc
    from web_manage.dal import server
    from web_manage.dal import device_status
    from web_manage.dal import business_unit
    from web_manage.dal import device_type
    from web_manage.dal import nic
    from web_manage.dal import memory
    from web_manage.dal import disk
    from web_manage.dal import handle_log
    from django.db.models import Q
    
    
    def asset_import_single(**kwargs):
        response = BaseResponse()
        try:
            with transaction.atomic():
                manage_ip = kwargs.pop('manage_ip')
                hostname = kwargs.pop('hostname')
                sn = kwargs.pop('sn')
    
                kwargs['idc'] = idc.get_obj_by_id(kwargs['idc'])
                kwargs['contract'] = contract.get_obj_by_id(kwargs['contract'])
                #kwargs['manage_user'] = user_profile.get_obj_by_id(kwargs['manage_user'])
                kwargs['device_status'] = device_status.get_obj_by_code('1000')
                kwargs['device_type'] = device_type.get_obj_by_code('1000')
    
                kwargs['business_unit'] = business_unit.get_obj_by_id(kwargs['business_unit'])
    
                asset_obj = asset.add(**kwargs)
                server.add(asset=asset_obj, manage_ip=manage_ip, hostname=hostname, sn=sn)
    
                response.data = asset_obj
                response.status = True
        except Exception, e:
            response.message = e
        return response
    
    
    def get_asset_lists_count(conditions):
        response = BaseResponse()
        try:
            # base ip get server object ip
            ips = conditions.get('ips__contains', None)
            if not ips:
                pass
            else:
                del conditions['ips__contains']
    
                q_ip = Q()
                q_ip.connector = 'OR'
                server_ids = []
                for item in (ips if ips else []):
                    q_ip.children.append(("ipaddrs__contains", item))
                server_ips = nic.get_field_by_q_group(q_ip, 'server_info', *['server_info__id'])
                for item in server_ips:
                    if item:
                        server_ids.append(item.values()[0])
                if server_ids:
                    conditions['server__id'] = server_ids
                else:
                    conditions['server__id'] = [0, ]
    
            # create search condition
            con = Q()
            for k, v in conditions.items():
                temp = Q()
                temp.connector = 'OR'
                for item in v:
                    temp.children.append((k, item))
                con.add(temp, 'AND')
    
            # do search
            result = asset.get_asset_lists_q_count(con)
    
            response.data = result
            response.status = True
    
        except Exception,e:
            response.message = str(e)
        return response
    
    
    def get_asset_lists(conditions, start, end):
        response = BaseResponse()
        try:
            values = ['id', 'cabinet_num', 'cabinet_order', 'server__manage_ip', 'server', 'server__hostname', 'server__sn',
                      'device_type__id', 'device_type__name',
                      'device_status__id', 'device_status__name',
                      'business_unit__id', 'business_unit__name',
                      'idc__id', 'idc__display',
                      'contract__id', 'contract__name']
            # base ip get server object ip
            ips = conditions.get('ips__contains', None)
            if not ips:
                pass
            else:
                del conditions['ips__contains']
    
                q_ip = Q()
                q_ip.connector = 'OR'
                server_ids = []
                for item in (ips if ips else []):
                    q_ip.children.append(("ipaddrs__contains", item))
                server_ips = nic.get_field_by_q_group(q_ip, 'server_info', *['server_info__id'])
                for item in server_ips:
                    if item:
                        server_ids.append(item.values()[0])
                if server_ids:
                    conditions['server__id'] = server_ids
                else:
                    conditions['server__id'] = [0, ]
    
            # create search condition
            con = Q()
            for k, v in conditions.items():
                temp = Q()
                temp.connector = 'OR'
                for item in v:
                    temp.children.append((k, item))
                con.add(temp, 'AND')
    
            # do search
            result = asset.get_asset_lists_q(start, end, con, *values)
    
            # get ip info
            for item in result:
                ips = nic.get_field_by_server(item['server'], *['ipaddrs', ])
                item['ips'] = list(ips)
    
            result = list(result)
    
            response.data = result
            response.status = True
    
        except Exception,e:
            response.message = str(e)
        return response
    
    
    def __asset_update_log(row, user):
        with transaction.atomic():
            asset_obj = asset.get_asset_by_id(row['id'])
            server_obj = server.get_obj_by_asset(asset_obj)
            log_list = []
    
            if(row.has_key('cabinet_order')):
                log_list.append(u"机柜由【%s】变更为【%s】" % (asset_obj.cabinet_order, row['cabinet_order']))
                asset_obj.cabinet_order = row['cabinet_order']
    
            if(row.has_key('cabinet_num')):
                log_list.append(u"柜上位置由【%s】变更为【%s】" % (asset_obj.cabinet_num, row['cabinet_num']))
                asset_obj.cabinet_num = row['cabinet_num']
    
            if(row.has_key('contract')):
                log_list.append(u"合同由【%s】变更为【%s】" % (asset_obj.contract.name, row['contract']))
                asset_obj.contract = contract.get_obj_by_name(row['contract'])
    
            if(row.has_key('business_unit')):
                log_list.append(u"业务线由【%s】变更为【%s】" % (asset_obj.business_unit.name, row['business_unit']))
                asset_obj.business_unit = business_unit.get_obj_by_name(row['business_unit'])
    
            if(row.has_key('idc')):
                log_list.append(u"IDC由【%s】变更为【%s】" % (asset_obj.idc.display, row['idc']))
                asset_obj.idc = idc.get_obj_by_display(row['idc'])
    
            if(row.has_key('device_status')):
                log_list.append(u"设备状态由【%s】变更为【%s】" % (asset_obj.device_status.name, row['device_status']))
                asset_obj.device_status = device_status.get_obj_by_name(row['device_status'])
    
            if(row.has_key('manage_ip')):
                log_list.append(u"管理IP由【%s】变更为【%s】" %(server_obj.manage_ip, row['manage_ip']))
                server_obj.manage_ip = row['manage_ip']
    
            if(row.has_key('hostname')):
    
                log_list.append(u"主机名由【%s】变更为【%s】" %(server_obj.hostname, row['hostname']))
                server_obj.hostname = row['hostname']
    
            if(row.has_key('sn')):
                log_list.append(u"SN号由【%s】变更为【%s】" %(server_obj.sn, row['sn']))
                server_obj.sn = row['sn']
    
            server_obj.save()
            asset_obj.save()
            if log_list:
                handle_log.write_handle_log(asset_obj, user, ';'.join(log_list))
    
    
    def del_asset(rows):
        response = BaseResponse()
        error_count = 0
        error_message = []
        try:
            rows = json.loads(rows)
        except Exception, e:
            response.status = 0
            response.data = str(e)
            response.message = error_message
            return response
    
        for row in rows:
            try:
                with transaction.atomic():
                    asset_obj = asset.get_asset_by_id(row['nid'])
                    server_obj = asset_obj.server
                    nic.del_by_server(server_obj)
                    disk.del_by_server(server_obj)
                    memory.del_by_server(server_obj)
                    handle_log.del_by_asset(asset_obj)
                    server_obj.delete()
                    asset_obj.delete()
            except Exception, e:
                error_count += 1
                error_message.append({'num': row['num'], 'message': str(e)})
    
        if error_count == 0:
            response.status = 1
            response.data = "删除%d条,成功%d." % (len(rows), len(rows)-error_count)
        elif error_count > 0:
            response.status = 0
            response.data = "删除%d条,成功%d,失败%d." % (len(rows), len(rows)-error_count, error_count)
            response.message = error_message
        return response
    
    
    def modify_multi_asset(data, user):
        # 临时
        response = BaseResponse()
        rows = json.loads(data)
        error_count = 0
        error_message = []
        user = json.loads(user)
        current_user_id = user['id']
        current_user_obj = user_profile.get_obj_by_id(current_user_id)
        for item in rows:
            try:
                __asset_update_log(item, current_user_obj)
            except Exception, e:
                error_count += 1
                error_message.append({'num': item['num'], 'message': str(e)})
        if error_count == 0:
            response.status = 1
            response.data = "更新%d条,成功%d." % (len(rows), len(rows)-error_count)
        elif error_count > 0:
            response.status = 0
            response.data = "更新%d条,成功%d,失败%d." % (len(rows), len(rows)-error_count, error_count)
            response.message = error_message
        print response
        return response
    
    
    def get_asset_detail(nid):
        response = BaseResponse()
        try:
            asset_obj = asset.get_asset_by_id(nid)
            nic_list = nic.get_objs_by_server(asset_obj.server)
            mem_list = memory.get_objs_by_server(asset_obj.server)
            disk_list = disk.get_objs_by_server(asset_obj.server)
            log_list = handle_log.get_handle_log(asset_obj=asset_obj)
            result = {'asset': asset_obj, 'nic': nic_list, 'memory': mem_list, 'disk': disk_list, 'log': log_list}
            response.status = True
            response.data = result
        except Exception, e:
            response.message = str(e)
        return response
    
    
    def init_config(nid):
        response = BaseResponse()
        try:
            asset_obj = asset.get_asset_by_id(nid)
            result = asset.get_init(asset_obj.server.manage_ip)
            asset_obj.server.service_sn = result['service_sn']
            asset_obj.server.sn = result['sn']
            asset_obj.server.first_mac = result['first_mac']
            asset_obj.server.save()
            response.status = True
            response.data = '初始化成功.'
        except Exception, e:
            response.status = False
            response.message = str(e)
    
        return response
    
    
    
    # ########################## 获取字典表 ########################## #
    
    
    def get_all_idc():
        response = BaseResponse()
        try:
            values = ['id','display']
            result = idc.get_all(*values)
            result = list(result)
            response.data = result
            response.status = True
        except Exception,e:
            response.message = str(e)
        return response
    
    
    def get_all_status():
        response = BaseResponse()
        try:
            values = ['id', 'name', ]
            result = device_status.get_all(*values)
            result = list(result)
            response.data = result
            response.status = True
        except Exception,e:
            response.message = str(e)
        return response
    
    
    def get_all_user_basic_op():
        response = BaseResponse()
        try:
            values = ['id', 'name', ]
            result = user_profile.get_all_basic_op(*values)
            result = list(result)
            response.data = result
            response.status = True
        except Exception,e:
            response.message = str(e)
        return response
    
    
    def get_all_business_unit():
        response = BaseResponse()
        try:
            values = ['id', 'name', ]
            result = business_unit.get_all(*values)
            result = list(result)
            response.data = result
            response.status = True
        except Exception,e:
            response.message = str(e)
        return response
    
    
    def get_all_contract():
        response = BaseResponse()
        try:
            values = ['id', 'name', ]
            result = contract.get_all(*values)
            result = list(result)
            response.data = result
            response.status = True
        except Exception,e:
            response.message = str(e)
        return response
    View Code

     7、作业:搜索功能开发

    那么作业来了:
    前端输入多个用户、多个年龄或者用户类型来搜索用户
    
    姓名:<input name="username" />
    年龄:<input name="age" />
    用户类型:<input name="user_type__caption" />   #跨表
    
    
    AJAX
        {
            "username":[c1,c2,c3],
            "age":[18,19]
        }
        
    后台
        dic 在前端获取
        con = Q()
        for key,value in dic:
            q=Q()
            q.connettor="OR"
            for v in value:
                q.children.append((key,v))
            con.add(q,'ADD')
            
            model.Tb1.objects.filter(con)
  • 相关阅读:
    事务
    约束条件(CONSTRAINTS)
    算术运算符
    数据查询、修改指令
    iview-admin使用webpack打包之后发布报Uncaught SyntaxError: Unexpected token <
    使用localhost可以访问,但使用本地ip+端口号无法访问
    datatables里面的search怎么去掉?
    删除操作之后的确定或取消弹出框?
    jquery实现上传图片本地预览效果
    怎么改变title属性的样式?
  • 原文地址:https://www.cnblogs.com/cqq-20151202/p/5744824.html
Copyright © 2011-2022 走看看