Reputation: 3
My goal is to display the total number of entries in a specific contest. Initially I tried doing this within the template section by incrementing a counter for each contest as I looped through entries. My thought is that when an entry submission is created, the total_submissions for the corresponding contest should be incremented, however I'm not sure how to do it.
Model:
class Contest(models.Model):
contest_name = models.CharField(max_length=200)
contest_description = models.CharField(max_length=5000)
contest_start_date = models.DateTimeField('start date')
contest_end_date = models.DateTimeField('end date')
submission_count = models.IntegerField(default=0)
def __str__(self):
return self.contest_name
class Submission(models.Model):
contest = models.ForeignKey(Contest, on_delete=models.CASCADE)
user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True)
date_uploaded = models.DateTimeField(auto_now_add=True)
votes = models.IntegerField(default=0)
def __init__(self):
#increment the submission_count variable for the corresponding contest
Other attempt by using templates:
<h1>Current Contests</h1>
<div class="row">
{% if current_contest_list %}
{% for contest in current_contest_list %}
<div class="col-sm-4"><h1><a href="{% url 'contests:detail' contest.id%}">{{ contest.contest_name }}</a></h1>
<img src="media/{{contest.display_image}}" class="img-responsive" alt="image">
{{ contest.contest_name }}
{% for submission in submission_list %}
{% if submission.contest == contest.contest_name %}
<P>Hi!</P>
{% endif %}
<p>{{ submission.contest }} {{ contest.contest_name }}</p>
{% if submission.contest == contest.contest_name %}
<P>Hi!</P>
{{ forloop.counter }}
{% set total_submissions = forloop.counter %}
{% endif %}
{% endfor %}
<p>Total entries: {{total_submissions}} </p>
When I did this, the total_submissions variable did not increment. What am I missing?
Upvotes: 0
Views: 59
Reputation: 3022
As I understand, you want to increase a contest's submission count when a new submission is added. To do that, you'll need
submission_count
when a new Submission
is inserted to the dbsubmission_count
when a Submission
is deletedTo do (1), you can override the save()
method of Submission
:
def save(self, *args, **kwargs):
if self.id is None: # To make sure this is an INSERT, not an UPDATE
contest = Contest.objects.select_for_update().get(id=self.contest.id)
contest.submission_count += 1
contest.save()
super().save(*args, **kwargs) # Call the "real" save() method.
To do (2), you can override the delete()
method:
def delete(self):
contest = Contest.objects.select_for_update().get(id=self.contest.id)
contest.submission_count -= 1
contest.save()
super().delete()
Note that this solution doesn't work if you creating or deleting submissions in bulk. See more at https://docs.djangoproject.com/en/2.1/topics/db/models/#overriding-predefined-model-methods
Personal Opinion: I wouldn't store submission count in db, unless the query to count number of submissions has noticeable impact on performance.
Upvotes: 1
Reputation: 5867
Django really discourages changing of data within templates, and they make it pretty hard to do. What you are trying to do won't work in a template.
In your template code, where is submission_list
coming from? If you want to iterate over all the submissions in each contest in your contest_list
, you would want to do something like:
{% for submission in contest.submission_set.all %}
To get the count, if your list is actually a Queryset (it usually is).. then the easiest way to get a count within the template is to use count
on the queryset, eg:
{{ contest.submission_set.all.count }}
This will result in another database query, but if you aren't worried about a super high volume of visitors it should be no problem.
Upvotes: 0