Hallo,
ich stehe vor folgendem, Problem:
- ich habe eine Aktion, zB kann man etwas kaufen, auf der Hauptseite ("/index/") ist ein Formular mit Menge etc.
- dieses Formular wird an "/buy/" ge-"postet"
- dieses Formular wird dann serverseitig auf Gültigkeit überprüft etc.
- nun soll bei Fehlermeldung etc. eine Statusmeldung erscheinen - diese sollten aber dann wieder unter "/index/" erscheinen
- dafür benötige ich ja normal ein redirect, nur wie kann ich hier die Statusmeldungen übergeben...?
Irgendwie ein relativ simples Problem, komme aber irgendwie nicht auf eine schön einfache Lösung. Wie würdet ihr das machen?
Danke![/list]
Grundsätzliches zu einer Webapp
Am einfachsten währe es wohl dir eine Art Wrapper namens `flash` zu schreiben, dieser fügt bei Aufruf an deine Session im Request ein neues Objekt `flash_messages` (type list) hinzu, oder erweitert diese. In einer Template Engine kannst du dann über Kontext-Modifikatoren diese Flash-Messages ins Template einbauen.
Einfaches Beispiel:
Das Beispiel setzt vorraus das du mit werkzeug.contrib.sessions arbeitest, sollte aber leicht auf andere Systeme adaptierbar sein.
Grüße, Christopher.
Einfaches Beispiel:
Code: Alles auswählen
def flash(message, success=None, classifier=None, session=None):
"""
Flash a message (can contain XHTML). If ``success`` is True, the flashbar
will be green, if it's False, it will be red and if it's undefined it will
be yellow. If a classifier is given it can be used to unflash all
messages with that classifier.
"""
if session is None:
session = getattr(current_request, 'session', None)
if session is None:
return False
if not 'flmsg' in session:
session['flmsg'] = [(message, success, classifier)]
else:
session['flmsg'].append((message, success, classifier))
session.modified = True
return True
Grüße, Christopher.
Rails nennt dies eine "flash message" und nutzt dafür ein Cookie und eine Sessions, damit sich die Index-Seite nach dem Redirect daran erinnert, dass da noch etwas anzuzeigen war. Die Nachricht überlebt genau einen Redirect und wird dann automatisch entfernt.
Vielleicht hilft dir http://python-rum.org/wiki/WebFlash Auf JavaScript zu vertrauen finde ich jedoch nicht so gut und würde lieber eine Session auf dem Server benutzen.
Stefan
Vielleicht hilft dir http://python-rum.org/wiki/WebFlash Auf JavaScript zu vertrauen finde ich jedoch nicht so gut und würde lieber eine Session auf dem Server benutzen.
Stefan
So, habe nun versucht das ganze mit Cookies zu lösen...
Wenn man nun die Statusnachrichten ansieht, summieren sich diese mit der Zeit immer weiter an... Ich finde das höchst merkwürdig, da muss es sich ja theoretisch immer um das gleiche Response Objekt handeln.
Ich kann den Fehler nicht entdecken... Wo liegt das Problem?
Vielen Dank!
Wenn man nun die Statusnachrichten ansieht, summieren sich diese mit der Zeit immer weiter an... Ich finde das höchst merkwürdig, da muss es sich ja theoretisch immer um das gleiche Response Objekt handeln.
Ich kann den Fehler nicht entdecken... Wo liegt das Problem?
Vielen Dank!
Zuletzt geändert von nemomuk am Dienstag 28. April 2009, 21:44, insgesamt 1-mal geändert.
Was erwartest du denn, wenn du "msg" als Klassenattribut von "Response" definierst? Natürlich "summieren" sich die Nachrichten auf, weil jeder Zugriff auf "msg" das Klassenattribut trifft, so gesehen handelt es sich auch immer um "das gleiche Response-Objekt".
Nebenbei bemerkt gibt es "werkzeug.redirect", außerdem wirft deine Anwendung an diversen Stellen "NameError".
Das du an diversen Stellen das Rad neu erfindest, kommt noch hinzu ... Werkzeug ist ohne Zweifel eine tolle Bibliothek, aber wenn ich mir deinen Code anschaue, kann ich nicht umhin zu glauben, dass du mit einem vernünftigen Framework besser bedient wärst ...
Nebenbei bemerkt gibt es "werkzeug.redirect", außerdem wirft deine Anwendung an diversen Stellen "NameError".
Das du an diversen Stellen das Rad neu erfindest, kommt noch hinzu ... Werkzeug ist ohne Zweifel eine tolle Bibliothek, aber wenn ich mir deinen Code anschaue, kann ich nicht umhin zu glauben, dass du mit einem vernünftigen Framework besser bedient wärst ...
upps... das war die alte Version,... aber trotzdem zugegeben: das ist ziemlich umständlich, was ich da fabriziert habe. Ich hatte mich da immer weiter in ein Konzept reingefrickelt, was nicht wirklich Sinn machte (was dann letztendlich darin geendet hat, dass ich mir sogar eine eigene redirect Funktion schreiben musste) - mache das Ganze nun über ein "Local"-Objekt.
Was hättest du sonst noch anders gemacht?
Was hättest du sonst noch anders gemacht?
Zuletzt geändert von nemomuk am Mittwoch 29. April 2009, 05:21, insgesamt 1-mal geändert.
Alles, was mir aufgefallen ist:
- Wofür benötigst du den Dateinamen des View-Moduls als kontextlokales Attribut?
- Warum unterscheidest du zwischen "prev_msg" und "msg"? Wenn du dem Nutzer etwas zu sagen hast, kannst du das auch gleich tun, anstatt Nachrichten immer über mindestens einen Request zu verschleppen.
- Du speicherst Nachrichten im HTML-Format im Cookie? Mal abgesehen davon, dass "<br />" dir den knappen Cookie-Speicherplatz stiehlt, ist das unsinnig, weil du vielleicht mal in die Verlegenheit kommen könntest, die Daten anderweitig anzuzeigen. Da wäre ein anderes Trennzeichen sinnvoller, das Template sollte dann eine Liste mit allen Nachrichten erhalten und selbst entscheiden, wie sie angezeigt werden sollten. Vergiss nicht, für die Darstellung ist das Template verantwortlich und nicht der Controller oder die Applikation.
- property funktioniert auch als Dekorator, die explizite Definition von "get_msg" ist daher überflüssig.
- Was hat PROJECT_NAME im Endpoint zu suchen? Das lässt darauf schließen, dass du nicht so ganz verstanden hast, wie Deployment funktionieren sollte.
- Wieso erzeugst du die URL_MAP nicht gleich in urls.py? Es ist ziemlich unsinnig, eine konstante Datenstruktur in eine andere konstante Datenstruktur zu überführen, du kannst auch einfach gleich alles bei der Initialisierung von URL_MAP angeben.
- Was haben die Einstellungen (settings.py) im Anwendungspaket zu suchen?
- Wieso erzeugst du in "render_template()" für jedes Template-Rendering ein separates Environment?! Du solltest ein Template-Environment global erzeugen, und "msg" in "**context" verschieben!
- render_msg() ist überflüssig, siehe oben
- Authentifizierung (und Authorisierung) ala "login_required()" solltest du nicht selbst bauen, dieses Rad wurde schon oft erfunden. Nimm Authkit, Barrel, repoze.what oder whatever ...
- In "login" fehlt jegliche Input Validierung. Benutzereingaben, selbst wenn sie nur aus Benutzername und Passwort bestehen, ist nie zu trauen, und sie müssen immer validiert werden.
Ich bedanke mich für deine ausführliche Schilderung! Vllt. hast du recht und ich versuche mir da selbst etwas zu basteln, was eigentlich nicht wirklich notwendig ist. Auf der anderen Seite ist mir Django zu aufgeblasen, mir wäre etwas "schlankeres" lieber...
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
Inwiefern aufgeblasen? Inwiefern stört das?
(Django ist ja immerhin kein J2EE)
Ansonsten kannst du dir ja Glashammer ansehen, wenn du bei Werkzeug bleiben willst.
Und wo ist dein Code von dem lunar spricht?
(Django ist ja immerhin kein J2EE)
Ansonsten kannst du dir ja Glashammer ansehen, wenn du bei Werkzeug bleiben willst.
Und wo ist dein Code von dem lunar spricht?
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
- gerold
- Python-Forum Veteran
- Beiträge: 5555
- Registriert: Samstag 28. Februar 2004, 22:04
- Wohnort: Oberhofen im Inntal (Tirol)
- Kontaktdaten:
Hallo SchneiderWeisse!SchneiderWeisse hat geschrieben:Auf der anderen Seite ist mir Django zu aufgeblasen, mir wäre etwas "schlankeres" lieber...
Dann versuche es doch mal einen Tag lang mit CherryPy. Das ist nicht aufgeblasen und trotzdem nimmt es dir viel Arbeit ab.
Zur Datenweitergabe kannst du alle Techniken einsetzen die du möchtest. Aber Sessions sind sicherlich die einfachste Möglichkeit dafür -- auch mit CherryPy.
mfg
Gerold
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Ich finde Django übrigens gar nicht aufgeblasen. Alles, was man braucht, um loszulegen:
1. `django_admin.py startproject prjct; cd prjct; chmod +x manage.py; ./manage.py startapp blog` ausführen.
2. Folgendes an `settings.py` anfügen (bzw. die passenden Eigenschaften ändern):
3. `mkdir templates static` zum Anlegen der Verzeichnisse ausführen.
4. In `urls.py` das Admin-UI aktivieren und `/static` binden:
5. Modell in `blog/models.py` definieren:
6. Admin-Formular in `blog/admin.py` (was blöderweise nicht mit angelegt wird) definieren:
7. Mit `manage.py sycndb` Datenbank anlegen und mit `manage.py runserver` das System starten.
8. Zu <http://localhost:8000/admin> gehen, und einen Blog-Eintrag anlegen.
9. Startseite für den Blog in `urls.py` als `(r^$, 'blog.views.index')` vereinbaren. Dann die View-Funktion schreiben:
10. Template erstellen, auf <http://localhost:8000/> und fertig.
Sollte ich Django anpassen dürfen, würde ich dafür sorgen, dass `startproject` und `startapp` diese Vorgaben gleich machen, sodass man sie nicht extra alle aufschreiben muss, sondern später dann nur auskommentieren muss. Ein bisschen mehr scaffolding a la Rails wäre nicht verkehrt. In jedem Fall sollte IMHO das Admin-UI, standardmäßig aktiviert sein.
Stefan
1. `django_admin.py startproject prjct; cd prjct; chmod +x manage.py; ./manage.py startapp blog` ausführen.
2. Folgendes an `settings.py` anfügen (bzw. die passenden Eigenschaften ändern):
Code: Alles auswählen
DATABASE_ENGINE = 'sqlite3'
DATABASE_NAME = 'prjct.db'
TEMPLATE_DIRS = ('templates',)
INSTALLED_APPS += ('django.contrib.admin', 'prjct.blog',)
MEDIA_ROOT = 'static/'
MEDIA_URL = '/static'
4. In `urls.py` das Admin-UI aktivieren und `/static` binden:
Code: Alles auswählen
from django.conf import settings
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
(r'^admin/', include(admin.site.urls)),
(r'^static/(.*)', 'django.views.static.serve', {'document_root': settings.MEDIA_ROOT})
)
Code: Alles auswählen
class Post(models.Model):
title = models.CharField(max_length=200)
text = models.TextField()
pub_date = models.DateTimeField(default=datetime.now)
class Meta:
ordering = ['-pub_date']
Code: Alles auswählen
from django.contrib import admin
from models import Post
admin.site.register(Post)
8. Zu <http://localhost:8000/admin> gehen, und einen Blog-Eintrag anlegen.
9. Startseite für den Blog in `urls.py` als `(r^$, 'blog.views.index')` vereinbaren. Dann die View-Funktion schreiben:
Code: Alles auswählen
from django.shortcuts import render_to_response
from models import Post
def index(request):
return render_to_response("blog/index.html", {'posts': Post.objects.all()[:10]})
Sollte ich Django anpassen dürfen, würde ich dafür sorgen, dass `startproject` und `startapp` diese Vorgaben gleich machen, sodass man sie nicht extra alle aufschreiben muss, sondern später dann nur auskommentieren muss. Ein bisschen mehr scaffolding a la Rails wäre nicht verkehrt. In jedem Fall sollte IMHO das Admin-UI, standardmäßig aktiviert sein.
Stefan
- gerold
- Python-Forum Veteran
- Beiträge: 5555
- Registriert: Samstag 28. Februar 2004, 22:04
- Wohnort: Oberhofen im Inntal (Tirol)
- Kontaktdaten:
Hallo!gerold hat geschrieben:Zur Datenweitergabe kannst du alle Techniken einsetzen die du möchtest. Aber Sessions sind sicherlich die einfachste Möglichkeit dafür -- auch mit CherryPy.
Hier findest du ein kleines Beispiel, wie man so etwas mit CherryPy machen kann:
http://paste.pocoo.org/show/114935/
EDIT: Das Beispiel sieht nur so groß aus, weil ich die Vorlagentexte ebenfalls mit in das Beispiel aufgenommen habe. Normalerweise legt man diese Vorlagentexte in eingenen Dateien ab.
mfg
Gerold
Zuletzt geändert von gerold am Mittwoch 29. April 2009, 12:44, insgesamt 1-mal geändert.
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Wenn jetzt schon wieder jeder sein Lieblingsframework in den Raum wirft, kann ich auch gleich Pylons erwähnen. Das hat bereits was fertiges für Flash Messages
Django aber wäre für ihn wohl das beste, immerhin versucht er es ja nachzuprogrammieren.
Django aber wäre für ihn wohl das beste, immerhin versucht er es ja nachzuprogrammieren.
- gerold
- Python-Forum Veteran
- Beiträge: 5555
- Registriert: Samstag 28. Februar 2004, 22:04
- Wohnort: Oberhofen im Inntal (Tirol)
- Kontaktdaten:
Hallo lunar!lunar hat geschrieben:Django aber wäre für ihn wohl das beste, immerhin versucht er es ja nachzuprogrammieren.
Warum denkst du, dass jemand mit diesen simplen Anforderungen
Django nachprogrammieren möchte?SchneiderWeisse hat geschrieben:- ich habe eine Aktion, zB kann man etwas kaufen, auf der Hauptseite ("/index/") ist ein Formular mit Menge etc.
- dieses Formular wird an "/buy/" ge-"postet"
- dieses Formular wird dann serverseitig auf Gültigkeit überprüft etc.
- nun soll bei Fehlermeldung etc. eine Statusmeldung erscheinen - diese sollten aber dann wieder unter "/index/" erscheinen
- dafür benötige ich ja normal ein redirect, nur wie kann ich hier die Statusmeldungen übergeben...?
Das ist doch etwas, was mit jedem, auch noch so kleinen, Framework gemacht werden kann. Man braucht nur eine passende Strategie und etwas Erfahrung dafür. Wie einfach das mit CherryPy ist, habe ich im obigen Beispiel aufgezeigt. Und ich kann mir nicht vorstellen, dass es mit Werkzeug viel komplizierter ist.
mfg
Gerold
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
Offensichtlich weil seine Implementation einen sehr Django-ähnlichen Aufbau hatte. Meine letztze Werkzeug-Applikation hatte auch einen ähnlichen aufbau zu Django, weil das System durchaus brauchbar ist.gerold hat geschrieben:Warum denkst du, dass jemand mit diesen simplen AnforderungenDjango nachprogrammieren möchte?SchneiderWeisse hat geschrieben:- ich habe eine Aktion, zB kann man etwas kaufen, auf der Hauptseite ("/index/") ist ein Formular mit Menge etc.
- dieses Formular wird an "/buy/" ge-"postet"
- dieses Formular wird dann serverseitig auf Gültigkeit überprüft etc.
- nun soll bei Fehlermeldung etc. eine Statusmeldung erscheinen - diese sollten aber dann wieder unter "/index/" erscheinen
- dafür benötige ich ja normal ein redirect, nur wie kann ich hier die Statusmeldungen übergeben...?
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
- gerold
- Python-Forum Veteran
- Beiträge: 5555
- Registriert: Samstag 28. Februar 2004, 22:04
- Wohnort: Oberhofen im Inntal (Tirol)
- Kontaktdaten:
Hallo Leonidas!Leonidas hat geschrieben:Offensichtlich weil seine Implementation einen sehr Django-ähnlichen Aufbau hatte. Meine letztze Werkzeug-Applikation hatte auch einen ähnlichen aufbau zu Django, weil das System durchaus brauchbar ist.
Ich verstehe. Nur leider wurden die Links zur Anwendung gelöscht. So kann ich mir nicht ansehen, welchen Ansatz er verwendet hat.
lg
Gerold
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Ich habe seinen Code gelesen.gerold hat geschrieben:Warum denkst du, dass jemand mit diesen simplen Anforderungen [...]lunar hat geschrieben:Django aber wäre für ihn wohl das beste, immerhin versucht er es ja nachzuprogrammieren.
Django nachprogrammieren möchte?
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
Ja, das habe ich auch angemäkelt. Finde sowas ziemlich daneben, weil nun so die Diskussion etwas im Raum hängt und unvollständig ist.gerold hat geschrieben:Ich verstehe. Nur leider wurden die Links zur Anwendung gelöscht. So kann ich mir nicht ansehen, welchen Ansatz er verwendet hat.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
hatte, es nur raus, da ich die Dateien nicht ewig auf dem Server rumgammeln lassen will... ich werde sie aber wieder reinstellen:
Habe mir inzwischen Django angesehen und musste festellen, dass der Aufbau eigentlich so ziemlich der gleiche ist...
Naja, dann werde ich mich mal durch den Urwald der vorhandenen Frameworks kämpfen...
@lunar: die umständliche Cookie Variante habe ich nur gewählt, damit ich auch nach einem "redirect" Statusnachrichten anzeigen kann, was so ja nicht möglich war. Das "url_dict" finde ich so schöner, als wenn man jedes mal das Rule(...) schreiben muss. Und den Einwand, dass man property auch als decorator verwenden kann, verstehe ich nicht... Man muss es ja nicht unbedingt so verwenden oder hat das einen speziellen Vorteil als decorator?
Habe mir inzwischen Django angesehen und musste festellen, dass der Aufbau eigentlich so ziemlich der gleiche ist...
Naja, dann werde ich mich mal durch den Urwald der vorhandenen Frameworks kämpfen...
@lunar: die umständliche Cookie Variante habe ich nur gewählt, damit ich auch nach einem "redirect" Statusnachrichten anzeigen kann, was so ja nicht möglich war. Das "url_dict" finde ich so schöner, als wenn man jedes mal das Rule(...) schreiben muss. Und den Einwand, dass man property auch als decorator verwenden kann, verstehe ich nicht... Man muss es ja nicht unbedingt so verwenden oder hat das einen speziellen Vorteil als decorator?
Zuletzt geändert von nemomuk am Donnerstag 30. April 2009, 16:45, insgesamt 1-mal geändert.