I have Member model and Group model with Foreign key from Member
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')
And I have created another model, Activity which will refer both Group and 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')
Now I have created a ModelForm for Acivity
class ActivityForm(ModelForm):
class Meta:
model = Activity
If i have used object of ActivityForm in template, all users will be loaded in participants 'Select' input. I wish to display only those members belonging to the group(with id= self.group_id) displayed in Select Option.
Can someone please help me in writing a queryset which I could include in init function of ActivityForm to do that?
Shouldn't Member
have a foreign key to Group
? You want to have many members in a group not many groups with a single member right?
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')
And then you can do:
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
With the change to using a ManyToManyField
I would recommend fixing your field names and related names too. It would be easier to make the changes early in the development process rather than when you run into a different problem that can't be fixed. If it makes it any easier to understand just think of it this way: the related name will be accessible on the model that the ForeignKey
or ManyToManyField
points to and will contain a queryset
with 0 or more entries.
So if you have...
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')
Then you can do things like...
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
And your form...
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
I think that would work, but if not:
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
Your ActivityForm class need to have an atribute:
class ActivityForm(ModelForm):
participants = forms.ModelMultipleChoiceField(queryset=Member.objects.filter(members__id==self.instance.group_id))
Your __init__ function should look like this:
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) You should rename "related_name" in group. The related name means how the field will be known from the other class eg. from the Member class
2) I think that "group_members" in your context should be ManyToManyField. Your class Group now allows you to store only one person to a group.
There could be some mistakes in naming because you have very confusing related names.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.