Reputation: 297
I'm trying to make some views in Ddjango when i click on a line in a tag in HTMl and i need some advise and please take into account that i'm a beginner in Django.
Indeed, i would like to change my view when i click on it, what will open a new view called like the Hash
inside my tag.
Let me explain you with this code called bap2pmonitoring.html
:
{% load staticfiles %}
<!DOCTYPE html>
<html lang="fr">
<head>
<link rel="stylesheet" type="text/css" href="{% static 'css/style.css' %}" />
</head>
<body>
<h1> BAP2P Monitoring</h1>
<table>
<tr>
<th width=550 height=20>Torrent Hash</th>
<th width=720 height=20>Torrent Name</th>
<th width=120 height=20>Size</th>
<th width=170 height=20>Active Peers</th>
</tr>
{% for torrent in torrents %}
<p id="demo">
<tr bgcolor=eeeeee>
<td width=550 height=20><a href="{{ url 'hash' torrent.Hash }}">{{ torrent.Hash }}</a></td>
<td width=720 height=20>{{ torrent.Name }}</td>
<td width=120 height=20>{{ torrent.Size }}</td>
<td width=170 height=20></td>
</tr>
</p>
{% endfor %}
</table>
</body>
</html>
I obtain thus this result:
![enter image description here][1]
My idea is that when i click in one of these 2 lines, it render a new view with informations about this torrent with the hash of the torrent as url like this:
127.0.0.1:8000/torrents/606d4759c464c8fd0d4a5d8fc7a223ed70d31d7b
Following the Django tutorial, i tried lot's of things without success and then i tried a "onclick" to start one of my def in my view.py
like this:
from django.shortcuts import render_to_response
from django.template import Template , Context
from polls.models import Torrent
# Create your views here.
# -*- coding: utf-8 -*-
def home(request):
return render_to_response('mysite/bap2pmonitoring.html', {'torrents':Torrent.objects.all()})
def details(request, torrent_hash):
return render_to_response('mysite/detail_torrent.html', {'torrents':Torrent.objects.filter(hash=torrent_hash)})
I also tried to display the hash as an url like this in urls.py
:
from django.conf.urls import patterns,include, url
from django.contrib import admin
from polls.models import Torrent
urlpatterns = patterns('polls.views',
url(r'^torrents$', 'home', name = 'home'),
url(r'^torrents/(?P<torrent_hash>)/$', 'details', name = 'hash'),
url(r'^admin/', include(admin.site.urls)),
)
I don't understand how can i resolve this, any idea are welcomed and appreciated
Now i'm obtaining this error page:
NoReverseMatch at /torrents
Reverse for 'hash' with arguments '(u'606d4759c464c8fd0d4a5d8fc7a223ed70d31d7b',)' and keyword arguments '{}' not found. 1 pattern(s) tried: ['torrents/(?P<torrent_hash>)/$']
And this Traceback:
Environment:
Request Method: GET
Request URL: http://127.0.0.1:8000/torrents
Django Version: 1.8.1
Python Version: 2.7.3
Installed Applications:
('django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'polls')
Installed Middleware:
('django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django.middleware.security.SecurityMiddleware')
Template error:
In template /home/florian/Documents/mysite/templates/mysite/bap2pmonitoring.html, error at line 23
Reverse for 'hash' with arguments '(u'606d4759c464c8fd0d4a5d8fc7a223ed70d31d7b',)' and keyword arguments '{}' not found. 1 pattern(s) tried: ['torrents/(?P<torrent_hash>)/$']
13 : <tr>
14 : <th width=550 height=20>Torrent Hash</th>
15 : <th width=720 height=20>Torrent Name</th>
16 : <th width=120 height=20>Size</th>
17 : <th width=170 height=20>Active Peers</th>
18 : </tr>
19 :
20 : {% for torrent in torrents %}
21 : <p id="demo">
22 : <tr bgcolor=eeeeee>
23 : <td width=550 height=20><a href=" {% url 'hash' torrent.Hash %} ">{{ torrent.Hash }}</a></td>
24 : <td width=720 height=20>{{ torrent.Name }}</td>
25 : <td width=120 height=20>{{ torrent.Size }}</td>
26 : <td width=170 height=20></td>
27 : </tr>
28 : </p>
29 : {% endfor %}
30 :
31 : </table>
32 :
33 : </body>
Traceback:
File "/usr/local/lib/python2.7/dist-packages/django/core/handlers/base.py" in get_response
132. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/florian/Documents/mysite/polls/views.py" in home
8. return render_to_response('mysite/bap2pmonitoring.html', {'torrents':Torrent.objects.all()})
File "/usr/local/lib/python2.7/dist-packages/django/shortcuts.py" in render_to_response
39. content = loader.render_to_string(template_name, context, using=using)
File "/usr/local/lib/python2.7/dist-packages/django/template/loader.py" in render_to_string
99. return template.render(context, request)
File "/usr/local/lib/python2.7/dist-packages/django/template/backends/django.py" in render
74. return self.template.render(context)
File "/usr/local/lib/python2.7/dist-packages/django/template/base.py" in render
209. return self._render(context)
File "/usr/local/lib/python2.7/dist-packages/django/template/base.py" in _render
201. return self.nodelist.render(context)
File "/usr/local/lib/python2.7/dist-packages/django/template/base.py" in render
903. bit = self.render_node(node, context)
File "/usr/local/lib/python2.7/dist-packages/django/template/debug.py" in render_node
79. return node.render(context)
File "/usr/local/lib/python2.7/dist-packages/django/template/defaulttags.py" in render
217. nodelist.append(node.render(context))
File "/usr/local/lib/python2.7/dist-packages/django/template/defaulttags.py" in render
507. six.reraise(*exc_info)
File "/usr/local/lib/python2.7/dist-packages/django/template/defaulttags.py" in render
493. url = reverse(view_name, args=args, kwargs=kwargs, current_app=current_app)
File "/usr/local/lib/python2.7/dist-packages/django/core/urlresolvers.py" in reverse
579. return force_text(iri_to_uri(resolver._reverse_with_prefix(view, prefix, *args, **kwargs)))
File "/usr/local/lib/python2.7/dist-packages/django/core/urlresolvers.py" in _reverse_with_prefix
496. (lookup_view_s, args, kwargs, len(patterns), patterns))
Exception Type: NoReverseMatch at /torrents
Exception Value: Reverse for 'hash' with arguments '(u'606d4759c464c8fd0d4a5d8fc7a223ed70d31d7b',)' and keyword arguments '{}' not found. 1 pattern(s) tried: ['torrents/(?P<torrent_hash>)/$']
Upvotes: 2
Views: 4448
Reputation: 1064
You'll need to:
change the context for your detail view to access only a single torrent, and also include your argument from the URL:
details(request, torrent_hash):
return render_to_response('mysite/detail_torrent.html', {'torrent':Torrent.objects.filter(hash=torrent_hash)})
use a URL like this, which passes through your torrent hash to the view:
url(r'^torrents/(?P<torrent_hash>)/$', 'details', name = 'hash'),
You'll also need your detail_torrent.html template, which you can then use your 'torrent' context in.
Edit to pre-empt another question:
In your main template, you can use this change to link through to the torrent. You are then passing the torrent.Hash variable through to your URL as the argument, which will be used for torrent_hash in the URL regex:
{% for torrent in torrents %}
<p id="demo">
<tr bgcolor=eeeeee>
<td width=560 height=20><a href="{% url 'hash' torrent.Hash %}">{{ torrent.Hash }}</a></td>
<td width=710 height=20>{{ torrent.Name }}</td>
<td width=110 height=20>{{ torrent.Size }}</td>
<td width=110 height=20></td>
</tr>
</p>
{% endfor %}
Upvotes: 3
Reputation: 111
Thanks to Ralph's suggestion, I managed to do the same thing as the poster. However, with one tweak, namely, I am staying (intentionally) on the initial page, i.e., in the above example I am only using
'mysite/bap2pmonitoring.html'
where I invoke
<a href="{{ url 'hash' torrent.Hash }}">{{ torrent.Hash }}</a>
(within the for loop)
the view consequently points back to 'mysite/bap2pmonitoring.html' instead of 'mysite/detail_torrent.html'
everything works well in terms of the link. However, once I click the link, and the result of the details view is displayed (correctly), the links of the loop disappear. Everything else of the initial page remains. Is there a way to prevent this, i.e., keep the links?
(The idea is to create a pannel and to display the details below, being able to update the details by the links of the pannel)
Upvotes: 0
Reputation: 11039
That onlick
attribute is not going to call your server side views functions. It is a JavaScript even handler so it is going to look for a JS function named details()
since it doesn't look like you have one it's not going to do anything. you can confirm this by opening up your browsers development tools and going to the "Console" tab. Once you're there click on of your rows and you'll see something that looks like this:
Uncaught ReferenceError: details is not defined
You will need to write a JS function that will back to your server and so your server can send a new page to be rendered. I would strongly recommend using jQuery for this as it will make your life much simpler.
First you need to modify your HTML as there are few things wrong:
{% for torrent in torrents %}
<tr class="torrent" id="{{ torrent.Hash }}" >
<td width=550 height=20>{{ torrent.Hash }}</td>
<td width=720 height=20>{{ torrent.Name }}</td>
<td width=120 height=20>{{ torrent.Size }}</td>
<td width=170 height=20></td>
</tr>
{% endfor %}
id
attributes on HTML elements should be unique and we will be using it later in our JS to get the right URL. There is no need to wrap <tr>
in a <p>
tag so let's get rid of it. I added a class to make our lives a little easier when writing the JS.
Now the JS:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script>
$(".torrent").on('click', function(){
var hash = $(this).attr('id');
window.location.href = '/torrents/' + hash;
});
</script>
Be sure to include this just above your closing <body>
tag in your template.
Alternatively you could not add a CSS class and use this jQuery selector $('tr')
but only do so if this will be the only table on the page.
This will create a URL for you and then open that URL when you click anywhere on the table row.
urlpatterns = patterns('polls.views',
url(r'^torrents$', 'home', name = 'home'),
url(r'^torrents/(?P<torrent_hash>)/$', 'details', name='hash'), # this line
url(r'^admin/', include(admin.site.urls)),
)
You will need to adjust the line I indicated so that it will work properly. And finally modify your view to accept your new parameter:
def details(request, torrent_hash):
return render_to_response('mysite/detail_torrent.html', {'torrents':Torrent.objects.get(Hash=torrent_hash)})
EDIT: One more step, to make it obvious to users that they can click on the table row to go to a new url you will want this in your CSS:
.torrent:hover {
cursor: pointer;
}
Upvotes: 1