我有会员模型和组模型,其中包含来自会员的外键
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')
现在我已经为Acivity创建了一个ModelForm
class ActivityForm(ModelForm):
class Meta:
model = Activity
如果我在模板中使用了ActivityForm的对象,则所有用户都将加载到参与者的“选择”输入中。我希望仅显示属于选择选项中显示的组(具有id = self.group_id)的成员。
有人可以帮我编写一个查询集,我可以将其包含在ActivityForm的 init 函数中吗?
答案 0 :(得分: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
如果更改为使用ManyToManyField
,我建议您修改字段名称和相关名称。在开发过程的早期进行更改会更容易,而不是在遇到无法修复的其他问题时。如果它更容易理解,只需这样思考:相关名称将在ForeignKey
或ManyToManyField
指向的模型上可访问,并包含queryset
0或更多条目。
所以,如果你有......
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
答案 1 :(得分: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。您的班级组现在允许您只将一个人存储到一个组中。
命名时可能会出现一些错误,因为您的相关名称非常混乱。