2011-11-19 18 views
8

Chciałbym stworzyć dekorator dla Flask trasach do flagi niektórych trasach jako publiczne, więc mogę robić rzeczy tak:Tworzenie dekorator Kolba url publicznego

@public 
@app.route('/welcome') 
def welcome(): 
    return render_template('/welcome.html') 

indziej, oto co mi myślenia dekorator i check wyglądałby następująco:

_public_urls = set() 

def public(route_function): 
    # add route_function's url to _public_urls 
    # _public_urls.add(route_function ...?.url_rule) 
    def decorator(f): 
     return f 

def requested_url_is_public(): 
    from flask import request 
    return request.url_rule in _public_urls 

wtedy, gdy wniosek został złożony, mam funkcję kontekstowe, które sprawdza requested_url_is_public.

Jestem nieco zakłopotany, ponieważ nie wiem, jak uzyskać regułę url dla danej funkcji w dekoratorze public.

Być może nie jest to najlepszy wybór dla Flask, ale spodziewam się, że jest inny elegancki sposób, aby to osiągnąć.

Widziałem już takie wzory w przeszłości i chciałbym je naśladować. Na przykład jest to odpowiednik dekoratora Django login_required.

Chciałbym czytać myśli na ten temat.

Odpowiedz

5

Kolba ma już dekorator login_required (patrz view decorators). Jeśli używasz public_urls do decydowania, które adresy wymagają autoryzacji, najprawdopodobniej lepiej będzie z nich skorzystać.

+0

Magic! Pozdrawiam za to. –

+1

Ups - Właśnie zdałem sobie sprawę, że tak blisko, jak to jest to, czego chcę, nie jestem całkiem pewien, że jest to odpowiedź, której potrzebuję. Mam około 4 publicznych adresów URL i ponad 100 prywatnych. Nie chcę zanieczyszczać kodu w/'login_required', więc chciałbym mieć np.' Before_request', który zaprzecza wszystkim publicznym żądaniom, chyba że w widoku jest '@ public'. Mam nadzieję, że widzisz, dlaczego to nie jest odpowiednia odpowiedź, ale to, co napisałeś, to z pewnością świetny trop. Jeśli wymyślę odpowiedź, zaznaczę to poprawnie i opowiem, co zrobiłem. Twoje zdrowie. –

1

skończyło się robi coś takiego:

def public(endpoint): 
    """A decorator for endpoints that flags them as publicly accessible 

    The endpoint is the Flask endpoint function. This is later tested by the 
    _is_public function, which is called before every request. 

    Note that @public must come AFTER route.add i.e. 
    @app.route('...') 
    @public 
    def handler(): ... 
    """ 
    @wraps(endpoint) 
    def public_endpoint(*args, **kwargs): 
     return endpoint(*args, **kwargs) 
    public_endpoint._is_public = True 
    return public_endpoint 

i

def _is_public(endpoint): 
    """Return true if the given endpoint function is public 

    Tests whether the @public decorator has been applied to the url. 
    """ 
    return getattr(endpoint, '_is_public', False) is True 


@blueprint.before_app_request # or @app.before_request 
def security_check(): 
    """Check all incoming requests for a current user. 
    """ 
    if current_user.is_logged_in: # need current_user test elsewhere 
     # we don't need to check if we have a public url if the user is 
     # logged in 
     return 

    try: 
     if _is_public(current_app.view_functions[request.endpoint]): 
      # we just go perform the endpoint function if it is public 
      return 
    except KeyError: 
     # There is no endpoint matching the request 
     abort(404) 

    # user is not logged in and it's not a public url 
    logging.info("No current user and %s is not public" % request.path[1:]) 

    # send the user to the welcome page 
    return redirect(url_for("some_public_page"))