I have a model for Group:
class Group(models.Model):
leader = models.ForeignKey(User, on_delete=models.CASCADE)
name = models.CharField(max_length=55)
description = models.TextField()
joined = models.ManyToManyField(User, blank=True)
size = models.BooleanField(default=False)
max_size = models.IntegerField(default=10)
closed = models.BooleanField(default=False, blank=True)
The idea is that Users can join groups (thus adding to the total joined
for that Group) and leave groups. They do that through this view:
def join_group(request, pk):
id_user = request.user.id
group = Group.objects.get(id=request.POST.get('group_id'))
account = Account.objects.get(user_id=id_user)
if group.joined.filter(id=request.user.id).exists():
group.joined.remove(request.user)
account.joined_groups.remove(group)
else:
group.joined.add(request.user)
account.joined_groups.add(group)
return HttpResponseRedirect(reverse('group_detail', args=[str(pk)]))
And template:
{% if user.is_authenticated %}
<form action="{% url 'join_group' group.pk %}" method="POST">
{% if group.closed == True %}
<div>Sorry, this group is closed</div>
{% else %}
{% csrf_token %}
{% if joined %}
<button type="submit" name="group_id" value="{{group.id}}">LEAVE</button>
{% else %}
<button type="submit" name="group_id" value="{{group.id}}">JOIN</button>
{% endif %}
{% endif %}
</form>
{% endif %}
Users joining and leaving groups works fine, the thing I'm trying to implement is when the total_joined == group.max_size
a function would be called to close
the group. Since, as of now the only way too close a Group is for the User who created it to go and update the Group to change closed=True
.
What I'm trying to do is call a function within the template to close the Group when it's reached max capacity ( or max_size
). The basic conditional works but I don't know how to call the function or even how to edit the current Group to change closed=True
:
{% if group.total_joined == group.max_size %}
{{ close_group function would go here }}
{% endif %}
the close_group view:
def close_chaburah(request, pk):
group = get_object_or_404(Group, id=request.POST.get('group_id'))
chaburah.closed == True
return HttpResponseRedirect(reverse('group_detail', args=[str(pk)]))
Is there a way to call this function once group.total_joined == group.max_size
using my conditional or does it have to triggered in a different way. Or should it be done in the join_group
view?
To test the conditional I hardcoded a link to call the function to close a Group:
{% if group.total_joined == group.max_size %}
<a href="{% url 'close_group' group.pk %}">Close Group</a>
{% endif %}
This worked in the sense that the link showed up when the conditional was met, but when I clicked the link I got an error group.models.Group.DoesNotExist: Group matching query does not exist
Is there a better way to close a Group? Should I be calling the function with the conditional in the view? Or should I call it in the template? Should it be in join_group
or in a specific close_group
function?
CodePudding user response:
For this, you might want to perform ac check in your join function prior to adding the user and after adding the user. This way, if the group is full, you can return that to the view, or if the user is the last to join the group, you can then close it. something like this may work:
def check_group(group):
if group.max_size == group.size and group.closed == False:
# Closes group because it has rached max size
group.closed = True
group.save()
# returns True since group has reached max size
return group.closed
elif group.max_size == group.size:
# Still returns True because the group is closed
return group.closed
else:
# Returns False since group is not max size or closed, new member can be added
return group.closed
Call this once before trying to add the member to the group. If it returns False, add the member, if it returns true, tell them the group is full. Then call this again after the member is added to see if the group needs to be closed now that they have joined.
CodePudding user response:
I would create a Model method that checks whether the group is full or not, you can then use this in your template and view more easily then recreating any logic.
class Group(models.Model):
...
@property
def is_full(self):
return self.total_joined == self.max_size
I would then include a post_save
signal that checks the is_full
property and updates closed
if so:
@receiver(models.signals.post_save, sender=Group)
def set_closed(sender, instance, using, **kwargs):
if instance.is_full and not instance.closed:
instance.closed = True
instance.save()
elif not instance.is_full and instance.closed:
instance.closed = False
instance.save()