Django:如何将原始 sql 查询的结果映射到管理 ListView 中的模型实例?

标签 django django-models django-admin

考虑简单模型:

class Item(models.Model):
    name                = models.CharField(...)
    unit_cost           = models.DecimalField(...)
    unit_price          = models.DecimalField(...)

它具有以下管理类:
class ItemAdmin(admin.ModelAdmin):
    def queryset(self, request):
        qs = self.model._default_manager.get_query_set()
        qs2 = self.model._default_manager.raw('''
        SELECT
            "stock_item"."id",
            "stock_item"."name",
            "stock_item"."unit_cost",
            "stock_item"."unit_price"
        FROM
            "stock_item"
        ''')
        qs3 = RawQuerySet('''
        SELECT
            "stock_item"."id",
            "stock_item"."name",
            "stock_item"."unit_cost",
            "stock_item"."unit_price"
        FROM
            "stock_item"
        ''', self.model)
        return qs   # WORKS
        return qs2  # DOESN'T WORK
        return qs3  # DOESN'T WORK

我覆盖了 queryset() 方法以控制管理 ListView 的行为。我想在 queryset() 中执行原始 sql 查询,将结果映射回 Item 模型,然后再将它们发送到 ListView 。
问题是返回qs2或qs3会在模板中产生如下错误(不抛出异常):
Database error
Something's wrong with your database installation. Make sure the appropriate database tables have been created, and make sure the database is readable by the appropriate user.

请注意,在单独的脚本中运行原始查询是有效的,例如:
items = Item._default_manager.raw('''
    SELECT
        "stock_item"."id",
        "stock_item"."name",
        "stock_item"."unit_cost",
        "stock_item"."unit_price"
    FROM
        "stock_item"
    ''')        

for item in items:
    print item.name, item.unit_price # WORKS!

事实上,我有一个更大的野心,能够创建一种不应该有相应数据库表的“虚拟模型”,其目的是将 sql 投影查询封装在其管理类中(以便模型可以显示在它的管理员 ListView 中)。

我尝试了另一种方法,根本不使用 ItemAdmin,而是使用:
class ItemManager(models.Manager):
    def get_query_set(self):
        return Item._default_manager.raw('''
        SELECT
            "stock_item"."id",
            "stock_item"."name",
            "stock_item"."unit_cost",
            "stock_item"."unit_price"
        FROM
            "stock_item"
        ''')

和:
class Item(models.Model):
    objects = ItemManager()
    etc...

但现在我在管理 ListView 中收到模板异常:

'RawQuerySet' 对象没有属性 'complex_filter'

该怎么办?谢谢...

最佳答案

解决了。

最简单的方法是在 sqlite3(我正在使用的数据库后端)中创建一个数据库 View ,然后添加一个名称与该 View 兼容的普通模型。模型必须有一组与 View 返回的字段名称相似的字段。我的目的不需要管理员或经理。

查看创建数据库脚本:

CREATE VIEW <view_name> AS SELECT etc...

查看删除数据库脚本(作为初步步骤运行,以防您需要重新创建 View ):
DROP VIEW <view_name>

创建 View 时唯一需要注意的是确保设置:
class Meta:
    managed = False
    #ordering = ( '-date', )

以免在运行 syncdb 时创建表。

还有一件事,您需要在您的 View 中选择一个唯一的字段作为主键(并在模型中反射(reflect)出来),否则 django 会提示如下:
no such column: stock_itemdbview.id

干杯!

关于Django:如何将原始 sql 查询的结果映射到管理 ListView 中的模型实例?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8687788/

相关文章:

python - Django -- 如何使用带有多个参数的 templatetags 过滤器

mysql - Django 1.8 中的复杂注释

python - Django Admin list_display 添加列【统计相关外键的记录】

python - 如何为具有多对多字段的 Django 模型创建对象?

python - 没有该列错误信息

Django CMS 自定义插件 - 如何处理翻译

django - ModelAdmin 的 Mixin 问题

javascript - 使用 django 过滤器和带有 Angular 表达式的标签

django - 在 Django Admin 中为 list_filter 创建自定义过滤器

python - Django 查询单下划线表现得像双下划线?