Python Django关系在没有_集的情况下向后工作,但在
我有以下数据库表:Python Django关系在没有_集的情况下向后工作,但在,python,django,Python,Django,我有以下数据库表: class Story(models.Model): user = models.ForeignKey(User) group = models.ForeignKey(Group, blank=True, null=True) date_added = models.DateTimeField(auto_now_add=True) date_modified = models.DateTimeField(auto_now=True) l
class Story(models.Model):
user = models.ForeignKey(User)
group = models.ForeignKey(Group, blank=True, null=True)
date_added = models.DateTimeField(auto_now_add=True)
date_modified = models.DateTimeField(auto_now=True)
location = models.CharField(max_length=100)
title = models.CharField(max_length=150)
description = models.CharField(blank=True, null=True, max_length=2000)
exp_text = models.TextField()
category = models.ForeignKey(Category, blank=True, null=True)
def __unicode__(self):
return self.title
class Comment(models.Model):
user = models.ForeignKey(User)
date_added = models.DateTimeField(auto_now_add=True)
date_modified = models.DateTimeField(auto_now=True)
emailOnReply = models.NullBooleanField(blank=True, null=True)
comment_text = models.TextField()
story = models.ForeignKey(Story)
def __unicode__(self):
return self.comment_text
当我创建了一个评论对象并需要访问一个故事的标题时,我希望能够做到这一点:
c = Comment.objects.all()
for com in c:
com.comment_set.title
但是django说注释集没有定义。在文档中,它指出,如果您试图访问另一个数据库表中未定义外来项的字段,则可以使用_set方法,其中前面的单词是类的名称
在尝试了不同的方法后,我发现这是可行的:
c = Comment.objects.all()
for com in c:
com.story.title
c = Comment.objects.all()
for com in c:
print com.story.title
既然外键是在Comment中定义的,我看不出它是如何工作的,但是它确实工作了,为什么设置不工作呢。因为我在定义外键的模型中处理一个对象,我需要转到故事,然后我需要根据文档使用_set…当处理故事对象时,我可以在定义相关的_name属性时引用注释模型,所以我也不需要在那里设置。。你为什么不在这里工作
更新:
现在,当我使用story对象并通过以下方式引用comment类时,关系可以反向工作:
s = Story.objects.all()
for st in s:
print st.comment_set.all()
我使用的是st.story_集而不是st.comment_集,但我仍然觉得这样做很奇怪:
c = Comment.objects.all()
for com in c:
com.story.title
c = Comment.objects.all()
for com in c:
print com.story.title
当尝试从故事对象开始工作时,我没有任何注释表的外键(只有注释表中外键上的相关名称),因此我似乎没有获得相同的访问权限。实际上,一切都按预期工作。
注释对象没有注释外键,它有一个“故事”外键。 评论“指向”故事。因此,一条评论只有一个故事,但一个故事可能有一组评论 这就是为什么
st.comment\u set
有效的原因,因为它“向后看”指向它的注释,而注释只是直接指向它相关的故事(即com.story
)
如果您有兴趣了解其工作原理,请参见此处:这就是Django的ORM如此酷的部分原因…Django中的以下关系有点含蓄。以下是您的模型的简化版本:
class Story(models.Model): # instances have access to Manager comment_set (backward)
title = models.CharField(max_length=150)
description = models.CharField(blank=True, null=True, max_length=2000)
class Comment(models.Model): # has access to Story (forward)
comment_text = models.TextField()
story = models.ForeignKey(Story) # stored in database as story_id, which refers to (implicit) id column in Story
您的数据库将如下所示(除非您另有指定):
向前
Comment
的实例可以通过将Comment
的Story\u id列与Story
的id列相匹配来访问Story
(后者对Django表是隐式的,不在您的模型中,但肯定在您的数据库表中,除非您另有指定)
向后
Comment
有一个外键指向Story
,因此Story
的实例可以访问名为Comment\u set
的管理器,该管理器可以跟踪从Story
到Comment
的关系
>>> s = Story.objects.get(title='first post')
>>> s.comment_set.comment_text # accesses Comment model from Story instance
'hello, world'
或者,如果您想重复您在注释中提到的所有注释集
s,请尝试以下操作:
>>> s = Story.objects.get(title='first post') # returns a single, non-iterable query object
>>> for story in s.comment_set.all(): # each comment_set object can have more than one item
print story.comment_text # story does not have a comment_set attribute
'hello, world' # my comment set here just happens to have one item
更新
或者,根据您的评论,您希望将迭代提高一个级别,请尝试以下操作:
>>> s = Story.objects.all()
>>> for story in s: # iterate over top level
>>> for row in story.comment_set.all():
>>> print row.comment_text # again, row does not have a comment_set attribute
'hello, world' # again, my comment set has only one item
谢谢你这么详细的解释。但是,在指定以下内容时,我无法使您的上一个代码正常工作:>>>s=Story.objects.all()>>>for Story in s:。。。打印story.comment\u set.comment\u文本。。。回溯(最近一次调用):文件“”,第2行,在AttributeError:“RelatedManager”对象中没有属性“comment\u text”…啊,不知道如何在注释中获得良好的格式:/@user2959896我很乐意提供帮助。我更新了上面的答案。有关如何迭代查询集的示例,请参见答案的末尾。实例s有一个
注释集
,但该实例中的查询项故事
没有注释集
。(另外,您可以使用键盘上的“back tick”设置注释中的代码格式。)@user2959896好的,我的上一次编辑将执行您在收到上述错误消息时尝试执行的操作。您必须遍历顶级查询集和查询集的子级别。我在上面举了一个有效的例子。祝你好运!