2

这是关于 Django 的另一个问题。

我有这个代码:

视图.py

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

我使用这样的 MySQL 查询,因为数据库不是 django 项目的一部分。

我的 cdr 表有一个名为 duration 的字段,我需要将其除以 60 并将结果乘以一个浮点数,例如 0.16。

有没有办法使用模板标签来乘以这个值?如果没有,在我看来有没有好的方法呢?

我的模板是这样的:

{% for call in calls %}
    <tr class="{% cycle 'odd' 'even' %}"><h3>
        <td valign="middle" align="center"><h3>{{ call.calldate }}</h3></td>
        <td valign="middle" align="center"><h3>{{ call.disposition }}</h3></td>
        <td valign="middle" align="center"><h3>{{ call.dst }}</h3></td>
        <td valign="middle" align="center"><h3>{{ call.billsec }}</h3></td>
        <td valign="middle" align="center">{{ (call.billsec/60)*0.16 }}</td></h3>
    </tr>
{% endfor %}

最后是我需要显示值的地方,我知道“(call.billsec/60)* 0.16”不可能在那里完成。我写它只是为了代表我需要展示的东西。

4

3 回答 3

4

您可以在三个不同的层上执行此操作:

  • 数据库级别。SQL 是一种强大的数学语言。您可以在查询的选择部分写下您的方程式。在你的情况下,应该是这样的SELECT (duration/60*0.16) FROM cdr;。可以在此处和 Google 上找到示例。请注意,在这种情况下,压力(算法复杂性)放在 MySQL 服务器进程而不是 Python 进程上。
  • 查看级别。在您的示例中,就在您返回之前,您可以遍历result变量的每个元素以修改其值。你可以按照 Lie Ryan 给出的这个级别的例子。
  • 模板级别。这是由自定义过滤器完成的。您可以按照文档中的说明编写自定义过滤器,并通过此过滤器管道模板变量以获得所需的值。

这些方面的内容将代表适用于您的模板的自定义过滤器:

@register.filter
def customFilter(value):
    return value / 60.0 * 0.16

{% load %}然后,在自定义过滤器之后,您可以在模板中以这种方式使用它(阅读文档以获取更多实现信息):

{{ billsec|customFilter }}
于 2012-09-02T05:23:05.830 回答
3

如果数学运算不太复杂,我通常使用custom template tags. 添加操作已经可以作为模板标签使用,我在我的项目中使用下面的代码片段分别进行乘法、减法和除法。将此代码放在.pyapp/templatetags所在位置的文件中,并在其中添加一个__init__.py

from django import template

#Django template custom math filters
#Ref : https://code.djangoproject.com/ticket/361
register = template.Library()

def mult(value, arg):
    "Multiplies the arg and the value"
    return int(value) * int(arg)

def sub(value, arg):
    "Subtracts the arg from the value"
    return int(value) - int(arg)

def div(value, arg):
    "Divides the value by the arg"
    return int(value) / int(arg)

register.filter('mult', mult)
register.filter('sub', sub)
register.filter('div', div)
于 2012-09-02T14:37:29.693 回答
1

编辑:以下答案是完全错误的,因为我认为 OP 使用的是 sqlite。MySQL 有自己的方式将事物包装到字典中,见下文。

您可以继承 sqlite3.Row 并编写自己的“计算字段”:

class MyRow(sqlite3.Row):
    def comp_billsec(self):
        return (self['billsec'] / 60) * 0.16

cursor = ...
cursor.row_factory = MyRow
for r in cursor.execute('...'):
    print r['billsec'], r.comp_billsec()

请注意,我们comp_billsec使用方法调用语法访问,而sqlite3.Row工厂通过字典语法提供访问。这种差异会在 django 模板中消失,因为在 django 模板中,字典访问和零参数函数调用具有相同的语法,因此您可以使用{{ call.billsec }}{{ call.comp_billsec }}.

编辑:在 MySQL 中,您可以在视图中插入计算值,如下所示:

cursor = connections['cdr'].cursor(cursorclass=MySQLdb.cursors.DictCursor)
calls = cursor.execute("...")
result = [r + dict(comp_billsec=r['billsec'] / 60 * 0.16) for r in cursor.fetchall()]
return render_to_response("cdr_user.html",
    {'calls':result }, context_instance=RequestContext(request))

另外,您应该使用参数化查询(注意逗号而不是 %):

cursor.execute("SELECT * FROM cdr where calldate > '%s'", (start_date,))

您之前的代码存在 SQL 注入安全问题,因为您将 start_date 直接插入到 SQL 查询中。' OR 1 OR '例如,如果 start_date 包含,您的查询将被内插为SELECT * FROM cdr where calldate > '' OR 1 OR ''它将选择表中的所有行;情况可能更糟。

于 2012-09-02T04:03:16.457 回答