django queryset 返回“类名对象”而不是 DB 值
Posted
技术标签:
【中文标题】django queryset 返回“类名对象”而不是 DB 值【英文标题】:django queryset returns "classname object" instead of DB values 【发布时间】:2014-01-27 01:58:24 【问题描述】:我对 django 查询集有疑问。
型号:
class Rooms(models.Model,):
room_state = models.CharField(max_length=255, choices=[('emptyReady', 'empty'), ('emptyWaiting4Clean', 'clean ready'), ('busy', 'busy')])
room_type = models.IntegerField()
room_number = models.IntegerField()
我可以通过输入 python shell 来检查查询集的工作情况:
for d in Rooms.objects.filter(room_state="emptyReady", id='1'): print(d)
在我的数据库中有表Rooms_rooms,里面有列room_state,如果我们对数据库进行查询:
SELECT room_state FROM Rooms_rooms where id = 1
返回值为emptyReady
但是当我使用查询集(如上面的示例)时,我总是得到:Rooms object
我做错了什么?我尝试在所有 WEB 中搜索答案 3 小时,现在我的耐心已经结束,所以我指望你们 ;)
【问题讨论】:
【参考方案1】:这里:
Rooms.objects.filter(room_state="emptyReady", id='1')
返回Room
对象的查询集。
现在,如果你想要一个特定的值:
Rooms.objects.filter(room_state="emptyReady", id='1').values_list('room_state', flat=True)
阅读更多values_list
here
或者:
for d in Rooms.objects.filter(room_state="emptyReady", id='1'): print(d.room_state)
另一种方法是在class Room
上指定__unicode__
attribute
class Rooms(models.Model,):
room_state = models.CharField(max_length=255, choices=[('emptyReady', 'empty'), ('emptyWaiting4Clean', 'clean ready'), ('busy', 'busy')])
room_type = models.IntegerField()
room_number = models.IntegerField()
def __unicode__(self):
return u'%s' % self.room_state
如果print d
被调用,这应该打印room_state
值
【讨论】:
【参考方案2】:如果我理解,您正在尝试使用 Django 模拟以下查询:
SELECT room_state FROM Rooms_rooms where id = 1
鉴于您的模型,使用 Django,这可以通过发出:
Rooms.object.filter(room_state='emptyReady', id=1).values('room_state')
values()
function 在 Django 1.2 版本(如果不是更早版本)中可用,它允许您仅选择那些您需要查询的字段。这比获取完整模型要快得多,因为它只为您提供包含选定字段的字典。
请注意,在您的代码中,您将 id 作为字符串而不是数字发送。此外,像 filter()
或 values()
这样的函数永远不会返回集合,而是一个 Django 对象,您需要对其进行迭代以获取值。因此,最后您需要执行以下操作:
Rooms.object.filter(room_state='emptyReady', id=1).values('room_state')[0]['room_state']
这是故意对delay the effective work until it is truly needed进行的。
【讨论】:
【参考方案3】:更新和完善@karthikr 的答案...
如果您尝试获取查询集并将其作为上下文传递给模板,然后在循环中迭代,例如:
(在views.py中)
# The manytomanyfield named subscribers in the Feed object points to the userprofile object which has a onetoonefield relationship with the user object
# [...]
queryset = Feed.objects.filter(subscribers=request.user.userprofile)
context =
"result_list" : queryset,
return render(request, "subscriptions/subscriptions.html", context)
(在 subscriptions.html 中)
# [...]
% for instance in result_list %
<p> instance.pk |---> <a href=''> instance.url </a> </p>
% endfor %
# [...]
你会得到错误:
'Feed' object has no attribute '__name__'
当更改模板以显示 result_list
而不使用 for 循环时,例如:
# [...]
result_list
# [...]
我看到了与 OP 相同的输出(这是渲染器输出的):
<QuerySet [<Feed 'https://news.ycombinator.com/rss'>
在我的例子中是Feed object
而不是Rooms object
。
最初尝试循环遍历result_list
时,当模板渲染器认为字符串 Feed 是查询集的列或对象本身的实例时,就会出现错误,然后尝试确定调用它的内容在类似字典的数据结构中。
我不知道为什么在我的情况下 Feed.objects.filter()
或在 OP 的情况下 Rooms.objects.filter()
决定包含不带引号的类名,从而混淆模板渲染器。
我的解决方案是将我的查询更改为:
queryset = Feed.objects.filter(subscribers=request.user.userprofile).values_list('pk','url', named=True)
使用named=True
对能够在模板中单独处理列值很重要(例如 instance.pk
)。使用上面的查询和如上所示的subscriptions.html 模板中的for-loop,渲染顺利进行:
1 |---> https://news.ycombinator.com/rss
【讨论】:
以上是关于django queryset 返回“类名对象”而不是 DB 值的主要内容,如果未能解决你的问题,请参考以下文章
在 Django 查询中提供 LIMIT 参数而不获取 QuerySet 的一部分