Как вернуть сообщение об ошибке в декораторе в Django? - PullRequest
0 голосов
/ 01 марта 2020

Я написал свой собственный декоратор, который проверяет, является ли зарегистрированный в данный момент пользователь учителем. Если нет, то декоратор перенаправляет пользователя на страницу входа, но для пользователя это немного сбивает с толку, поэтому я хочу передать сообщение, почему пользователь был перенаправлен на страницу входа, но я не знаю, как это сделать.

# here is my decorator:
def teacher_required(function=None, redirect_field_name=REDIRECT_FIELD_NAME, login_url='login'):
    '''
    Decorator for views that checks that the logged in user is a teacher,
    redirects to the log-in page if necessary.
    '''
    actual_decorator = user_passes_test(
        lambda u: u.is_active and u.is_teacher,
        login_url=login_url,
        redirect_field_name=redirect_field_name
    )
    if function:
        return actual_decorator(function)
    return actual_decorator

Ответы [ 3 ]

0 голосов
/ 02 марта 2020

Django поставляется со встроенной структурой сообщений. https://docs.djangoproject.com/en/3.0/ref/contrib/messages/

Для использования, если необходимо выполнить следующие действия:

Убедитесь, что в установленных приложениях в вашем файле settings.py добавлено django сообщений.

INSTALLED_APPS = [
    ...

    'django.contrib.messages',

    ...
]

Сконфигурируйте хранилище сообщений, добавив следующую строку в ваши настройки. * и затем, если вы используете bootstrap, вы можете отобразить изменения в своем шаблоне следующим образом:

{% if messages %}
    {% for message in messages %}
    <div class="alert alert-warning">
    {{ message }}
    </div>
    {% endfor %}
{% endif %}

документацию для bootstrap предупреждений можно найти здесь: https://getbootstrap.com/docs/4.0/components/alerts/

0 голосов
/ 02 марта 2020

Вы можете использовать встроенные сообщения из Django с пользовательским декоратором.

Для этого Django обеспечивает полную поддержку повара ie - и сеанса - на основе обмена сообщениями, как для анонимных, так и для аутентифицированных пользователей.

В вашем случае, примером может быть следующий:

decorators.py

# Import Django messages
from django.contrib import messages

# Custom Decorator
def teacher_required(function):
    def _function(request, *args, **kwargs):
        if not request.user.is_teacher:
            messages.info(request, 'Custom message to user')
            return HttpResponseRedirect(reverse('app:url_name'))
        return function(request, *args, **kwargs)

    return _function

views.py

from django.utils.decorators import method_decorator
from django.contrib.auth.decorators import login_required
from foo.decorators import teacher_required

@method_decorator([login_required, teacher_required], name='dispatch')
class MyView(TemplateView):
    template_name = 'template.html'

В этом случае вам нужно вызвать декоратора с помощью @method_decorator() и сначала передать login_required, чтобы убедиться, что пользователь вошел в систему, прежде чем проверять, является ли он учителем.

Если вы хотите реализовать более элегантную систему, я нашел пример на github .

0 голосов
/ 02 марта 2020

Декоратор - это функция, которая принимает в качестве входных данных функцию (или класс) для декорирования и вносит в нее некоторые изменения. Я бы go выбрал вариант с двумя методами, в котором, если первый метод является истинным, тогда он настоящий учитель, в противном случае это не так, и в таком случае он дает правильный результат.

def teacher_required(function=None, redirect_field_name=REDIRECT_FIELD_NAME, login_url='login'):
    '''
    Decorator for views that checks that the logged in user is a teacher,
    redirects to the log-in page if necessary.
    '''
    actual_decorator = user_passes_test(
        lambda u: u.is_active and u.is_teacher,
        login_url=login_url,
        redirect_field_name=redirect_field_name
    )

Мы можем просто использовать случай для декоратора user_passes_test

from django.contrib.auth.decorators import user_passes_test

def teacher_required(function=None):
    def is_teacher(u):
        return Shopkeeper.objects.filter(user=u).exists()
    actual_decorator = user_passes_test(is_teacher)
    if function:
        return actual_decorator(function)
    else:
        return actual_decorator

Вы можете, например, реализовать его как:

@login_required
@teacher_required
def teacher_view(request):
    # ...
    pass

@login_required
def not_teacher_view(request):
    # ...
    pass

Надеюсь, вы поняли идею, для ясности смотрите это

...