Reputation: 247
I just want to call a view funciton from a template, and I've seen that I have to do it with the reverse function. I want to pass a parameter to the view function, but I don't want to show it in the url. Is it possible? Here is my code and the error:
urls.py
url(r'^perfil/deleteDownloadedTrack/$','principal.views.delete_downloaded_track', name='delete_downloaded_track'),
views.py
def delete_downloaded_track(request, track):
...
return HttpResponseRedirect(reverse('profile_detail'))
template.html
{% for track in downloadedTracks %}
<tr>
<td>
{{track.name}}
</td>
<td>
<div class="botoForm" onclick="location.href='{% url "principal.views.delete_downloaded_track" track %}'"> Eliminar </div>
</td>
{% endfor %}
and the error:
Reverse for 'principal.views.delete_downloaded_track' with arguments '(<DownloadedTrack: DownloadedTrack object>,)' and keyword arguments '{}' not found.
Thanks!!
Upvotes: 0
Views: 1005
Reputation: 53719
The recommended way by the HTML standard to handle any request that changes data on the server, is to use a POST request.
{% for track in downloadedTracks %}
<tr>
<td>
{{track.name}}
</td>
<td>
<form method="POST" action="{% url principal.views.delete_downloaded_track %}" id="delete-form-{{ track.id }}">
{% csrf_token %}
<input type="hidden" name="track_id" value="{{ track.id }}" />
<div class="botoForm" onclick="document.getElementById('delete-form-{{ track.id }}').submit()"> Eliminar </div>
</form>
</td>
{% endfor %}
The {% csrf_token %}
prevents cross-site forgery requests by validating that the person you send this form to is also the person sending it back through a POST request. Just retrieve the id in your view by using:
if request.method == 'POST':
id = request.POST.get("track_id", None)
track = Track.objects.get(id=id)
Data send through POST will not show in the url.
Upvotes: 2
Reputation: 638
If you don't wish to show the parameter in your URL, then you probably want to pass it in as a query parameter, e.g.
<host_and_path>/perfil/deleteDownloadedTrack/?track_id=<some_track_id>
.
So your view would look like this:
def delete_downloaded_track(request):
track_id = request.GET.get('track_id')
# get track based on track_id and delete it.
and your template like this (assuming you pass in the reverse of delete_downloaded_track as delete_url in the template context):
{% for track in downloadedTracks %}
<!-- template code -->
{% with delete_url|add:"?track_id="|add:track.id as url_with_id %}
<a href="{{url_with_id|safe}}">Delete</a>
{% endwith %}
{% endfor %}
Upvotes: 1