0

我有成员模型和组模型,其中包含来自成员的外键

class Member(models.Model):
    member_name = models.CharField(max_length=100)
    member_dob = models.DateField()

class Group(models.Model):
    group_name = models.CharField(max_length=100)
    group_owner = models.ForeignKey(Member, related_name='owner')
    group_members = models.ManyToManyField(Member, related_name='members')

我创建了另一个模型,Activity,它将同时引用 Group 和 Member

class Activity(models.Model):
    group_id = models.ForeignKey(Group)
    topic = models.CharField(max_length=100)
    start_by = models.ForeignKey(Member, related_name='started')
    participants = models.ManyToManyField(Member, related_name='participants')

现在我为 Activity 创建了一个 ModelForm

class ActivityForm(ModelForm):
    class Meta:
        model = Activity

如果我在模板中使用了 ActivityForm 对象,所有用户都将加载到参与者的“选择”输入中。我希望仅显示属于 Select Option 中显示的组的那些成员(id= self.group_id)。

有人可以帮我编写一个查询集,我可以将它包含在ActivityForm 的init函数中来做到这一点吗?

4

2 回答 2

2

不应该Member有外键Group吗?您希望一个组中有很多成员,而不是一个成员的多个组,对吗?

class Member(models.Model):
    name = models.CharField(max_length=100)
    dob = models.DateField()
    group = modes.ForeignKey('Group', related_name='members')

class Group(models.Model):
    name = models.CharField(max_length=100)
    owner = models.ForeignKey('Member', related_name='owned_groups')

class Activity(models.Model):
    group = models.ForeignKey('Group', related_name='activities')
    topic = models.CharField(max_length=100)
    start_by = models.ForeignKey('Member', related_name='started_activities')
    participants = models.ManyToManyField('Member', related_name='participating_activities')

然后你可以这样做:

class ActivityForm(ModelForm):
    def __init__(self, *args, **kwargs):
        super(ActivityForm, self).__init__(*args, **kwargs)
        if 'initial' in kwargs:
            self.fields['participants'].queryset = Member.objects.filter(group=initial.group)
    class Meta:
        model = Activity

编辑


随着使用 a 的更改,ManyToManyField我建议您也修复您的字段名称和相关名称。在开发过程的早期进行更改比在遇到无法修复的不同问题时更容易。如果它更容易理解,请这样想:相关名称将可在ForeignKeyorManyToManyField指向的模型上访问,并且将包含queryset具有 0 个或更多条目的 a。

所以如果你有...

class Member(models.Model):
    name = models.CharField(max_length=100)
    dob = models.DateField()

class Group(models.Model):
    name = models.CharField(max_length=100)
    owner = models.ForeignKey('Member', related_name='owned_groups')
    members = models.ManyToManyField('Member', related_name='groups')

class Activity(models.Model):
    group = models.ForeignKey(Group)
    topic = models.CharField(max_length=100)
    start_by = models.ForeignKey('Member', related_name='started_activities')
    participants = models.ManyToManyField('Member', related_name='activities')

然后你可以做类似的事情......

g1 = Group.objects.create(name='Group 1', ...)
g2 = Group.objects.create(name='Group 2', ...)

member = Member.objects.get(name='John')
member.groups.all() # Get all the groups for the member
member.groups.add(g1, g2) # Add the member to 2 groups
member.activities.all() # Get all activities the member is a participant in
member.started_activities.all() # Get all activities started by the user

还有你的表格...

class ActivityForm(ModelForm):
    ...
    def __init__(self, *args, **kwargs):
        super(ActivityForm, self).__init__(*args, **kwargs)
        if 'initial' in kwargs:
            self.fields['participants'].queryset = initial.group.members.all()

    class Meta: 
        model = Activity

我认为这会起作用,但如果不是:

class ActivityForm(ModelForm):
    ...
    def __init__(self, *args, **kwargs):
        super(ActivityForm, self).__init__(*args, **kwargs)
        if 'initial' in kwargs:
            self.fields['participants'].queryset = Member.objects.filter(group__id=initial.group.id)

    class Meta: 
        model = Activity
于 2013-09-04T20:17:24.823 回答
0

您的 ActivityForm 类需要有一个属性:

class ActivityForm(ModelForm):
    participants = forms.ModelMultipleChoiceField(queryset=Member.objects.filter(members__id==self.instance.group_id))

您的 __init__ 函数应如下所示:

def __init__(self, *args, **kwargs):
    # call parent
    super(ActivityForm, self).__init__(*args, **kwargs)
    # fill initial values
    self.fields['participants'].initial = [c.pk for c in Member.objects.filter(members__id=self.instance.group_id, participants__in=self.instance)

1)您应该在组中重命名“related_name”。相关名称表示如何从其他类中知道该字段,例如。从成员类

2)我认为您的上下文中的“group_members”应该是ManyToManyField。您的班级群组现在允许您将一个人存储到一个群组中。

命名可能会出现一些错误,因为您的相关名称非常混乱。

于 2013-09-04T20:09:03.480 回答