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 %}

 

 

 

 

posted @ 2018-05-22 17:43  Feiger.Lan  阅读(276)  评论(0编辑  收藏  举报