103 votes

Comment configurer un intergiciel personnalisé dans Django ?

J'essaie de créer un middleware pour passer optionnellement un kwarg à chaque vue qui remplit une condition.

Le problème est que je n'arrive pas à trouver un exemple de la façon de configurer l'intergiciel. J'ai vu des classes qui surchargent la méthode que je veux, process_view :

Class CheckConditionMiddleware(object):  
    def process_view(self, request):  

        return None  

Mais où dois-je mettre cette classe ? Dois-je créer une application middleware et placer cette classe à l'intérieur de celle-ci, puis la référencer dans la section settings.middleware ?

169voto

Liarez Points 826

Premier : La structure du chemin

Si vous ne l'avez pas, vous devez créer le fichier intergiciel dans votre application en suivant la structure :

yourproject/yourapp/middleware

Le dossier middleware doit être placé dans le même dossier que settings.py, urls, templates...

Important : N'oubliez pas de créer le init .py vide dans le dossier middleware pour que votre application reconnaisse ce dossier.

Deuxièmement : créer l'intergiciel

Maintenant nous devons créer un fichier pour notre middleware personnalisé, dans cet exemple supposons que nous voulons un middleware qui filtre les utilisateurs en fonction de leur IP, nous créons un fichier appelé filtre_ip_middleware.py à l'intérieur de la intergiciel avec ce code :

class FilterIPMiddleware(object):
    # Check if client IP is allowed
    def process_request(self, request):
        allowed_ips = ['192.168.1.1', '123.123.123.123', etc...] # Authorized ip's
        ip = request.META.get('REMOTE_ADDR') # Get client IP
        if ip not in allowed_ips:
            raise Http403 # If user is not allowed raise Error

       # If IP is allowed we don't do anything
       return None

Troisièmement : Ajouter le middleware dans notre 'settings.py'.

Nous devons chercher :

  • MIDDLEWARE_CLASSES (django < 1.10)
  • MIDDLEWARE (django >= 1.10)

Dans le fichier settings.py, nous devons ajouter notre middleware ( Ajoutez-le dans la dernière position ). Cela devrait ressembler à cela :

MIDDLEWARE = ( #  Before Django 1.10 the setting name was 'MIDDLEWARE_CLASSES'
    'django.middleware.common.CommonMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
     # Above are django standard middlewares

     # Now we add here our custom middleware
     'yourapp.middleware.filter_ip_middleware.FilterIPMiddleware'
)

¡Hecho! Désormais, chaque requête de chaque client appellera votre middleware personnalisé et traitera votre code personnalisé !

14voto

Roald Nefs Points 684

Écrire un intergiciel dans Django>=1.10

Depuis Django 1.10, une classe d'intergiciel doit accepter un fichier get_response dans son __init__() et fournir une __call__() méthode. Bien que cela puisse être réalisé en utilisant la méthode django.utils.deprecation.MiddlewareMixin lors de la définition d'une classe d'intergiciel ( comme indiqué dans le réponse de W.Perrin ), la création d'un intergiciel basé sur des classes dans les versions actuellement prises en charge de Django ressemble à ceci :

class CustomMiddleware(object):
    def __init__(self, get_response):
        """
        One-time configuration and initialisation.
        """
        self.get_response = get_response

    def __call__(self, request):
        """
        Code to be executed for each request before the view (and later
        middleware) are called.
        """
        response = self.get_response(request)
        return response

    def process_view(self, request, view_func, view_args, view_kwargs):
        """
        Called just before Django calls the view.
        """
        return None

    def process_exception(self, request, exception):
        """
        Called when a view raises an exception.
        """
        return None

    def process_template_response(self, request, response):
        """
        Called just after the view has finished executing.
        """
        return response

En process_view() , process_exception() y process_template_response() sont des hooks spéciaux, appelés par Django lors du traitement de l'intergiciel, que vous pouvez définir dans votre classe d'intergiciel. Dans l'exemple ci-dessus, les hooks implémentés ne feront rien de spécial, sauf s'assurer que Django appellera le prochain middleware pour poursuivre le traitement de la réponse/demande.

Activation du middleware

Pour activer le composant intergiciel, ajoutez-le à la section MIDDLEWARE dans les paramètres de Django.

MIDDLEWARE = [
    # Default Django middleware
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',

    # Add your custom middleware
    'path.to.your.middleware.CustomMiddleware',
]

7voto

W.Perrin Points 381

Juste deux étapes. Cela fonctionne pour moi avec django2.1 .

1. créer votre propre classe Middleware.

Il existe une bonne démo du manuel officiel.

https://docs.djangoproject.com/en/2.1/ref/request-response/#django.http.HttpRequest.get_host

    from django.utils.deprecation import MiddlewareMixin

    class MultipleProxyMiddleware(MiddlewareMixin):
        FORWARDED_FOR_FIELDS = [
            'HTTP_X_FORWARDED_FOR',
            'HTTP_X_FORWARDED_HOST',
            'HTTP_X_FORWARDED_SERVER',
        ]

        def process_request(self, request):
            """
            Rewrites the proxy headers so that only the most
            recent proxy is used.
            """
            for field in self.FORWARDED_FOR_FIELDS:
                if field in request.META:
                    if ',' in request.META[field]:
                        parts = request.META[field].split(',')
                        request.META[field] = parts[-1].strip()

Référencer votre classe Middleware dans le fichier MIDDLEWARE liste de votre projet setting.py fichier.

La règle pour la référence Middleware est le chemin vers votre classe à partir du répertoire Root de votre projet.

Par exemple, dans un projet nommé mysite ,l'arbre est le suivant.

 mysite
    manage.py
    mysite
       __init__.py
       middleware.py
       settings.py
       urls.py
       wsgi.py

Nous ajoutons simplement notre classe Middleware MultipleProxyMiddleware dans le middleware.py fichier. Nous obtenons le nom de référence suivant.

MIDDLEWARE = [
    'mysite.middleware.MultipleProxyMiddleware',  
     ...
]

0voto

Boyce Cecil Points 27

Premièrement, l'intergiciel est en fait le pont entre Httprequest et HttpResponse, il est normalement global, parce qu'il est le pont, parce que le HttpRequest doit marcher sur le pont pour atteindre le serveur et marcher sur le pont pour revenir au client avec le HttpResponse. C'est super cool, ce qui signifie que vous pouvez écrire un tas de méthodes à exécuter avant que la requête n'atteigne le serveur, ou après que la requête ait atteint le serveur. Prenons l'exemple du csrfmiddleware, la requête sera d'abord jugée par le middleware pour savoir si la méthode est POST, si c'est le cas, alors le middleware comparera le csrf_token qu'il possède avec le token stocké dans le serveur, ce token est généré lorsque vous envoyez le HTML avec la balise form, car normalement, le client ne peut envoyer une requête POST qu'à travers le formulaire que le serveur envoie directement au client, donc le serveur peut utiliser ce jeton pour juger si ce POST provient du serveur de formulaire qui vous a été envoyé, et combiné avec l'authentification ou l'autorisation, décider d'envoyer la requête au serveur ou juste objecter la requête dans son ensemble. Ainsi, lorsque vous écrivez votre propre middleware, soyez clair sur ce que vous voulez faire avec la requête ou la réponse, do you want to add an element in the response? Like the messagemiddleware did, this new element can be seen as the context django view send or you want to add session, and check the session everytime the client make a request Avec cet état d'esprit, suivez un format fixe, comme dans ce site web. https://medium.com/scalereal/everything-you-need-to-know-about-middleware-in-django-2a3bd3853cd6 .

-2voto

user6061091 Points 17

Il sera utile dans le cas où vous savez quel type d'exception se produit dans les vues. A partir de ce qui précède, j'ai créé ma propre classe personnalisée comme suit

from .models import userDetails

class customMiddleware(object):

    def process_request(self,request):
        result=''
        users = userDetails.objects.all()
        print '-->',users ,'---From middleware calling ---'

        username=request.POST.get("username")
        salary = request.POST.get("salary")
        if salary:
            try:
                result = username+int(salary)
            except:
                print "Can't add"

Il sera exécuté lorsque l'exception se produit dans le cas de l'addition de chaînes de caractères et d'entiers.

Vous pouvez écrire des vues correspondantes pour la classe middleware ci-dessus.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X