Django:在多对多关系中交换元素

1 投票
2 回答
575 浏览
提问于 2025-04-17 15:04

我在两个模型之间设置了一个多对多的关系,按照标准的方式来做。

class UserSet(models.Model):
    name = models.CharField(max_length=256)
    items = models.ManyToManyField(Item, blank=True, through='ItemUserSet')

class ItemUserSet(models.Model):
    set = models.ForeignKey(UserSet)
    item = models.ForeignKey(Item)
    order = models.IntegerField()

简单来说,我有很多物品,任何用户都可以为他们的个人列表创建一组物品。

我想让用户能够在他们的列表中交换一个物品和另一个物品,并且这个操作也会在其他任何拥有被交换物品的用户列表中进行交换。

orig_item = Item.objects.get(uuid=orig_uuid)
repl_item = Item.objects.get(uuid=repl_uuid)
board_uuid = request.GET['board'] or None

board = UserSet.objects.filter(uuid=board_uuid) 
ius = ItemUserSet.objects.filter(item__uuid=orig_uuid)

for u_set in board:
    u_set.items_set.remove(orig_item)
    u_set.items_set.add(repl_item)
    c['msg']='OK'
for sets in ItemUserSet:
    sets.item = repl_item.pk
    sets.save()

但是这样做不行,我遇到了这个错误。

'ManyRelatedManager' object has no attribute 'remove'

基本上,当一个用户选择两个物品进行交换时,如果那个物品在任何用户的列表中存在,就应该进行交换。

2 个回答

-1

我不确定这是否是你想要的答案,但看起来你是在尝试从管理器对象中移除,而不是直接从项目中移除。

我没有时间去测试这个,不过你可以试试在下面这行代码的末尾加上 .all():

board = UserSet.objects.filter(uuid=board_uuid)

这样做实际上会提取出项目,而不仅仅是返回管理器。之前我在模板中遇到过类似的问题,这个方法对我有帮助。

1

我终于明白我哪里做错了。

显然,在这种情况下,你需要通过“中间”模型来处理多对多关系的操作。(所以可能这个名字就是这么来的?)我想这就是Django文档想表达的意思.. :/

所以我通过以下方式解决了这个问题:

for s in ius:
    s.item = repl_item
    s.save()

现在运行得很好。希望这能帮助到其他人。

撰写回答