Django外键不适用于一对多关系
Posted
技术标签:
【中文标题】Django外键不适用于一对多关系【英文标题】:Django foreign key not working for One-To-Many relationship 【发布时间】:2016-11-16 00:19:09 【问题描述】:我正在尝试编写一个查询,当搜索艺术家 ID 时,该艺术家的信息及其所有作品都是结果,基本上是 Artist
和 ArtistPiece
之间的连接查询
#models.py
class Artist(models.Model):
name = models.CharField(max_length=100)
artist = models.CharField(max_length=150)
created_by = models.ForeignKey(User)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class ArtistPiece(models.Model):
artist = models.ForeignKey(Artist, on_delete = models.CASCADE)
piece_name = models.CharField(max_length=50)
details = models.CharField(max_length=100)
#views.py
from .models import Artist, ArtistPiece
class EditArtistViewSet(viewsets.ViewSet):
def edit(self,request,artist_id):
artist = Artist.objects.select_related().get(pk=artist_id)
data = model_to_dict(artist)
return render(
request, 'ArtistInfo/edit.html',
'editing': 'true',
'edit_data': json.dumps(data),
)
def submit_edit(self,request):
return render(request, 'ArtistInfo/edit.html')
上述方法有效,但它不会从 ArtistPiece 模型中选择任何数据,尽管有主键。然后在阅读this post 关于使用select_related
之后,我意识到与其查找艺术家,不如通过foreign_key 查找ArtistPiece,并使用select_related 查找有关艺术家的信息。
然后我尝试了这个
def edit(self, request, artist_id):
artist = ArtistPiece.objects.get()
data = model_to_dict(artist)
这导致了以下错误get()
返回了多个 ArtistPiece -- 它返回了 5!。搜索,我发现this post 表明我需要使用过滤器而不是获取。然后我尝试了这个
def edit(self, request, artist_id):
artist = ArtistPiece.objects.select_related('artist').filter(artist=artist_id)
data = model_to_dict(artist)
这给出了以下错误'QuerySet' object has no attribute '_meta'
。我尝试搜索这个错误,发现 this 基本上建议使用 get,这似乎与我发现的所有其他内容背道而驰。
总而言之,我只想选择一位艺术家和他们的作品,但我似乎无法弄清楚如何。
编辑 - 我尝试了一些方法并取得了一些进展,但仍然无法正常工作
为了清楚起见,我正在尝试编写一个查询,该查询将通过他们的 id 查找艺术家,结果将是艺术家的信息和艺术家的作品。我可以根据艺术家 ID 或 ArtistPiece
模型查询和检索 Artist
模型,但没有一个查询会同时返回 Artist
和与该艺术家关联的所有 ArtistPiece
条目。
按照@bignose 的建议将related_name='pieces'
添加到我的模型中,然后我尝试了artist = Artist.objects.select_related('pieces').filter(pk=artist_id)
,但仍然给出了no 属性.... 上面的错误。然后我将 data = model_to_dict(artist)
更改为 data = [model_to_dict(a) for a in artist]
并且它起作用了,但是数据只是艺术家,ArtistPiece
模型中没有任何数据。
我没有查询Artist
模型,而是尝试查询ArtistPiece
模型:artist = ArtistPiece.objects.select_related('artist').filter(artist=artist_id)
,但是只返回了艺术家的作品,没有来自Artist
模型的信息。
【问题讨论】:
我已将ArtistPiece
的名称修改为单数;该名称应反映每个实例代表其中 一个 的事实。
【参考方案1】:
model_to_dict
接受单个模型对象,但您正在将QuerySet
类型的对象传递给该对象(与列表非常相似)。要获取所有对象的字典列表,您需要在每个模型对象上显式调用model_to_dict
,例如:
data = [model_to_dict(a) for a in artist]
更好的方法是使用QuerySet.values()
:
data = artist.values()
根据Queryset.Values()
document:
当用作可迭代对象时,返回一个返回字典而不是模型实例的 QuerySet。
这些字典中的每一个都代表一个对象,其键对应于模型对象的属性名称。
还可以查看Serializer
类。我认为它对你有用。
【讨论】:
这部分有效。我可以查询Artist
模型或ArtistPiece
模型,但我似乎无法使用外键获得“组合”查询。我在上面编辑了我的帖子以显示更改。谢谢【参考方案2】:
ArtistPiece.objects.filter(artist=artist_id)
,这将返回一个查询集。
如果你想要一个列表,你可以做ArtistPiece.objects.filter(artist=artist_id).values_list('id', flat=True)
https://docs.djangoproject.com/en/1.10/ref/models/querysets/#values-list
【讨论】:
如果这不是您想要的,请告诉我 第一个查询有效,但它只返回该艺术家 ID 的ArtistPiece
条目,而不是同时返回 Artist
和 ArtistPiece
。第二个返回如下错误'int' object has no attribute '_meta'
【参考方案3】:
ForeignKey
字段类型也会自动在外部模型上设置一个属性;在你的情况下,Artist.artistpieces_set
。
favourite_artist = Artist.objects.get(pk="foo") # However you get an Artist instance.
favourite_artist.artistpieces_set # Is a QuerySet of all the ArtistPiece instances that reference this instance.
# Because it's a QuerySet, you can iterate it, filter it, etc.
for piece in favourite_artist.artistpieces_set.all():
put_in_exhibition(piece)
因此,当您获得 Artist
实例时,它会自动具有一个属性,即 QueryManager
用于引用 Artist
的 ArtistPiece
实例。
这很好,因为这意味着外键关系是在一个地方定义的,但也可以从另一端访问。
有关如何使用这些功能,请参阅“Following relationships “backwards””的文档。
【讨论】:
当我尝试这个favourite_artist = Artist.objects.get(pk="foo")
时,艺术家被返回,但favourite_artist.pieces
抛出一个错误,指出'QuerySet' object has no attribute 'pieces'
。我的模型中肯定有相关名称。
该消息告诉您您有一个 QuerySet 实例,而不是 Artist 实例。仔细检查您是如何获取对象的。
我做了一些更改并取得了一些进展,但仍然无法正常工作。我从模型中删除了related_name='pieces'
,也将favourite_artist.pieces
设为单数,所以现在是favourite_artist.piece
,我注意到这是Django documentation 显示的方式。但是我现在收到错误'RelatedManager' object is not iterable
感谢您的帮助,但我想我可能误解了这些搜索的工作原理。我来自 Cakephp/Laravel 背景,对此的查询将返回同一对象中的 Artist 和 ArtistPiece。例如:Artist : 'name' : 'some_name'...., 'ArtistPiece' : 'piece_name' : 'name', ...
。对 Django 来说是这样吗,或者在这种情况下,查询Artist
并设置一个变量,然后在查询ArtistPiece
后设置一个单独的变量是否是标准做法?以上是关于Django外键不适用于一对多关系的主要内容,如果未能解决你的问题,请参考以下文章
转: django数据库操作-增删改查-多对多关系以及一对多(外键)关系