filter queryset using values_list
Date: April 25th 2016
Last updated: April 25th 2016
I'll start by describing my django objective. I have a button in an html template labeled as "join group". I will also note that this html template has been given a list of groups collected from views.py (i.e. Group.objects.all()). When the user clicks on the "join" button, data is sent to a model containing, User and Group. I am calling this the GroupRequest model. Now... I want this button to change color and the label to say "request sent".
models.py
class GroupModerator(models.Model):
"""
Extends the group model. This model is used to provide editable control
over the groups privacy and accepting user requests.
"""
group_user = models.ForeignKey(User)
group_id = models.ForeignKey(Group)
STATUS = (('Open', 'Open'),('Full', 'Full'),)
group_status = models.CharField(max_length=4, choices=STATUS,default='Open')
def __str__(self):
return '{} --> {}'.format(self.group_user, self.group_id)
class GroupRequest(models.Model):
"""
A model to temporarily store User requests. The GroupModerator is included
so that they are alerted to a new request.
"""
user_requesting_groupjoin = models.ManyToManyField(User)
group_moderator_id = models.ForeignKey(GroupModerator)
group_id = models.ForeignKey(Group)
def __str__(self):
return '{}'.format(self.user_requesting_groupjoin)
views.py
Send data to html template.
@login_required
def groups(request):
groups_list = Group.objects.all()
context = {'groups_list': groups_list}
return render(request, 'surferprofile/groups.html', context)
My expectation is that I can access both GroupRequest and GroupModerator from the html template because they are connected to Group with a ForeignKey.
For example, I can do this...
<!--groups.html-->
{{group.grouprequest_set.all.0.user_requesting_groupjoin.id}}
However, this will only get the first User in the queryset. If I back up to get the queryset I seem to need to iterate over the list to access the content (i.e. for loop). That is, I can't seem to ask if a user is in this set.
<!--groups.html-->
{{group.grouprequest_set.all}}
Here is the context in which the button must change...
Groups.html
{% for group in groups_list %}
<!-- snipped (buttons appear in table format) -->
<!-- Warning: The following if statement is an indicator only
which is meant to show my logic -->
{% if GROUP_REQUEST in GROUP %} <!-- PROBLEM LINE -->
<!-- Note that join_group populates the GroupRequest Table -->
<a href="{% url 'surferprofile:join_group' my_group_id=group.id %}">
<button style="width: 120px; margin-left: 2%;"
type="button"
class="btn btn-success"> sent
</button>
</a>
{% else %}
<!-- There is programming logic in join_group function to
only allow one user request per group -->
<a href="{% url 'surferprofile:join_group' my_group_id=group.id %}">
<button style="width: 120px; margin-left: 2%;"
type="button"
class="btn btn-primary"> Join group
</button>
</a>
{% endif %}
{% endfor %}
My solution was to go back to views.py and provide a filtered list to groups.html by using a values_list. This means I only need to check that the group id is found in the GroupRequest model. I.e. my filtered values_list.
views.py
@login_required
def groups(request):
groups_list = Group.objects.all()
group_values_list = GroupRequest.objects.filter(
user_requesting_groupjoin=request.user).values_list(
'group_id', flat=True)
context = {'groups_list': groups_list, 'group_values_list': group_values_list}
return render(request, 'surferprofile/groups.html', context)
groups.html (update)
{% for group in groups_list %}
<!-- snipped -->
{% if group.id in group_values_list %} <!-- MODIFIED LINE -->
<a><button><!--snipped--> </button></a>
{% else %}
<a><button><!--snipped--> </button></a>
{% endif %}
{% endfor %}