考虑简单模型:
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/