无法获取Django ManyToMany模型对象的句柄

1 投票
2 回答
1141 浏览
提问于 2025-04-18 17:56

我在一个Django应用里有一个简单的例子,涉及到一个会员(Member)和一个会员组(MemberGroup)类。我想要这样的数据表示,但不确定使用多对多关系(ManyToMany)是否让事情变得复杂了:

会员:
1 - 会员1
2 - 会员2
3 - 会员3

组:
1 - 组1
2 - 组2
3 - 组3

会员组:
1 - 会员1/组1
2 - 会员1/组2
3 - 会员2/组3,等等。

我有以下这些类:

class Member(models.Model):
    nickname = models.CharField(max_length=30, blank=False)
    paid = models.BooleanField(default=False)

class MemberGroup(models.Model):
    member = models.ManyToManyField(Member)
    group_name = models.CharField(max_length=50, db_index=True)
    description = models.CharField(max_length=255)

我希望能在其他模型类中使用id/会员/组的组合(比如在BlogPost类中用MemberGroupId和帖子内容),但我不太确定怎么才能获取到那个特定的对象。现在的模型能生成正确的数据库表,但我不太清楚怎么获取代表链接表的对象。在Django的命令行界面中,当我获取MemberGroup(id=1)并尝试打印与这个MemberGroup关联的会员时,我得到的结果是:

 <django.db.models.fields.related.ManyRelatedManager object at 0x2ae6c10>

我需要创建另一个类,组(Group),然后让会员和组在会员组类中作为外键吗?这样才能实现我想要的功能,还是我可以继续用现在的设置?谢谢任何帮助!

2 个回答

3

首先,我会这样创建模型:

from django.db import models

class Group(models.Model):
    group_name = models.CharField(max_length=50, db_index=True)
    description = models.CharField(max_length=255)

class Member(models.Model):
    nickname = models.CharField(max_length=30, blank=False)
    paid = models.BooleanField(default=False)
    groups = models.ManyToManyField(Group)

然后你可以这样做:

>>> test_group = Group(group_name='Admin', description='Admin group')
>>> test_group.save()
>>> m1 = Member(nickname='Robert')
>>> m1.save()
>>> m1.groups.add(test_group)
>>> m1.save()
>>> m1.groups.all()
[<Group: Group object>]
>>> test_group.objects.get(group_name='Admin').member_set.all()
[<Member: Member object>]

这段代码创建了一个名为“Admin”的组,然后添加了一个成员“Robert”。它把“Robert”这个用户和“Admin”组关联起来。接着,我可以通过 member_set 来获取“Admin”组的所有成员。

补充说明:把 ManyToMany 字段放在 Group 模型里来指向成员其实没有什么问题,但在我看来,把成员和组关联起来似乎更合理,而不是把组和成员关联起来。

1

所以我又看了一遍关于多对多关系的文档,找到了正确的解决办法,就是在模型上使用这个“through”的设置。现在我的模型看起来是这样的:

class Member(models.Model):
    nickname = models.CharField(max_length=30, blank=False)
    paid = models.BooleanField(default=False)

class Group(models.Model):
    group_name = models.CharField(max_length=50, db_index=True)
    description = models.CharField(max_length=255)
    created_by = models.ForeignKey('Member', related_name='created_by')
    created_date = models.DateTimeField(auto_now=True)
    members = models.ManyToManyField(Member, through="Membership")

    def __unicode__(self):
        return self.group_name

class Membership(models.Model):
     member = models.ForeignKey(Member)
     group = models.ForeignKey(Group)
     active = models.BooleanField(default=True, db_index=True)
     join_date = models.DateTimeField(auto_now=True)
     league_manager = models.BooleanField(default=False, db_index=True)

     def __unicode__(self):
         return "%s (%s)" % (self.member, self.group)

现在我可以直接使用Membership这个类了,而之前虽然建立了关系,但没有明确的对象可以使用。谢谢大家。

撰写回答