I have a Django form that contains a table with rows that reflect course objects from a database . Each row contains a checkbox input. This form also has some submit buttons that allow the user to filter the course objects shown in the table (besides a generic submit button).
This form is used to update the users profile with courses they are interested in. When the form is submitted, courses in the filter that are unchecked should be removed from the interested M2M relation and checked ones should be added to it.
To do that I need to know which inputs are checked , which I know how to retrieve, but I also need to know which courses are in the table that have unchecked inputs. Retreiving this is not as easy as ‘all the other courses in the database’ because my table does not always contain all course objects. If a user previously clicked one of the filter buttons, then the table contains only a filtered set of courses.
So I need to know which courses were used to create the table at rendertime, i.e. the ones that were injected as HTML context variable. Of course I know this at rendertime, but I don’t know how to retrieve it at POST request processing time.
I researched potential solutions and read something about using hidden inputs. The idea would be to give each row a hidden input with the course reference, which I could retrieve when the form is submitted. However I am curious if this would be the best way to go. Or if there is a better solution to this issue.
Please have a look at the code below, specifically the update_user_interests() function : How do I retrieve the courses that are in the form table context?
Form :
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" name="submit" value='Submit'/>
{% for filter in filters%}
<input type="submit" name="filter" value='{{filter}}'/>
{% endfor %}
<table class="table table-striped table-bordered">
<tbody>
{% for course in courses %}
<tr>
<td>
<input type="checkbox"
name="checks"
value={{course.reference}}
{% if course in user_interests %} checked {% endif %}>
</td>
<td>
{{ course.reference|default:"" }}
</td>
<td>
{{ course.name|default:"" }}
</td>
<td>
{{ course.description|default:"" }}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</form>
View:
def table(request):
profile = Profile.objects.get(user=request.user.id)
allcourses = Course.objects.all()
filteropts = ['A','B','C']
if request.method == 'GET':
tablecourses = allcourses
user_interests = profile.interests.all()
if request.method == 'POST':
# update user interests from submitted form
update_user_interests(request, profile)
user_interests = profile.interests.all()
# filter the table if filter button clicked
filter = get_filter(request)
if filter:
tablecourses = Course.objects.filter(curriculum=filter).values()
else:
tablecourses = allcourses
return render(request, 'table.html',
{'courses': tablecourses,
'user_interests' : user_interests,
'filters':filteropts})
Helpers:
def get_filter(request):
if 'filter' in request.POST:
return request.POST.getlist("filter")[0]
def update_user_interests(request, profile):
tablecourses = [] # How do I retrieve the courses that are in the form table ????
checked_courses = request.POST.getlist("checks")
for course in tablecourses:
ref = course.reference
if ref in checked_courses:
profile.interests.add(coursemodel)
else:
profile.interests.remove(coursemodel)
profile.save()
Models :
class Course(models.Model):
name = models.CharField(
unique=False,
null=False,
blank=False,
max_length=250
)
reference = models.CharField(
unique=True,
null=False,
blank=False,
max_length=250
)
curriculum = models.CharField(
unique=False,
null=True,
blank=True,
max_length=250,
)
description = models.TextField(
unique=False,
null=True,
blank=True,
max_length=2000,
)
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
interests = models.ManyToManyField(
Course,
related_name='interests')
user22574281 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
1