zoukankan      html  css  js  c++  java
  • Django的cmdb探索与开发(二)

    先记下最坑的地方吧。关于Django调用原生语句RawQuerySet的一些问题。

    官方文档上有一段话是这样写的:

    警告

    虽然RawQuerySet可以像普通的QuerySet一样迭代,RawQuerySet并没有实现可以在 QuerySet上使用的所有方法。例如,__bool__()__len__()RawQuerySet中没有被定义,所以所有RawQuerySet转化为布尔值的结果都是TrueRawQuerySet中没有实现他们的原因是,在没有内部缓存的情况下会导致性能下降,而且增加内部缓存不向后兼容。

    在些被坑了好久。因为对Django不够熟悉的原因,在多表联查、数据分页上被这个<class 'django.db.models.query.RawQuerySet'>的对象坑的不要不要的。

    我的view里关于数据查询的一段代码是这样写的。

      因为Devices的model里没有定义DataroomName这个名称的字段,当时想到的只能是通过多表联查,同时查询 Dataroom表和Devices表的数据然后显示出来。

    #获取RawQuerySet结果的len值
    def get_len(rawqueryset):
        def __len__(self):
            params = ["""'%s'""" % p for p in self.params]
            sql = 'SELECT COUNT(*) FROM (' + (rawqueryset.raw_query % tuple(params)) + ') B;'
            cursor = connection.cursor()
            cursor.execute(sql)
            row = cursor.fetchone()
            return row[0]
        return __len__
    
    def DeviceList(request):
    
        user = request.session["UserData"]["user"]
        totalsec = len(Devices.objects.filter(deviceType=3))
        totalnet = len(Devices.objects.filter(deviceType=2))
        totalserver = len(Devices.objects.filter(deviceType=1))
        totaldevices = len(Devices.objects.all())
    
        page_num = 1 #给页码一个初始赋值
        if request.method == "GET" and request.GET.get("page"):
            page_num = request.GET.get("page")
            page_num = int(page_num)
            page_numnext = page_num+1
            page_numlast = page_num-1
        #机房select下拉框
        dataroom = ImportForm(request.POST)
        #查询语句
        sql = "select users_devices.basemodel_ptr_id,users_devices.sn,users_devices.CabinetID,users_devices.deviceMap,users_devices.company,users_devices.model,users_devices.produceIP,users_devices.updatetime,users_dataroom.DataroomName from users_dataroom,users_devices where users_dataroom.basemodel_ptr_id = users_devices.DataRoomID"
        #获取多表联查结果
        deviceData = Devices.objects.raw(sql)
        #获取结果表长度并强行定义给RawQuerySet对象以实现前端分面
        setattr(type(deviceData), '__len__', get_len(deviceData))
    
        page_total = len(deviceData)/10
        if page_total != int(page_total):
            page_total += 1
        page_total = int(page_total)
        page_list = range(1,page_total+1)#确定页码
        page_device = deviceData[(int(page_num)-1)*10:int(page_num)*10]
        return render(request, "DevicesList.html", locals())              

    在此算是把Django原生语句的用法用了个遍。最关键的是还会出现一些小bug。比如用了

    setattr(type(deviceData), '__len__', get_len(deviceData))之后。另一个页面的RawQuerySet查询的前端显示也会爱到影响。。。。


    解决方法
    :(多表联查什么的理论上都可以通过这个实现)
      model中定义函数直接通过
    QuerySet获取。。还是用ORM吧。。。原生的SQL不到成不得已,还是不要用。。。
    models.py
    class Cabinet(BaseModel):
        CabinetName = models.CharField(max_length=32, verbose_name="机柜名称")
        DataRoomID = models.IntegerField(verbose_name="机房ID")
        Capacity = models.CharField(max_length=32,verbose_name="机柜容量")
        # AbleCapacity = models.CharField(max_length=32,verbose_name="机柜可用量")
        CabinetDes = models.CharField(max_length=64,verbose_name="机柜描述")
        #获取设备数目
        def getdevicescout(self):
            return len(Devices.objects.filter(CabinetID=self.basemodel_ptr_id))
        #获取机房名称
        def getDataRoomName(self):
            return Dataroom.objects.get(basemodel_ptr_id=self.DataRoomID).DataroomName
        #计算剩余可用容量
        def AbleCapcity(self):
            deviceuse = 0
            for device in Devices.objects.filter(CabinetID=self.basemodel_ptr_id):
                devicespace = int(device.deviceSize) + 1
                deviceuse = deviceuse+devicespace
            ablecap =  int(self.Capacity)-deviceuse
            return ablecap
    view.py
    
    CabinetData = Cabinet.objects.all()
    
    html:
    
    {% for c in CabinetData %}
                                    <tr class="first">
                                        <td>
                                            <input type="checkbox" style="margin-top: 0"/>
                                        </td>
                                        <td class="description">
                                            {{ c.CabinetName }}
                                        </td>
                                        <td class="description">
                                            {{ c.getDataRoomName }}
                                        </td>
                                        <td class="description">
                                            {{ c.getdevicescout }}
                                        </td>
                                        <td class="description">
                                            {{ c.Capacity }}
                                        </td>
                                        <td class="description">
                                            {{ c.AbleCapcity }}
                                        </td>
                                        <td>
                                            <ul class="actions">
                                                <li><i class="table-edit"></i></li>
                                                <li><i class="table-settings"></i></li>
                                                <li class="last"><i class="table-delete" id="{{ c.basemodel_ptr_id }}" onclick="del(this.id)"></i></li>
                                            </ul>
                                        </td>
                                    </tr>
                                    {% endfor %}
     
  • 相关阅读:
    C++编程入门题目--No.5
    C++编程入门题目--No.4
    C++编程入门题目--No.3
    C++编程入门题目--No.2
    C++入门编程题目 NO.1
    深度使用魅族16T后的评价(本人魅友,绝对客观公正,不要盲目的为手机厂商辩护,想想从当初到现在,魅族正在一步步背离自己的信仰,有问题,解决问题才能有更好的发展)
    ACM及各类程序竞赛专业术语
    python刷LeetCode:3.无重复字符的最长子串
    python刷LeetCode:2.两数相加
    python刷LeetCode:1.两数之和
  • 原文地址:https://www.cnblogs.com/feigerlan/p/9073249.html
Copyright © 2011-2022 走看看