2017-05-11 8 views
1

Einige meiner Ansichten Dekorateure haben, die den Zugang beschränken, etwa so:Wiederverwendung des Dekorateur einer Ansicht aus einer Vorlage

@user_passes_test(my_validation_function) 
def my_restricted_view(request): 
    ... 

Die Sache ist, in meinen Vorlagen würde Ich mag die Links verbergen, für die der Benutzer hat keinen Zugang, gemäß der Logik in my_validation_function.

Ich verstehe, dass eine Möglichkeit, dies zu tun wäre, einen benutzerdefinierten Filter zu definieren, der im Grunde my_validation_function (sagen my_validation_filter), und zeigt/verbirgt den Link entsprechend. Etwas wie folgt aus:

{% if request | my_validation_filter %} 
    <a href="{% url 'my_restricted_view' %}"></a> 
{% endif %} 

Das Problem, das ich hier sehe, ist, dass ich die Validierung zweimal bin Verknüpfung: einmal in der Ansicht, und einmal in der Vorlage. Angenommen, ich viele Ansichten, die jeweils mit unterschiedlichen Validierungslogik hinter ihnen:

@user_passes_test(my_validation_function) 
def my_restricted_view(request): 
    ... 

@user_passes_test(my_other_validation_function) 
def my_other_restricted_view(request): 
    ... 

Dies würde bedeutet, dass, wenn ich die Vorlagen zu schreiben, muss ich vorsichtig sein, immer daran denken, welche Validierungsfunktion, mit welcher Ansicht geht.

Gibt es eine Möglichkeit, eine Funktion zu definieren oder die URL umzukehren, und überprüft dann die Validierungen im Dekorator der Ansicht definiert? Ich denke, so etwas wie diese:

{% if can_access 'my_restricted_view' %} 
    {# this implicitly calls 'my_validation_function' #} 
    ... 
{% endif %} 

{% if can_access 'my_other_restricted_view' %} 
    {# this implicitly calls 'my_other_validation_function' #} 
    ... 
{% endif %} 

Im Grunde, was ich will, ist nur die Validierungslogik in einem Ort für jede Ansicht ändern müssen, und nicht so sehr meine Vorlagen berühren.

Antwort

1

Ihre Frage ist sehr interessant, ich habe keine vollständige Antwort, aber einige Spuren.

Zunächst einmal ist es schwierig, vielleicht unmöglich, den Dekorateur von der verzierten Funktion zu bekommen, inspect zum Beispiel, kann das nicht tun, wie ich weiß. Sie können jedoch die Validierungsfunktion vom Decorator auf die Decorated-Funktion verschieben. Ersetzen Sie diese:

@user_passes_test(my_validation_function) 
def my_restricted_view(request): 
    ... 

durch diese:

@user_passes_test 
def my_restricted_view(request): 
    ... 

my_restricted_view.validation_function = my_validation_function 

Es sollte einfach sein, diese Änderung im Code des Dekorateur zu behandeln.

Dann können Sie einen benutzerdefinierten Filter Sie rufen schreiben:

{% if request|validation_filter:'my_restricted_view' %} 

Der Code dieses Filters könnte wie folgt aussehen:

def validation_filter(request, view_name): 
    view_func = resolve(reverse(view_name)).func 
    validation_func = view_func.validation_function 
    return validation_func(request) 
+0

Dank! Obwohl ich noch keine Möglichkeit gefunden habe, die richtige Validierungsfunktion zu verwenden, führte Ihre Antwort mich in die richtige Richtung. Das Problem ist, dass ich nicht auf die 'validation_function' verweisen kann, die in jeder Ansicht definiert ist, weil Sie auf diese Weise nicht auf Funktionsvariablen zugreifen können. Jedoch , wenn ich es wie folgt definieren: 'my_restricted_view.validation_function = my_validation_function' es * macht * Arbeit. Ich bin immer noch nicht glücklich mit dieser Lösung, weil ich nicht den Namen jeder Funktion jedes Mal zweimal schreiben möchte, also versuche ich, die Variable der Funktion innerhalb des Dekorators zu definieren. –

+0

@Jaime Sanz: Schande über mich, du hast Recht. Ich aktualisiere meine Antwort. – albar

+0

@Jaime Sanz: Vielleicht könnten Sie ein benutzerdefiniertes Template-Tag schreiben, das den Link nur generiert, wenn die Ansicht validiert ist. Etwas, das Sie '{link_if_valid 'my_restricted_view'%}' nennen könnten. – albar

Verwandte Themen