我想做与SELECT user_name, item_name FROM users, items WHERE users.favor_item_id = items.item_id
等效的查询,即返回user_name和item_name对。在数据库中,一个用户可以拥有多个受欢迎的项目。
我只是好奇这个SQL查询的等效Django查询是什么?
我的第一个想法是列出USERS中的所有(user,favor_item_id)对,然后查找id为item_id的item_name。但似乎它会搜索ITEM表N次(N是对数),其复杂度为O(NlogM)(M是ITEM中的项目数),而使用上面的SQL查询,复杂度为O (N)。
在django(或任何ORM系统)中有更有效的方法吗?
答案 0 :(得分:2)
(或任何ORM系统)?
真的?这是你在sqlalchemy中的表现方式
假设合理的映射类(这里,使用声明):
Base = sqlalchemy.ext.declarative.declarative_base()
class Item(Base):
__tablename__ = 'items'
id = Column('item_id', Integer, primary_key=True)
name = Column('item_name', String)
class User(Base):
__tablename__ = 'users'
name = Column('user_name', String(50), primary_key=True)
favor_item_id = Column(Integer, ForeignKey(Item.id))
favor_item = relationship(Item, backref="favored_by")
查询非常简单
>>> print sqlalchemy.orm.Query((User.name, Item.name)).join(Item.favored_by)
SELECT users.user_name AS users_user_name, items.item_name AS items_item_name
FROM items JOIN users ON items.item_id = users.favor_item_id
答案 1 :(得分:1)
假设模型:
class User(models.Model):
name = models.CharField(max_length=32)
favorite = models.ForeignKey(Item)
class Item(models.Model):
name = models.CharField(max_length=32)
等效的Django将是:
usersFavorites = User.objects.all().values_list("name", "favorite__name")
这不使用您提供的字段的确切名称。为此,您只需在模型中添加适当的db_table
和db_column
字段。
P.S。这种特殊的模式并不是特别好。恕我直言,User
和Item
应该有多对多的关系:
class User(models.Model):
name = models.CharField(max_length=32)
favorites = models.ManyToManyField(Item, related_name="users")
class Item(models.Model):
name = models.CharField(max_length=32)
除非某个项目只能有一个用户,否则ForeignKey
应位于Item
。
然后你可以迭代一个双循环:
for user in User.objects.all().select_related("favorites"):
for favorite in user.favorites:
# use `user` and `favorite` in some way.
由于select_related()
调用,查询在第一个for
循环中一举完成。