Flask Problem mit Static Files

Django, Flask, Bottle, WSGI, CGI…
Antworten
burli
User
Beiträge: 1116
Registriert: Dienstag 9. März 2004, 18:22

Mittwoch 30. Januar 2013, 10:08

Hi, ich bastel gerade wieder mit Flask und hänge an einem Problem, was mir nicht in den Kopf will

Ich verwende im Moment dieses Tutorial, welches ich versuche nachzuvollziehen. Ich habe allerdings Bootstrap schon früher eingebunden als im Tutorial.

Bis Teil 5 habe ich eigentlich keine Probleme. Ab Teil 6 bekomme ich jedoch eine Fehlermeldung, wenn ich versuche, auf Static Files zuzugreifen. Aber auch nicht bei allen. Die Zeile

Code: Alles auswählen

    <link rel="shortcut icon" href="{{ url_for('static', filename='favicon.ico') }}">
wird klaglos angenommen und das Favicon wird angezeigt. Die Zeile

Code: Alles auswählen

    <link href="{{ url_for('static', filename='css/bootstrap.css') }}" rel="stylesheet" media="screen">


produziert aber diesen Fehler
Traceback (most recent call last):
File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1518, in __call__
return self.wsgi_app(environ, start_response)
File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1506, in wsgi_app
response = self.make_response(self.handle_exception(e))
File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1504, in wsgi_app
response = self.full_dispatch_request()
File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1264, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1260, in full_dispatch_request
rv = self.preprocess_request()
File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1387, in preprocess_request
rv = func()
File "/home/burli/flask/microblog2/app/views.py", line 15, in before_request
if g.user.is_authenticated():
File "/usr/local/lib/python2.7/dist-packages/werkzeug/local.py", line 336, in __getattr__
return getattr(self._get_current_object(), name)
File "/usr/local/lib/python2.7/dist-packages/werkzeug/local.py", line 295, in _get_current_object
return self.__local()
File "/usr/local/lib/python2.7/dist-packages/flask_login.py", line 392, in <lambda>
current_user = LocalProxy(lambda: _request_ctx_stack.top.user)
AttributeError: 'RequestContext' object has no attribute 'user'
Der Fehler wird auch erzeugt, wenn ich versuche, im Browser direkt auf das CSS File zuzugreifen. Genauso wenn ich das url_for() weglasse und den Pfad direkt angebe.

Wenn ich das CSS File von einer externen Quelle einbinde funktioniert alles wie es soll.

Code: Alles auswählen

    <link href="http://twitter.github.com/bootstrap/assets/css/bootstrap.css" rel="stylesheet" media="screen">
Stehe da gerade komplett auf dem Schlauch. Ach ja, ich verwende Python 2.7 ohne Virtualenv sondern die normale Systeminstallation
burli
User
Beiträge: 1116
Registriert: Dienstag 9. März 2004, 18:22

Mittwoch 30. Januar 2013, 10:54

Der Vollständigkeit halber: Der Fehler wird in dieser Funktion geworfen

Code: Alles auswählen

@app.before_request
def before_request():
    g.user = current_user
    if g.user.is_authenticated():
        g.user.last_seen = datetime.utcnow()
        db.session.add(g.user)
        db.session.commit()
Aber wie gesagt nur beim Zugriff auf besagte Static Files, nicht im normalen Programmablauf. Und auch nicht beim Favicon
Benutzeravatar
Sr4l
User
Beiträge: 1091
Registriert: Donnerstag 28. Dezember 2006, 20:02
Wohnort: Kassel
Kontaktdaten:

Mittwoch 30. Januar 2013, 19:25

Wo jetzt das Problem genau liegt kann ich dir nicht sagen, aber auch für static files wird @app.before_request ausgeführt.

Scheinbar bekommen diese static files nicht die nötigen Informationen mit geliefert um dann Fehler frei die Authentifizierung zu durchlaufen. Weil eben _request_ctx_stack.top.user nicht vorhanden ist.

Was ist current_user was steck dahinter?

Code: Alles auswählen

def before_request():
    g.user = current_user
burli
User
Beiträge: 1116
Registriert: Dienstag 9. März 2004, 18:22

Donnerstag 31. Januar 2013, 08:42

current_user stammt aus der Flask-Login Extension und liefert das aktuelle User Objekt. Wenn kein User angemeldet ist dann halt einen Anonymen User
Benutzeravatar
Sr4l
User
Beiträge: 1091
Registriert: Donnerstag 28. Dezember 2006, 20:02
Wohnort: Kassel
Kontaktdaten:

Donnerstag 31. Januar 2013, 11:49

burli hat geschrieben:current_user stammt aus der Flask-Login Extension und liefert das aktuelle User Objekt.
Ahhh okay verstehe
burli hat geschrieben:Wenn kein User angemeldet ist dann halt einen Anonymen User
Das tut es scheinbar eben nicht ich denke du hast etwas vergessen.

Beispiel:

Code: Alles auswählen

import flask
import flask_login

app = flask.Flask("lo")
app.secret_key = "123"

@app.route("/test")
def test():
    user = flask_login.current_user
    if not user.is_authenticated():
        return "Nicht angemeldet"
    return "Angemeldet"

app.run(debug=True)
Ergebnis:
127.0.0.1 - - [31/Jan/2013 11:46:23] "GET /test HTTP/1.1" 500 -
Traceback (most recent call last):
...
...
File "C:\Users\Sr4l\Desktop\test.py", line 10, in test
if not user.is_authenticated():
...
...
File "C:\Dev\Python27\lib\site-packages\flask_login.py", line 403, in <lambda>
current_user = LocalProxy(lambda: _request_ctx_stack.top.user)
AttributeError: 'RequestContext' object has no attribute 'user''
Da ich bei diesem Beispiel die LoginExtension nicht in der App regestriert habe, kommt es beim ersten Zugriff auf `current_user` zum Fehler, nicht jedoch bei der Zuweisung.

Beispiel (hoffentlich ohne Fehler):

Code: Alles auswählen

import flask
import flask_login

app = flask.Flask("lo")
app.secret_key = "123"
login_manager = flask_login.LoginManager()
login_manager.setup_app(app)

@app.route("/test")
def test():
    user = flask_login.current_user
    if not user.is_authenticated():
        return "Nicht angemeldet"
    return "Angemeldet"

app.run(debug=True)
Kann es sein das dir der setup_app aufruf fehlt?
burli
User
Beiträge: 1116
Registriert: Dienstag 9. März 2004, 18:22

Donnerstag 31. Januar 2013, 12:43

Sr4l hat geschrieben:Kann es sein das dir der setup_app aufruf fehlt?
Nein, der ist in der __init__.py. Sollte eigentlich als erstes aufgerufen werden.

Wie gesagt, es passiert in dem Tutorial ab Teil 6. Ich werde bei Teil 5 nochmal anfangen und Schritt für Schritt jede Änderung durchgehen, bis der Fehler auftritt.
Antworten