dynamische html Seite mit Ajax

Django, Flask, Bottle, WSGI, CGI…
erdmulch
User
Beiträge: 230
Registriert: Samstag 17. Juli 2010, 19:50

hallo nochmals,

ich glaub ich hab es nun verstanden wie es geht und habe nur noch einen kleinen Fehler. Und zwar sieht so meine javascript funktion aus, die alle 10sec geladen wird:

Code: Alles auswählen

function loadContent()
{
    {% include 'create_ajax_request.js' %}    
    request.open('post', "{% url Wetterstation.views.index %} ", true);
    return false;
}

Leider erscheint dann folgende Fehlermeldung:

Code: Alles auswählen

NoReverseMatch at /articles/

Reverse for 'Wetterstation.views.index' with arguments '()' and keyword arguments '{}' not found.

Request Method: 	GET
Request URL: 	http://192.168.0.110:9090/articles/
Django Version: 	1.4.2
Exception Type: 	NoReverseMatch
Exception Value: 	

Reverse for 'Wetterstation.views.index' with arguments '()' and keyword arguments '{}' not found.

Exception Location: 	/usr/local/lib/python2.6/dist-packages/Django-1.4.2-py2.6.egg/django/template/defaulttags.py in render, line 424
Python Executable: 	/usr/bin/python
Python Version: 	2.6.5
Python Path: 	

['/home/peter/tmp/djangoprojs/Wetterstation',
 '/usr/local/lib/python2.6/dist-packages/pymodbus-0.5.1-py2.6.egg',
 '/usr/local/lib/python2.6/dist-packages/pyserial-2.6-py2.6.egg',
 '/usr/local/lib/python2.6/dist-packages/nose-1.1.2-py2.6.egg',
 '/usr/local/lib/python2.6/dist-packages/Django-1.4.2-py2.6.egg',
 '/usr/lib/python2.6',
 '/usr/lib/python2.6/plat-linux2',
 '/usr/lib/python2.6/lib-tk',
 '/usr/lib/python2.6/lib-old',
 '/usr/lib/python2.6/lib-dynload',
 '/usr/lib/python2.6/dist-packages',
 '/usr/lib/python2.6/dist-packages/PIL',
 '/usr/lib/python2.6/dist-packages/gst-0.10',
 '/usr/lib/pymodules/python2.6',
 '/usr/lib/python2.6/dist-packages/gtk-2.0',
 '/usr/lib/pymodules/python2.6/gtk-2.0',
 '/usr/lib/python2.6/dist-packages/wx-2.8-gtk2-unicode',
 '/usr/local/lib/python2.6/dist-packages']

Server time: 	Sat, 8 Dec 2012 21:23:21 +0100
Benutzeravatar
/me
User
Beiträge: 3561
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

erdmulch hat geschrieben:

Code: Alles auswählen

NoReverseMatch at /articles/

Reverse for 'Wetterstation.views.index' with arguments '()' and keyword arguments '{}' not found.
Dann enthält deine urls.py keinen url-Eintrag mit dem Namen Wetterstation.views.index.
erdmulch
User
Beiträge: 230
Registriert: Samstag 17. Juli 2010, 19:50

Oh, man ich hangle von einem Problem in das nächste und doch bin ich nur noch einen Katzensprung von der Lösung entfernt.
nun erscheint folgende Meldung:

Code: Alles auswählen


TemplateSyntaxError at /articles/

Invalid block tag: '/home/peter/tmp/djangoprojs/Wetterstation/Wetterstation/articles.views.index', expected 'endblock'

Request Method: 	GET
Request URL: 	http://192.168.0.110:9090/articles/
Django Version: 	1.4.2
Exception Type: 	TemplateSyntaxError
Exception Value: 	

Invalid block tag: '/home/peter/tmp/djangoprojs/Wetterstation/Wetterstation/articles.views.index', expected 'endblock'

Exception Location: 	/usr/local/lib/python2.6/dist-packages/Django-1.4.2-py2.6.egg/django/template/base.py in invalid_block_tag, line 320
Python Executable: 	/usr/bin/python
Python Version: 	2.6.5
Python Path: 	

['/home/peter/tmp/djangoprojs/Wetterstation',
 '/usr/local/lib/python2.6/dist-packages/pymodbus-0.5.1-py2.6.egg',
 '/usr/local/lib/python2.6/dist-packages/pyserial-2.6-py2.6.egg',
 '/usr/local/lib/python2.6/dist-packages/nose-1.1.2-py2.6.egg',
 '/usr/local/lib/python2.6/dist-packages/Django-1.4.2-py2.6.egg',
 '/usr/lib/python2.6',
 '/usr/lib/python2.6/plat-linux2',
 '/usr/lib/python2.6/lib-tk',
 '/usr/lib/python2.6/lib-old',
 '/usr/lib/python2.6/lib-dynload',
 '/usr/lib/python2.6/dist-packages',
 '/usr/lib/python2.6/dist-packages/PIL',
 '/usr/lib/python2.6/dist-packages/gst-0.10',
 '/usr/lib/pymodules/python2.6',
 '/usr/lib/python2.6/dist-packages/gtk-2.0',
 '/usr/lib/pymodules/python2.6/gtk-2.0',
 '/usr/lib/python2.6/dist-packages/wx-2.8-gtk2-unicode',
 '/usr/local/lib/python2.6/dist-packages']

Server time: 	Sun, 9 Dec 2012 00:36:53 +0100



um es genau zusagen meckert er diese Zeile an:

Code: Alles auswählen

function loadContent()
 {
 	request.open('post', "{% /home/peter/tmp/djangoprojs/Wetterstation/Wetterstation/articles.views.index %} ", true);
 }
Sirius3
User
Beiträge: 18250
Registriert: Sonntag 21. Oktober 2012, 17:20

Um es deutlich zu sagen: Deine Katze ist ein betrunkener Elefant, der von einer Ecke in
die andere torkelt.

Das einzige was ich aus Deinen letzten Posts entnehme ist, dass Du die richtige
verwendung von Tags:
{% url Wetterstation.views.index %}
in das hier umgewandelt hast:
{% /home/peter/tmp/djangoprojs/Wetterstation/Wetterstation/articles.views.index %}
Natürlich erscheint jetzt eine andere Fehlermeldung, weil die Template-Sprache von django
mit dieser Zeile absolut nichts anfangen kann. Tags haben immer ein KeyWord, hier
im oberen Fall url. Unten fehlt es.
Absolute Pfadangaben haben in Templates absolut nichts verloren.

Wenn Du mal Deine eigene urls.py anschaust:

Code: Alles auswählen

urlpatterns = patterns('',
   (r'^articles/$', 'Wetterstation.articles.views.index'),
)
dann wirst Du relativ schnell feststellen, dass die url die Du im Template verwendest nicht
den selben Namen hat, wie das was in urls.py steht. (--> "articles" <--)
Und wie schon 1000mal von /me gesagt, brauchst Du noch eine zweite URL um
die Ajax-Daten abzufragen, weil sie entweder json- oder xml-Daten sind, die in javscript
weiterverarbeitet werden, oder aber Teilstücke von HTML-Seiten, aber niemals komplette
HTML-Seiten.
Benutzeravatar
/me
User
Beiträge: 3561
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

erdmulch hat geschrieben:

Code: Alles auswählen

function loadContent()
 {
 	request.open('post', "{% /home/peter/tmp/djangoprojs/Wetterstation/Wetterstation/articles.views.index %} ", true);
 }
Ich glaube ich weiß, was du da tun willst, aber du hast die Prinzipien von Django und die Template-Syntax noch nicht verstanden.

{% und %} sind in einem Template die öffnenden bzw. schließenden Kennzeichner für ein Tag. Nun hat Django aber kein Tag namens /home/peter/tmp/djangoprojs/Wetterstation/Wetterstation/articles.views.index definiert. Das Tag, das dir einen Link aus der urls.py automatisch generiert heißt {% url viewname %}. Dir fehlt also ein url.

Zudem glaube ich nicht, dass du die View wirklich so benannt hast und wenn, dann wäre das ein äußerst unpraktischer Name. So wie das aussieht müsste deine urls.py wie folgt aussehen.

Code: Alles auswählen

urlpatterns = patterns('',
    url(r'^articles/$', 'Wetterstation.articles.views.index',
        name='/home/peter/tmp/djangoprojs/Wetterstation/Wetterstation/articles.views.index'
    ),
)
Wie wäre es denn einfach mit dem folgenden Namen?

Code: Alles auswählen

urlpatterns = patterns('',
    url(r'^articles/$', 'Wetterstation.articles.views.index',
        name='Wetterstation.articles.index'
    ),
)
Ein Name ist genau das: nur ein Name. Ein Name über den man den Eintrag referenzieren kann. Er muss nicht zwangsläufig mit dem Pfad zur View übereinstimmen und er sollte auf keinen Fall die physikalische Struktur zu einem Pfad abbilden. Wozu sollte das auch gut sein? Möchtest du den Namen um keine Missverständnisse aufkommen zu lassen dann auch jedes Mal ändern wenn du das System wechselst? Genau dafür ist doch der Name gedacht. Du bekommst eine von der konkreten Implementierung abgekoppelte Referenz.

Stell dir mal vor, du änderst später mal im Rahmen eines Redesigns die URL:

Code: Alles auswählen

urlpatterns = patterns('',
    url(r'^myapp/articles/$', 'Wetterstation.articles.views.index',
        name='Wetterstation.articles.index'
    ),
)
Jetzt müssen alle Templates in denen bisher der alte Link war auf den neuen Link umgeschrieben werden. Wenn du jetzt konsequent statt eines fixen Links den Namen in deinen Templates verwendet hast, dann musst du die Templates nicht anpassen! Das url-Tag kümmert sich schon automatisch darum, dass jetzt der passende Link eingetragen wird. Glaub mir, wenn du die manuelle Änderung einmal mit 25 Templates gemacht hast, dann weißt du, dass du ab jetzt konsequent nur noch über den Namen gehen willst statt beim nächsten Mal vielleicht 100 Templates manuell ändern zu müssen.
erdmulch
User
Beiträge: 230
Registriert: Samstag 17. Juli 2010, 19:50

jetzt kommt zwar keine Fehlermeldung mehr, aber wenn ich auf den html Button klicke passiert auch sonst nichts.
Beginnen wir ganz von vorne bei den html seiten.

die html Seite funktioniert wie folgt:
ich habe einen Button, wenn ich diesen drücke wird mit der onclick Methode eine Javascript funktion ausgelöst, was auch funktioniert, das sehe ich daran dass ein Fenster mit "Test" aufblockt. Allerdings hätte ich nun erwartet, dass ein request auf die Seite: /home/peter/tmp/djangoprojs/Wetterstation/Wetterstation/articles.views.index gemacht wird

Code: Alles auswählen

{% block content %}
<script type="text/javascript">

function loadContent()
{
    alert( 'Test' );
    request.open('post', "{% url /home/peter/tmp/djangoprojs/Wetterstation/Wetterstation/articles.views.index %} ", true);
    return false;
}
</script>

<html>
<body>

<p id="myContent">
<ul>
{% for article in latest_articles_list %}
  <li>
     <a href="/articles/{{ article.id }}/">
      {{ article.title }}
     </a>
  </li>
{%endfor%}
</ul>
</p>
  <input type="button" name="Text 1" value="Text 1 anzeigen" onclick="loadContent();">
</body>
</html>
{% endblock %}

meine views.py ist unter /home/peter/tmp/djangoprojs/Wetterstation/Wetterstation/articles/views.py abgelegt und sieht wie folgendermaßen aus:

Code: Alles auswählen

#!/usr/bin/env python
#-*- coding: utf-8 -*-



from django.template import Context, loader
from django.http import HttpResponse
from django.shortcuts import render_to_response
from django.template.response import TemplateResponse
from Wetterstation.articles.models import Article, Talkback
from django.shortcuts import render


def index(request):
    "Create a list of the 5 latest articles"
    latest_articles_list = Article.objects.all().order_by('-pub_date')[:5]
    return render(request, 'articles.html', {'latest_articles_list': latest_articles_list,})
bedeutet, dass wenn ich die Seite 192.168.0.110:8000/articles in meinem Browser aufrufe, dass dann ein Datenbankzugriff erfolgt und die letzten 5 Einträge von meiner Datenbank auf meiner html Seite angezeigt werden, was auch funktioniert.

Jetzt hätte ich allerdings erwartet, dass wenn die html Seite aufgebaut wurde und ich auf den Button klicke dass ein request auf meine html seite erfolgt und die daten aus der Datenbank neu geladen werden. Allerdings passiert gar nichts.

meine urls.py sieht übrigens wie folgt aus:

Code: Alles auswählen

from django.conf.urls import patterns, include, url
urlpatterns = patterns('',
    url(r'^articles/$', 'Wetterstation.articles.views.index',
        name='/home/peter/tmp/djangoprojs/Wetterstation/Wetterstation/articles.views.index'
    ),
)
Sirius3
User
Beiträge: 18250
Registriert: Sonntag 21. Oktober 2012, 17:20

Hallo erdmulch,

dass nichts passiert, kann viele Gründe haben.
Gibt es irgendwelche javascript-Fehler?
Was macht die Function request.open überhaupt?
Wo wird das Ergebnis des Requests in javascript weiterverarbeitet?
Sagen die django-Server-Logs dass beim Drücken des Buttons die Seite /articles angefragt wird?

Grüße
Sirius
Benutzeravatar
/me
User
Beiträge: 3561
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

erdmulch hat geschrieben:

Code: Alles auswählen

    url(r'^articles/$', 'Wetterstation.articles.views.index',
        name='/home/peter/tmp/djangoprojs/Wetterstation/Wetterstation/articles.views.index'
    ),
/home/peter/tmp/djangoprojs/Wetterstation/Wetterstation/articles.views.index? :? Welch ein deskriptiver Name. :evil:

OK, ich bin raus aus diesem Thread. Das wird mir zu stressig.

"Sirius, übernehmen Sie."
erdmulch
User
Beiträge: 230
Registriert: Samstag 17. Juli 2010, 19:50

Es erscheint folgende Meldung:

Django version 1.4.2, using settings 'Wetterstation.settings'
Development server is running at http://0.0.0.0:9090/
Quit the server with CONTROL-C.
/usr/local/lib/python2.6/dist-packages/Django-1.4.2-py2.6.egg/django/template/defaulttags.py:1235: DeprecationWarning: The syntax for the url template tag is changing. Load the `url` tag from the `future` tag library to start using the new behavior.
category=DeprecationWarning)
[09/Dec/2012 13:20:32] "GET /articles/ HTTP/1.1" 200 2985
Sirius3
User
Beiträge: 18250
Registriert: Sonntag 21. Oktober 2012, 17:20

und ich geh mal davon aus, es kommen keinen weiteren
GET /articles/
Zeilen wenn Du mehrmals auf Deinen Knopf drückst.
Was sagt denn die Javascript-Konsole Deines Browsers?
erdmulch
User
Beiträge: 230
Registriert: Samstag 17. Juli 2010, 19:50

Hallo nochmals,

ich glaub dass es definitiv an diesem Code liegt:

Code: Alles auswählen

function loadContent()
{    
    request.open('post', "{% url /home/peter/tmp/djangoprojs/Wetterstation/Wetterstation/articles.views.index %} ", true);
    return false;
}
will nicht die Lösung, sondern den Lösungsweg.
Nach meiner Logik müsste, die views.py aufgerufen werden. In dier views.py wird die Datenbank abfrage gemacht. Ist meine Logik generell richtig? oder mach ich was falsch?
muss ich noch was importieren?
Sirius3
User
Beiträge: 18250
Registriert: Sonntag 21. Oktober 2012, 17:20

Eine url im Browser, bei Dir also "http://localhost:8000/article/" wird
über die regulären Ausdrücke in url.py in eine Funktion aufgelöst, bei Dir
def index(request): ...
Diese Funktion liefert ein HTTPResponse zurück, der dann wieder im
Browser angezeigt wird.

Da Du aber meine Fragen nicht beantwortest, scheinst Du auch nicht
an irgendwelchen Wegen interessiert zu sein, die zu einer Lösung führen.
erdmulch
User
Beiträge: 230
Registriert: Samstag 17. Juli 2010, 19:50

sorry, so war das nicht gemeint.
Nein es kommen keine weiteren get methoden wenn ich auf den Button klicke.
darum kann ich es auch nicht debuggen mit meinem Browser. wie gesagt, ich denke dass das Problem an meiner Javascript Funktion liegt. Aber ich kann es eben nicht 100%ig sagen

hast du so was mal programmiert?
wie sieht deine Javascript Funktion aus?
BlackJack

Um mal Sirius3 zu wiederholen: „Was sagt denn die Javascript-Konsole Deines Browsers?”

Setz Dich mit Deinem Browser auseinander und dessen Dokumentation wie man JavaScript dort „verfolgen” kann. Wenn das mit Deinem Browser nicht geht, dann installiere entsprechende Erweiterungen. Wenn es die nicht gibt, verwende einen anderen Browser um mit JavaScript zu entwickeln.
erdmulch
User
Beiträge: 230
Registriert: Samstag 17. Juli 2010, 19:50

ich hoffe ihr könnt damit was anfangen

Code: Alles auswählen


<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta name="robots" content="NONE,NOARCHIVE">
<title>403 Forbidden</title>
<style type="text/css">
html * { padding:0; margin:0; }
body * { padding:10px 20px; }
body * * { padding:0; }
body { font:small sans-serif; background:#eee; }
body>div { border-bottom:1px solid #ddd; }
h1 { font-weight:normal; margin-bottom:.4em; }
h1 span { font-size:60%; color:#666; font-weight:normal; }
#info { background:#f6f6f6; }
#info ul { margin: 0.5em 4em; }
#info p, #summary p { padding-top:10px; }
#summary { background: #ffc; }
#explanation { background:#eee; border-bottom: 0px none; }
</style>
</head>
<body>
<div id="summary">
<h1>Forbidden <span>(403)</span></h1>
<p>CSRF verification failed. Request aborted.</p>
</div>
<div id="info">
<h2>Help</h2>
<p>Reason given for failure:</p>
<pre>
CSRF cookie not set.
</pre>
<p>In general, this can occur when there is a genuine Cross Site Request Forgery, or when
<a
href='http://docs.djangoproject.com/en/dev/ref/contrib/csrf/#ref-contrib-csrf'>Django's
CSRF mechanism</a> has not been used correctly. For POST forms, you need to
ensure:</p>
<ul>
<li>Your browser is accepting cookies.</li>
<li>The view function uses <a
href='http://docs.djangoproject.com/en/dev/ref/templates/api/#subclassing-context-requestcontext'><code>RequestContext</code></a>
for the template, instead of <code>Context</code>.</li>
<li>In the template, there is a <code>{% csrf_token
%}</code> template tag inside each POST form that
targets an internal URL.</li>
<li>If you are not using <code>CsrfViewMiddleware</code>, then you must use
<code>csrf_protect</code> on any views that use the <code>csrf_token</code>
template tag, as well as those that accept the POST data.</li>
</ul>
<p>You're seeing the help section of this page because you have <code>DEBUG =
True</code> in your Django settings file. Change that to <code>False</code>,
and only the initial error message will be displayed. </p>
<p>You can customize this page using the CSRF_FAILURE_VIEW setting.</p>
</div>
</body>
</html> 
Benutzeravatar
/me
User
Beiträge: 3561
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

erdmulch hat geschrieben:

Code: Alles auswählen

<h1>Forbidden <span>(403)</span></h1>
<p>CSRF verification failed. Request aborted.</p>
Ich konnte das Lurken ja doch nicht lassen.

Ein CSRF-Problem. Steht doch da. Darauf hatte ich schon vor 6 Tagen hingewiesen und auch darauf verlinkt.
erdmulch
User
Beiträge: 230
Registriert: Samstag 17. Juli 2010, 19:50

Hallo,

mir würde erklärt dass es sich hierbei um ein CSRF-Problem handelt?
kann mir jemand sagen was das ist? bzw. wie man sowas umgehen kann?
BlackJack

@erdmulch: Ist jetzt nicht Dein Ernst oder‽ Im Beitrag davor hat /me doch geschrieben das er da einen Link zu geschrieben hatte. Folge dem doch mal.
erdmulch
User
Beiträge: 230
Registriert: Samstag 17. Juli 2010, 19:50

hallo nochmals,

vielleicht hab eich mich da falsch ausgedrückt. Bisher hab ich meine Views so programmiert:

Code: Alles auswählen

from django.template import Context, loader
from django.http import HttpResponse
from django.shortcuts import render_to_response
from django.template.response import TemplateResponse
from Wetterstation.articles.models import Article, Talkback
from django.shortcuts import render
from django.core.context_processors import csrf
from django.shortcuts import render_to_response

def index(request):
    "Create a list of the 5 latest articles"
    latest_articles_list = Article.objects.all().order_by('-pub_date')[:5]
    return render(request, 'articles.html', {'latest_articles_list': latest_articles_list,})
allerdings so wie in der django Doku beschrieben ist funktioniert es nicht

Code: Alles auswählen

from django.core.context_processors import csrf
from django.shortcuts import render_to_response

def my_view(request):
    c = {}
    c.update(csrf(request))
    # ... view code here
    return render_to_response("a_template.html", c)
kann mir jemand sagen wie ich den code oben ergänzen muss?
danke im voraus
Sirius3
User
Beiträge: 18250
Registriert: Sonntag 21. Oktober 2012, 17:20

@erdmulch: Du mußt an Deinem Python-Code gar nichts ändern. Das Problem besteht darin, dass bei
post-Requests zusätzlich der Parameter csrfmiddlewaretoken mit dem Wert von '{{csrf_token}}' übertragen
werden muß (wie es in der Dokumentation ausführlichst beschrieben steht).
Bei Formulardaten wird das einfach mit dem Template-Tag {% csrf_token %} gemacht, bei Ajax
bist Du dafür selbst verantwortlich.
Antworten