【问题标题】:How to make an external database query iterable?如何使外部数据库查询可迭代?
【发布时间】:2012-08-27 06:27:32
【问题描述】:

我有以下代码:

settings.py

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql', 
        'NAME': 'tectcom',                     
        'USER': 'test',                    
        'PASSWORD': '***146***',                 
        'HOST': '',                     
        'PORT': '',                      
    },

    'cdr': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'ast',                     
        'USER': '123',                      
        'PASSWORD': '654',                 
        'HOST': '',                      
        'PORT': '',                     
    }

views.py

def cdr_user(request):
        cursor = connections['cdr'].cursor()
        calls = cursor.execute('SELECT * FROM cdr')
        return render_to_response("cdr_user.html",
                {'result':calls }, context_instance=RequestContext(request))

cdr_user.html

{% for res in result %}

{{ res.billsec }}<br />

{% endfor %}

桌子是这样的:

+-------------+--------------+------+-----+---------------------+-------+
| Field       | Type         | Null | Key | Default             | Extra |
+-------------+--------------+------+-----+---------------------+-------+
| calldate    | datetime     | NO   | MUL | 0000-00-00 00:00:00 |       | 
| clid        | varchar(80)  | NO   |     |                     |       | 
| src         | varchar(80)  | NO   |     |                     |       | 
| dst         | varchar(80)  | NO   | MUL |                     |       | 
| dcontext    | varchar(80)  | NO   |     |                     |       | 
| channel     | varchar(80)  | NO   |     |                     |       | 
| dstchannel  | varchar(80)  | NO   |     |                     |       | 
| lastapp     | varchar(80)  | NO   |     |                     |       | 
| lastdata    | varchar(80)  | NO   |     |                     |       | 
| duration    | int(11)      | NO   |     | 0                   |       | 
| billsec     | int(11)      | NO   |     | 0                   |       | 
| disposition | varchar(45)  | NO   |     |                     |       | 
| amaflags    | int(11)      | NO   |     | 0                   |       | 
| accountcode | varchar(20)  | NO   | MUL |                     |       | 
| userfield   | varchar(255) | NO   |     |                     |       | 
| uniqueid    | varchar(32)  | NO   |     |                     |       | 
| linkedid    | varchar(32)  | NO   |     |                     |       | 
| sequence    | varchar(32)  | NO   |     |                     |       | 
| peeraccount | varchar(32)  | NO   |     |                     |       | 
+-------------+--------------+------+-----+---------------------+-------+

问题是我得到一个 “异常值:'long' 对象不可迭代”

TypeError at /cdr_user/
'long' object is not iterable
Request Method: GET
Request URL:    http://localhost:8000/cdr_user/
Django Version: 1.4.1
Exception Type: TypeError
Exception Value:    
'long' object is not iterable
Exception Location: /usr/local/lib/python2.7/site-packages/django/template/defaulttags.py in render, line 144
Python Executable:  /usr/local/bin/python
Python Version: 2.7.0
Python Path:    
['/home/tectadmin/cdr/billing',
 '/usr/local/lib/python2.7/site-packages/setuptools-0.6c11-py2.7.egg',
 '/usr/local/lib/python2.7/site-packages/pip-1.0-py2.7.egg',
 '/usr/local/lib/python2.7/site-packages/django_endless_pagination-1.1-py2.7.egg',
 '/usr/local/lib/python27.zip',
 '/usr/local/lib/python2.7',
 '/usr/local/lib/python2.7/plat-linux2',
 '/usr/local/lib/python2.7/lib-tk',
 '/usr/local/lib/python2.7/lib-old',
 '/usr/local/lib/python2.7/lib-dynload',
 '/usr/local/lib/python2.7/site-packages']
Server time:    Sab, 1 Set 2012 19:56:10 -0300
Error during template rendering

In template /home/tectadmin/cdr/billing/config/templates/cdr_user.html, error at line 21
'long' object is not iterable
11    text-indent: 6em;
12  }
13  </style>
14  {% extends "index_cliente.html" %}
15  {% load endless %}
16  {% block title %}CDR{% endblock %}
17  {% block content %}
18  
19  
20  
21  {% for res in result %}
22  
23  {{ res.billsec }}<br />
24  
25  {% endfor %}
26  
27  
28  
29  
30  <br />
31  <form name="input" action="/user_cdr/" method="et" >
Traceback Switch to copy-and-paste view

/usr/local/lib/python2.7/site-packages/django/core/handlers/base.py in get_response
                        response = callback(request, *callback_args, **callback_kwargs) ...
▶ Local vars
/home/tectadmin/cdr/billing/config/views.py in cdr_user
                {'result':result }, context_instance=RequestContext(request)) ...
▶ Local vars

如何使结果可迭代以在模板中显示? 我看过https://docs.djangoproject.com/en/dev/topics/db/sql/ 和其他文档,但我仍然迷失在代码中。

谢谢。

【问题讨论】:

  • 能否发布Exception Value: 'long' object is not iterable 错误的完整回溯?
  • 好的,我粘贴了所有的异常。
  • 为什么要在 Django 应用程序中运行原始 SQL(而不是使用它们的 ORM 来存储对象?)?
  • 表 cdr 不是我项目的模型,它是另一个非 django 项目的一部分。在这种情况下我可以使用 ORM 吗?
  • 没有。不过,我确实明白你需要做什么。我会写一个答案。

标签: python django django-templates django-views


【解决方案1】:

要在 Python 中迭代 SQL 查询的结果,请使用 cursor.fetchall() 将其转换为列表列表。有一个非常方便的秘诀 here 可以将这些结果转换为您可以轻松访问的对象:

class SQLRow(object):
    def __init__(self, cursor, row):
        for (attr, val) in zip((d[0] for d in cursor.description), row) :
            setattr(self, attr, val)

一旦你有了那个类,这很简单:

def cdr_user(request):
    cursor = connections['cdr'].cursor()
    calls = cursor.execute('SELECT * FROM cdr')
    result = [SQLRow(cursor, r) for r in cursor.fetchall()]
    return render_to_response("cdr_user.html",
            {'result': result }, context_instance=RequestContext(request))

这样,billsec 属性(以及所有其他属性)仍可在您的模板中访问。

【讨论】:

  • 完美运行,非常感谢!!如果您需要任何有关电话的信息,请告诉我。
【解决方案2】:

cursor.execute() 不返回可迭代对象。它在适当的位置修改光标对象。这是一些documentation

您需要调用.fetchone() .fetchmany().fetchall() 来检索结果,这些结果应该是可迭代的,例如:

def cdr_user(request):
  cursor = connections['cdr'].cursor()
  cursor.execute('SELECT * FROM cdr')
  calls = cursor.fetchall()
  return render_to_response("cdr_user.html",
                            {'result':calls }, 
                            context_instance=RequestContext(request))

【讨论】:

  • 这不适用于他拥有的模板(无法使用res.billsec 访问)。
猜你喜欢
  • 2023-03-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-09
  • 2021-10-19
相关资源
最近更新 更多