在this回答之后,我试图将SQL Story表拆分为父级/子级-子级保存特定的用户数据,而父级则保存更多的通用数据。现在,我遇到了一个问题,出了我缺乏Django经验的问题。我的用户页面尝试显示用户编写的所有故事的列表。以前,当我的用户页面仅从故事表中提取数据时,它运行良好。现在,我需要从两个具有链接信息的表中提取数据,但我不知道该怎么做。
这也是我的user_page视图,也试图从父故事表中提取数据:
def user_page(request, username):
user = get_object_or_404(User, username=username)
userstories = user.userstory_set.order_by('-id')
variables = RequestContext(request, {
'username': username,
'userstories': userstories,
'show_tags': True
})
return render_to_response('user_page.html', variables)
这是我的models.py:
class story(models.Model):
title = models.CharField(max_length=400)
thetext = models.TextField()
class userstory(models.Model):
main = models.ForeignKey(story)
date = models.DateTimeField()
user = models.ForeignKey(User)
从父表中查找适当的信息并将其分配给变量,我真的不知道从哪里开始。我需要做的是按照用户表的“主”键进入故事表,并将故事表分配为变量。但是我只是看不到如何在定义中实现它。
编辑:我已经尝试了故事= userstory.objects.get(user = user),但我得到了'userstory匹配查询不存在'。
最佳答案
通读您链接到的上一个问题,我发现了混乱所在。我的印象是Story
可能有许多与之相关的UserStory
。请注意,我使用Capital
作为类名,这是Python的常见做法。我做这个假设是因为您的模型结构允许通过在UserStory
模型中使用外键来实现这一点。您的模型结构应如下所示:
class Story(models.Model):
title = models.CharField(max_length=400)
thetext = models.TextField()
class UserStory(models.Model):
story = models.OneToOneField(Story) # renamed field to story as convention suggests
date = models.DateTimeField()
user = models.ForeignKey(User)
class ClassicStory(models.Model)
story = models.OneToOneField(Story)
date = models.DateTimeField()
author = models.CharField(max_length=200)
请参见OneToOne relationships here的用法。 “一对一”字段表示一对一关系,这意味着一个故事只有一个用户故事,只有一个。这也意味着UserStory与一个故事完全相关。这是“父母-孩子”关系,另外的约束是父母只有一个孩子。您之前使用ForeignKey意味着一个Story有多个与之关联的UserStories,这对于您的用例是错误的。
现在,您的查询(和属性访问器)将表现出预期的效果。
# get all of the users UserStories:
user = request.user
stories = UserStory.objects.filter(user=user).select_related('story')
# print all of the stories:
for s in stories:
print s.story.title
print s.story.thetext
请注意,select_related将创建一个SQL连接,因此您每次打印出故事文本时都不会执行另一个查询。阅读有关此内容,这非常非常非常重要!
您先前的问题提到您还有另一个表ClassicStories。就像UserStories一样,它也应该有一个OneToOneField。以这种方式使用OneToOne字段将很难遍历Story模型,因为它可能是“ ClassicStory”,但可能是“ UserStory”:
# iterate over ALL stories
allstories = Story.objects.all()
for s in allstories:
print s.title
print s.thetext
print s.userstory # this might error!
print s.classicstory # this might error!
看到问题了吗?您不知道这是什么样的故事。在访问子表中的字段之前,需要检查故事的类型。有一些项目可以帮助您管理此类继承,例如django-model-utils InheritanceManager,但这有点先进。如果您永远不需要遍历
Story
模型并访问其子表,则无需担心。只要您仅访问ClassicStories或UserStories中的Story,就可以了。