Partager via


Procédure pas à pas : Application web API Bing Ads dans Python

Ce tutoriel explique comment commencer à exécuter une application web Microsoft Advertising à l’aide du Kit de développement logiciel (SDK) Python Bing Ads, de l’IDE Visual Studio Code et de l’infrastructure web Django .

Ce tutoriel n’explore pas différents détails sur Django lui-même, tels que l’utilisation de modèles de données et la création d’une interface d’administration. Pour obtenir des conseils sur ces aspects, reportez-vous à la documentation django. Pour plus d’informations sur l’utilisation de Django dans le terminal, l’éditeur et le débogueur VS Code, consultez Utiliser Django dans Visual Studio Code. Ce didacticiel s’appuie largement sur les instructions d’installation fournies dans Utiliser Django dans Visual Studio Code.

Vue d’ensemble de l’exemple d’application web

À la fin de ce tutoriel, vous disposez d’une application web qui s’exécute sur http://localhost qui authentifie vos informations d’identification utilisateur Microsoft Advertising et affiche vos informations d’utilisateur et de comptes. Vous pouvez ensuite ajouter plusieurs utilisateurs de l’application web, qui peuvent permettre à votre application d’utiliser leurs informations d’identification Microsoft Advertising. Cette application web fournit un mappage un-à-un d’un utilisateur d’application web, par exemple ContosoUser à un utilisateur Microsoft Advertising. Pour plus d’informations sur la modification du modèle de données, consultez la documentation django pour plus d’informations. Si l’utilisateur de votre application web autorise l’accès à son compte Microsoft Advertising avec un compte Microsoft, un jeton d’actualisation est stocké dans la base de données SQL Lite sur votre serveur web.

Conditions préalables

Visual Studio Code doit être installé pour suivre ce didacticiel. Pour exécuter l’application web Django, vous pouvez utiliser Visual Studio Community ou Visual Studio Professional. Toutefois, les étapes de configuration varient de celles de ce didacticiel.

Python 3 doit être installé à partir de python.org ; utilisez généralement le bouton Télécharger Python 3.7.0 qui apparaît en premier sur la page (ou quelle que soit la dernière version). Sur Windows, vérifiez que l’emplacement de votre interpréteur Python est inclus dans votre variable d’environnement PATH. Vous pouvez case activée cela en exécutant path à l’invite de commandes. Si le dossier de l’interpréteur Python n’est pas inclus, ouvrez Paramètres Windows, recherchez « environnement », sélectionnez Modifier les variables d’environnement pour votre compte, puis modifiez la variable Path pour inclure ce dossier.

Vous devez installer le Kit de développement logiciel (SDK) Python Bing Ads, et ce tutoriel vous guidera tout au long de l’installation.

Vous aurez besoin de l’infrastructure web Django installée pour déployer l’application localement, et ce tutoriel vous guidera tout au long de l’installation.

Vous aurez besoin d’au moins un utilisateur disposant d’informations d’identification Microsoft Advertising et d’un jeton de développeur.

Vous devez inscrire une application et prendre note de l’ID client (ID d’application inscrit) et de la clé secrète client (mot de passe inscrit). Vous devez inscrire une application web (non native) pour cet exemple. Vous serez invité à inscrire une ou plusieurs URL de redirection, et pour ce didacticiel, vous devez inscrire http://localhost/callback. Vous devez plutôt utiliser https lors du déploiement sur un serveur de production. Pour plus d’informations sur l’inscription d’une application et le flux d’octroi du code d’autorisation, consultez Authentification avec OAuth.

Ce tutoriel a été développé sur Windows. Bien que Windows ne soit pas nécessaire pour exécuter l’exemple, certaines des étapes ci-dessous varient si vous utilisez un autre système d’exploitation, par exemple, Linux ou MacOS.

Créer un environnement de projet pour Django

Dans cette section, vous créez un environnement virtuel dans lequel Django est installé. L’utilisation d’un environnement virtuel évite d’installer Django dans un environnement Python global et vous donne un contrôle exact sur les bibliothèques utilisées dans une application.

  1. Sur votre système de fichiers, créez un dossier de projet pour ce didacticiel, par hello_djangoexemple .

  2. Dans le hello_django dossier, ouvrez PowerShell ou votre interpréteur de commandes de script favori et utilisez la commande suivante pour créer un environnement virtuel nommé env en fonction de votre interpréteur actuel :

    py -3 -m venv env
    
  3. Ouvrez le dossier du hello_django projet dans VS Code en exécutant code .ou en exécutant VS Code et en utilisant la commande Fichier>Ouvrir le dossier .

    Ouvrir VS Code

  4. Dans VS Code, ouvrez la palette de commandes (Palette de commandes d’affichage> ouCtrl+Shift+P). Sélectionnez ensuite la commande Python : Sélectionner l’interpréteur .

  5. La commande présente une liste des interpréteurs disponibles que VS Code peut localiser automatiquement. Votre liste varie ; Si vous ne voyez pas l’interpréteur souhaité, consultez Configuration des environnements Python. Dans la liste, sélectionnez l’environnement virtuel dans votre dossier de projet qui commence par ./env ou .\env:

    Sélection de l’environnement virtuel pour Python

  6. Exécutez Terminal : Nouveau terminal (Ctrl+Shift+ ` ) à partir de la palette de commandes, qui crée un terminal et active automatiquement l’environnement virtuel en exécutant son script d’activation.

    Remarque

    Sur Windows, si votre type de terminal par défaut est PowerShell, vous pouvez voir une erreur indiquant qu’il ne peut pas s’exécuter activate.ps1 car l’exécution de scripts est désactivée sur le système. L’erreur doit fournir un lien pour obtenir des informations sur l’autorisation des scripts. Sinon, utilisez Terminal : sélectionnez Interpréteur de commandes par défaut pour définir la valeur par défaut de votre choix.

    L’environnement sélectionné apparaît dans le coin inférieur gauche de la barre de status VS Code. Notez l’indicateur (venv) qui vous indique que vous utilisez un environnement virtuel :

    Environnement sélectionné s’affichant dans la barre de status VS Code

  7. Installez Django dans l’environnement virtuel via pip dans le terminal VS Code :

    python -m pip install django
    
  8. Installez le Kit de développement logiciel (SDK) Python Bing Ads dans l’environnement virtuel via pip dans le terminal VS Code :

    python -m pip install bingads
    

Vous disposez maintenant d’un environnement virtuel autonome prêt à écrire du code Django et Microsoft Advertising.

Créer et exécuter une application Django

Dans la terminologie Django, un « projet Django » est composé de plusieurs fichiers de configuration au niveau du site, ainsi que d’une ou plusieurs « applications » que vous déployez sur un hôte web pour créer une application web complète. Un projet Django peut contenir plusieurs applications, chacune ayant généralement une fonction indépendante dans le projet, et la même application peut se trouver dans plusieurs projets Django. Une application, pour sa part, est simplement un package Python qui suit certaines conventions attendues par Django.

Pour créer une application Django, vous devez d’abord créer le projet Django pour servir de conteneur pour l’application, puis créer l’application elle-même. À ces deux fins, vous utilisez l’utilitaire d’administration Django, django-admin, qui est installé lorsque vous installez le package Django.

Créer le projet Django

  1. Dans le terminal VS Code où votre environnement virtuel est activé, exécutez la commande suivante :

    django-admin startproject web_project .
    

    Cette startproject commande suppose (à l’aide de . à la fin) que le dossier actif est votre dossier de projet, et crée les éléments suivants dans celui-ci :

    • manage.py: utilitaire d’administration en ligne de commande Django pour le projet. Vous exécutez des commandes d’administration pour le projet à l’aide de python manage.py <command> [options].

    • Un sous-dossier nommé web_project, qui contient les fichiers suivants :

      • __init__.py: fichier vide qui indique à Python que ce dossier est un package Python.
      • wsgi.py: point d’entrée pour les serveurs web compatibles WSGI pour servir votre projet. En règle générale, vous laissez ce fichier tel qu’il fournit les hooks pour les serveurs web de production.
      • settings.py: contient les paramètres du projet Django, que vous modifiez au cours du développement d’une application web.
      • urls.py: contient une table des matières du projet Django, que vous modifiez également au cours du développement.

      Projet web Django

  2. Pour vérifier le projet Django, vérifiez que votre environnement virtuel est activé, puis démarrez le serveur de développement de Django à l’aide de la commande python manage.py runserver. Le serveur s’exécute sur le port par défaut 8000, et vous voyez une sortie semblable à celle-ci dans la fenêtre de sortie du terminal VS Code :

    Performing system checks...
    
    System check identified no issues (0 silenced).
    
    You have 15 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
    Run 'python manage.py migrate' to apply them.
    October 18, 2018 - 05:38:23
    Django version 2.1.2, using settings 'web_project.settings'
    Starting development server at http://127.0.0.1:8000/
    Quit the server with CTRL-BREAK.
    

    Lorsque vous exécutez le serveur la première fois, il crée une base de données SQLite par défaut dans le fichier db.sqlite3, qui est généralement destinée au développement, mais qui peut être utilisée en production pour les applications web de faible volume. En outre, le serveur web intégré de Django est destiné uniquement à des fins de développement local. Toutefois, lorsque vous effectuez un déploiement sur un hôte web, Django utilise le serveur web de l’hôte à la place. Le wsgi.py module du projet Django se charge du raccordement aux serveurs de production.

    Si vous souhaitez utiliser un port différent du port 8000 par défaut, spécifiez simplement le numéro de port sur la ligne de commande, par python manage.py runserver 5000exemple .

  3. Ctrl+click URL http://127.0.0.1:8000/ dans la fenêtre de sortie du terminal VS Code pour ouvrir votre navigateur par défaut à cette adresse. Si Django est installé correctement et que le projet est valide, vous voyez la page par défaut ci-dessous. La fenêtre Sortie de VS Code affiche également le journal du serveur.

    Affichage par défaut du projet Django vide

  4. Lorsque vous avez terminé, fermez la fenêtre du navigateur et arrêtez le serveur dans VS Code en utilisant Ctrl+C comme indiqué dans la fenêtre de sortie du terminal VS Code.

Créer une application Django pour Microsoft Advertising

  1. Dans le terminal VS Code avec votre environnement virtuel activé, exécutez la commande de l’utilitaire d’administration dans le dossier de startapp votre projet (où manage.py réside) :

    python manage.py startapp app
    

    La commande crée un dossier appelé app qui contient un certain nombre de fichiers de code et un sous-dossier. Parmi ceux-ci, vous travaillez fréquemment avec views.py (qui contient les fonctions qui définissent les pages dans votre application web) et models.py (qui contient des classes définissant vos objets de données). Le migrations dossier est utilisé par l’utilitaire d’administration de Django pour gérer les versions de base de données, comme décrit plus loin dans ce tutoriel. Il existe également les fichiers apps.py (configuration de l’application), admin.py (pour la création d’une interface d’administration) et tests.py (pour les tests unitaires), qui ne sont pas abordés ici.

  2. Dans app/settings.py , ajoutez le code suivant et définissez vos propres valeurs CLIENT_ID, CLIENT_SECRET, DEVELOPER_TOKEN et ENVIRONNEMENT .

    """
    Bing Ads API settings
    Edit with your credentials.
    """
    
    REDIRECTION_URI = "http://localhost:8000/callback"
    CLIENT_ID = "ClientIdGoesHere" # Your registered App ID
    CLIENT_SECRET="ClientSecretGoesHere" # Your registered App Password
    DEVELOPER_TOKEN = "DeveloperTokenGoesHere" # Your production developer token
    ENVIRONMENT = 'production'
    API_VERSION=13
    
  3. Dans app/settings.py , ajoutez app à la liste des applications installées.

        INSTALLED_APPS = [
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        'app',
    ]
    
  4. Dans le terminal VS Code, créez les app/static/app dossiers et app/templates/app :

    (env) PS C:\dev\hello_django> mkdir app/static/app
    (env) PS C:\dev\hello_django> mkdir app/templates/app 
    
  5. Dans les app/static/app dossiers, créez un fichier nommé site.css et ajoutez le contenu suivant.

    .message {
        font-weight: 600;
        color: blue;
    }
    
    .message_list th,td {
        text-align: left;
        padding-right: 15px;
    }
    
    .navbar {
        background-color: lightslategray;
        font-size: 1em;
        font-family: 'Trebuchet MS', 'Lucida Sans Unicode', 'Lucida Grande', 'Lucida Sans', Arial, sans-serif;
        color: white;
        padding: 8px 5px 8px 5px;
    }
    
    .navbar a {
        text-decoration: none;
        color: inherit;
    }
    
    .navbar-brand {
        font-size: 1.2em;
        font-weight: 600;
    }
    
    .navbar-item {
        font-variant: small-caps;
        margin-left: 30px;
    }
    
    .body-content {
        padding: 5px;
        font-family:'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
    }
    
    input[name=message] {
        width: 80%;
    }
    
  6. Dans le app/templates/app dossier, créez un fichier, index.html avec le contenu ci-dessous.

    {% extends "app/layout.html" %}
    {% block content %}
    {% if errors %}
    <div class="jumbotron">
        <section id="errors">
            <h1>Errors occurred in your last request to Bing Ads API.</h1>
            <table class="message_list">
                <tr>
                    <th>Code</th>
                    <th>ErrorCode</th>
                    <th>Message</th>
                </tr>
                {% for error in errors %}
                <tr>
                    <td>{{ error.Code }}</td> 
                    <td>{{ error.ErrorCode }}</td> 
                    <td>{{ error.Message }}</td> 
                </tr>
                {% endfor %}
            </table> 
        </section>
    </div>
    {% endif %}
    {% if user.is_authenticated  %}
    {% if bingadsuser  %}
    <div class="jumbotron">
        <section id="enabled">
            <h1>Your credentials have access to Microsoft Advertising.</h1>
            <table class="message_list">
                <tr>
                    <th>Id</th>
                    <th>UserName</th>
                    <th>First Name</th>
                    <th>Last Name</th>
                </tr>
                <tr>
                    <td>{{ bingadsuser.Id }}</td> 
                    <td>{{ bingadsuser.UserName }}</td> 
                    <td>{{ bingadsuser.Name.FirstName }}</td> 
                    <td>{{ bingadsuser.Name.LastName }}</td> 
                </tr>
            </table>  
        </section>
    </div>
    <div class="jumbotron">
        <section id="revoke">
            <p class="lead">Click here to revoke access for this app to your Microsoft Advertising accounts. You will then be able to login with a different Microsoft Advertising user. </p>
            <form id="revokeForm" action="/revoke" method="post" class="navbar-left">
                {% csrf_token %}
                <p><a href="javascript:document.getElementById('revokeForm').submit()" class="btn btn-primary btn-large">Delete Refresh Token</a></p>
            </form>
        </section>
    </div>
    <div class="jumbotron">
        <section id="accounts">        
            <h1>Account Details</h1>
            <table class="message_list">
                <thead>
                <tr>
                    <th>Id</th>
                    <th>Name</th> 
                </tr>
                </thead>
                <tbody>
                {% for account in accounts %}
                <tr>
                    <td>{{ account.Id }}</td>
                    <td>{{ account.Name }}</td> 
                </tr>
                {% endfor %}
                </tbody>
            </table> 
        </section>
    </div>
    {% else  %}
    <div class="jumbotron">
        <section id="enable">
            <h1>Enable Microsoft Advertising Access</h1>
            <p class="lead">
                You are logged into the Django web application, but not yet signed in with your Microsoft Advertising credentials. 
                You can sign in with Microsoft Advertising credentials below.
            </p>
        </section>
    </div>
    <div>
        <div class="col-md-6">
            <section id="socialLoginForm">
                <h1>Microsoft Account Login</h1>
                <p class="lead">
                    Click here to authenticate your Microsoft Account. 
                    If you don't have Microsoft Advertising credentials, you can go to the 
                    <a href="https://ads.microsoft.com/customer/Signup.aspx">Microsoft Advertising Sign Up</a> page.
                </p>
                <p><a href="/callback" class="btn btn-primary btn-large">Authenticate Microsoft Account &raquo;</a></p>
            </section>
        </div>    
    </div>
    {% endif %}
    {% else %}
    <div class="jumbotron">
        <div class="col-md-6">
            <section id="socialLoginForm">
                <h1>Microsoft Advertising Example Web Application</h1>
                <p class="lead">
                    Before you can provide your Microsoft Advertising user credentials and access Microsoft Advertising data, 
                    you must <a href="{% url 'login' %}">login</a> to the Django web application.
                </p>
                <p class="lead">Use your site's Django admin portal to add web app users.</p>
                <p><a href="/admin" class="btn btn-primary btn-large">Django Admin &raquo;</a></p>
            </section>
        </div>    
    </div>
    {% endif %}
    <div>
        <div class="col-md-4">
            <h2>Get Started Using Python with Bing Ads API</h2>
            <p>The Bing Ads Python Software Development Kit (SDK) simplifies workflows such as OAuth authentication and report file parsing.</p>
            <p><a class="btn btn-default" href="https://learn.microsoft.com/advertising/guides/get-started-python">Learn more &raquo;</a></p>
        </div>
        <div class="col-md-4">
            <h2>Django</h2>
            <p>Django is a free web framework for building Web sites and Web applications using HTML, CSS and JavaScript.</p>
            <p><a class="btn btn-default" href="https://www.djangoproject.com/">Learn more &raquo;</a></p>
        </div>
        <div class="col-md-4">
            <h2>Microsoft Azure</h2>
            <p>You can publish your web app to Microsoft Azure. Find out how you can host your application with a free trial today.</p>
            <p><a class="btn btn-default" href="https://azure.microsoft.com">Learn more &raquo;</a></p>
        </div>
    </div>
    {% endblock %}
    {% block scripts %}
    {% load static %}
    <link rel="stylesheet" type="text/css" href="{% static 'app/site.css' %}"/>
    {% endblock %}
    
  7. Dans le app/templates/app dossier, créez un fichier, layout.html avec le contenu ci-dessous.

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>{{ title }} - My Django Application</title>
        {% load static %}
        <link rel="stylesheet" type="text/css" href="{% static 'app/site.css' %}"/>
        <script src="{% static 'app/scripts/modernizr-2.6.2.js' %}"></script>
    </head>
    <body>
        <div class="navbar navbar-inverse navbar-fixed-top">
            <div class="container">
                <div class="navbar-header">
                    <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
                        <span class="icon-bar"></span>
                        <span class="icon-bar"></span>
                        <span class="icon-bar"></span>
                    </button>
                    <a href="/" class="navbar-brand">Microsoft Advertising App via Django</a>
                </div>
                <div class="navbar-collapse collapse">
                    <ul class="nav navbar-nav">
                        <li><a href="{% url 'home' %}">Home</a></li>
                    </ul>
                    {% include 'app/loginpartial.html' %}
                </div>
            </div>
        </div>
        <div class="container body-content">
    {% block content %}{% endblock %}
            <hr/>
            <footer>
                <p>&copy; {{ year }} - My Django Application</p>
            </footer>
        </div>
    {% block scripts %}{% endblock %}
    </body>
    </html>
    
  8. Dans le app/templates/app dossier, créez un fichier, login.html avec le contenu ci-dessous.

    {% extends "app/layout.html" %}
    {% block content %}
    <h2>{{ title }}</h2>
    <div class="row">
        <div class="col-md-8">
            <section id="loginForm">
                <form action="." method="post" class="form-horizontal">
                    {% csrf_token %}
                    <h4>Use a local account to log in.</h4>
                    <hr />
                    <div class="form-group">
                        <label for="id_username" class="col-md-2 control-label">User name</label>
                        <div class="col-md-10">
                            {{ form.username }}
                        </div>
                    </div>
                    <div class="form-group">
                        <label for="id_password" class="col-md-2 control-label">Password</label>
                        <div class="col-md-10">
                            {{ form.password }}
                        </div>
                    </div>
                    <div class="form-group">
                        <div class="col-md-offset-2 col-md-10">
                            <input type="hidden" name="next" value="/" />
                            <input type="submit" value="Log in" class="btn btn-default" />
                        </div>
                    </div>
                    {% if form.errors %}
                    <p class="validation-summary-errors">Please enter a correct user name and password.</p>
                    {% endif %}
                </form>
            </section>
        </div>
    </div>
    {% endblock %}
    {% block scripts %}
    {% load static %}
    <link rel="stylesheet" type="text/css" href="{% static 'app/site.css' %}"/>
    {% endblock %}
    
  9. Dans le app/templates/app dossier, créez un fichier, loginpartial.html avec le contenu ci-dessous.

    {% if user.is_authenticated  %}
    <form id="logoutForm" action="/applogout" method="post" class="navbar-right">
        {% csrf_token %}
        <ul class="nav navbar-nav navbar-right">
            <li><span class="navbar-brand">Hello {{ user.username }}!</span></li>
            <li><a href="javascript:document.getElementById('logoutForm').submit()">Log off</a></li>
        </ul>
    </form>
    {% else %}
    <ul class="nav navbar-nav navbar-right">
        <li><a href="{% url 'login' %}">Log in</a></li>
    </ul>
    {% endif %}
    
  10. Dans le app dossier, créez un fichier, forms.py avec le contenu ci-dessous.

    from django import forms
    from django.contrib.auth.forms import AuthenticationForm
    from django.utils.translation import ugettext_lazy as _
    
    class BootstrapAuthenticationForm(AuthenticationForm):
        """Authentication form which uses boostrap CSS."""
        username = forms.CharField(max_length=254,
                                   widget=forms.TextInput({
                                       'class': 'form-control',
                                       'placeholder': 'User name'}))
        password = forms.CharField(label=_("Password"),
                                   widget=forms.PasswordInput({
                                       'class': 'form-control',
                                       'placeholder':'Password'}))
    
  11. Modifiez app/models.py pour qu’il corresponde au code suivant.

    from django.db import models
    from django.contrib.auth.models import User
    
    # In this web app a Microsoft Advertising user maps a Django web user to a refresh token.
    
    class BingAdsUser(models.Model):
        user = models.OneToOneField(User, on_delete=models.PROTECT)
        refresh_token = models.CharField(max_length=200)
    
        # def __unicode__(self):              # __unicode__ on Python 2
        #     return self.refresh_token
        def __str__(self):              # __str__ on Python 3
            return self.refresh_token
    
  12. Modifiez app/views.py pour qu’il corresponde au code suivant.

    from django.http import HttpRequest, HttpResponse
    from django.shortcuts import render
    from django.template.loader import get_template, render_to_string
    from web_project import settings
    from datetime import datetime
    from django.shortcuts import redirect
    from django.contrib.auth import authenticate, login, logout, get_user_model
    from django.contrib.auth.models import User
    from app.models import BingAdsUser
    from bingads import *
    
    # import logging
    # logging.basicConfig(level=logging.INFO)
    # logging.getLogger('suds.client').setLevel(logging.DEBUG)
    # logging.getLogger('suds.transport').setLevel(logging.DEBUG)
    
    authorization_data = AuthorizationData(
        account_id=None, 
        customer_id=None, 
        developer_token=None, 
        authentication=None)
    
    customer_service=None
    
    def home(request):
        """
        If an authenticated user returns to this page after logging in, the appropriate 
        context is provided to index.html for rendering the page. 
        """
        assert isinstance(request, HttpRequest)
    
        # If the Django user has a refresh token stored, 
        # try to use it to get Microsoft Advertising data.
        if user_has_refresh_token(request.user.username):
            return redirect('/callback')
        else:
            return render(
                request,
                'app/index.html'
            )
    
    def callback(request):
        """Handles OAuth authorization, either via callback or direct refresh request."""
        assert isinstance(request, HttpRequest)
    
        authentication = OAuthWebAuthCodeGrant(
            client_id=settings.CLIENT_ID,
            client_secret=settings.CLIENT_SECRET, 
            redirection_uri=settings.REDIRECTION_URI,
            env=settings.ENVIRONMENT)
    
        return authorize_bing_ads_user(request, authentication)
    
    def authorize_bing_ads_user(request, authentication):
        assert isinstance(request, HttpRequest)
    
        global customer_service
        bingadsuser = None
    
        try:
            Users = get_user_model()
            user = User.objects.get(username=request.user.username)
        except User.DoesNotExist:
            return render(
                request,
                'app/index.html'
            )
    
        try:
            bingadsuser = user.bingadsuser
        except BingAdsUser.DoesNotExist:
            bingadsuser = BingAdsUser()
            bingadsuser.user = user
            pass
    
        try:
            # If we have a refresh token let's refresh the access token.
            if(bingadsuser is not None and bingadsuser.refresh_token != ""):
                authentication.request_oauth_tokens_by_refresh_token(bingadsuser.refresh_token)
                bingadsuser.refresh_token = authentication.oauth_tokens.refresh_token
    
            # If the current HTTP request is a callback from the Microsoft Account authorization server,
            # use the current request url containing authorization code to request new access and refresh tokens.
            elif (request.GET.get('code') is not None):
                authentication.request_oauth_tokens_by_response_uri(response_uri = request.get_full_path()) 
                bingadsuser.refresh_token = authentication.oauth_tokens.refresh_token
        except OAuthTokenRequestException:
            bingadsuser.refresh_token = ""  
    
        user.save()
        bingadsuser.save()
    
        # If there is no refresh token saved and no callback from the authorization server, 
        # then connect to the authorization server and request user consent.
        if (bingadsuser.refresh_token == ""):
            return redirect(authentication.get_authorization_endpoint())
    
        set_session_data(request, authentication)
    
        # At this point even if the user has valid Django web application credentials, 
        # we don't know whether they have access to Microsoft Advertising.
        # Let's test to see if they can call Bing Ads API service operations. 
    
        bing_ads_user = None
        accounts=[]
        errors=[]
    
        try:
            bing_ads_user = get_user(None)
            accounts = search_accounts_by_user_id(bing_ads_user.Id)['AdvertiserAccount']
        except WebFault as ex:
            errors=get_webfault_errors(ex)
            pass
    
        context = {
            'bingadsuser': bing_ads_user,
            'accounts': accounts,
            'errors': errors,
        }
        return render(
            request,
            'app/index.html',
            context
        )
    
    def revoke(request):
        """Deletes the refresh token for the user authenticated in the current session."""
        assert isinstance(request, HttpRequest)
    
        try:
            Users = get_user_model()
            user = User.objects.get(username=request.user.username)
            bingadsuser = user.bingadsuser
            if(bingadsuser is not None):
                bingadsuser.refresh_token = ""
                bingadsuser.save()
        except User.DoesNotExist:
            pass
        except BingAdsUser.DoesNotExist:
            pass
    
        clear_session_data(request)
    
        return render(
            request,
            'app/index.html'
        )
    
    def user_has_active_session(request):
        try:
            return True if request.session['is_authenticated'] else False 
        except KeyError:
            return False
    
    def user_has_refresh_token(username):
        try:
            Users = get_user_model()
            user = User.objects.get(username=username)
            bingadsuser = user.bingadsuser
            if(bingadsuser is not None and bingadsuser.refresh_token != ""):
                return True
        except User.DoesNotExist:
            return False
        except BingAdsUser.DoesNotExist:
            return False
    
    def set_session_data(request, authentication):
        global authorization_data
        global customer_service
    
        try:
            request.session['is_authenticated'] = True
    
            authorization_data.authentication = authentication
            authorization_data.developer_token = settings.DEVELOPER_TOKEN
    
            customer_service = ServiceClient(
                service='CustomerManagementService', 
                version=settings.API_VERSION,
                authorization_data=authorization_data,
                environment=settings.ENVIRONMENT
            )
    
        except KeyError:
            pass
        return None   
    
    def clear_session_data(request):
        global authorization_data
        global customer_service
    
        request.session['is_authenticated'] = False
    
        authorization_data = AuthorizationData(account_id=None, customer_id=None, developer_token=None, authentication=None)
        customer_service = None
    
    def applogout(request):
        logout(request)
        clear_session_data(request)
        return redirect('/')
    
    def get_user(user_id):
        ''' 
        Gets a Microsoft Advertising User object by the specified user ID.
    
        :param user_id: The Microsoft Advertising user identifier.
        :type user_id: long
        :return: The Microsoft Advertising user.
        :rtype: User
        '''
        global customer_service
    
        return customer_service.GetUser(UserId = user_id).User
    
    def search_accounts_by_user_id(user_id):
        ''' 
        Search for account details by UserId.
    
        :param user_id: The Microsoft Advertising user identifier.
        :type user_id: long
        :return: List of accounts that the user can manage.
        :rtype: Dictionary of AdvertiserAccount
        '''
    
        predicates={
            'Predicate': [
                {
                    'Field': 'UserId',
                    'Operator': 'Equals',
                    'Value': user_id,
                },
            ]
        }
    
        accounts=[]
    
        page_index = 0
        PAGE_SIZE=100
        found_last_page = False
    
        while (not found_last_page):
            paging=set_elements_to_none(customer_service.factory.create('ns5:Paging'))
            paging.Index=page_index
            paging.Size=PAGE_SIZE
            search_accounts_response = customer_service.SearchAccounts(
                PageInfo=paging,
                Predicates=predicates
            )
    
            if search_accounts_response is not None and hasattr(search_accounts_response, 'AdvertiserAccount'):
                accounts.extend(search_accounts_response['AdvertiserAccount'])
                found_last_page = PAGE_SIZE > len(search_accounts_response['AdvertiserAccount'])
                page_index += 1
            else:
                found_last_page=True
    
        return {
            'AdvertiserAccount': accounts
        }
    
    def set_elements_to_none(suds_object):
        for (element) in suds_object:
            suds_object.__setitem__(element[0], None)
        return suds_object
    
    def get_webfault_errors(ex):
        errors=[]
    
        if not hasattr(ex.fault, "detail"):
            raise Exception("Unknown WebFault")
    
        error_attribute_sets = (
            ["ApiFault", "OperationErrors", "OperationError"],
            ["AdApiFaultDetail", "Errors", "AdApiError"],
            ["ApiFaultDetail", "BatchErrors", "BatchError"],
            ["ApiFaultDetail", "OperationErrors", "OperationError"],
            ["EditorialApiFaultDetail", "BatchErrors", "BatchError"],
            ["EditorialApiFaultDetail", "EditorialErrors", "EditorialError"],
            ["EditorialApiFaultDetail", "OperationErrors", "OperationError"],
        )
    
        for error_attribute_set in error_attribute_sets:
            errors = get_api_errors(ex.fault.detail, error_attribute_set)
            if errors is not None:
                return errors
    
        return None
    
    def get_api_errors(error_detail, error_attribute_set):
        api_errors = error_detail
        for field in error_attribute_set:
            api_errors = getattr(api_errors, field, None)
        if api_errors is None:
            return None
    
        errors=[]
        if type(api_errors) == list:
            for api_error in api_errors:
                errors.append(api_error)
        else:
            errors.append(api_errors)
        return errors
    
  13. Remplacez le contenu de web_project/urls.py par le contenu ci-dessous. Le urls.py fichier est l’endroit où vous spécifiez des modèles pour acheminer différentes URL vers leurs vues appropriées. Par exemple, le code ci-dessous mappe l’URL racine de l’application ("") à la home fonction que vous venez d’ajouter à app/views.py:

    from django.contrib import admin
    from django.urls import path
    from app import views as app_views
    from django.contrib.auth import views as auth_views
    from datetime import datetime
    from django.conf.urls import include, url
    from app.forms import BootstrapAuthenticationForm
    from django.contrib.auth.views import HttpResponseRedirect
    
    from django.contrib import admin
    admin.autodiscover()
    
    urlpatterns = [
        url(r'^applogout', app_views.applogout, name='applogout'),
        url(r'^callback', app_views.callback, name='callback'),
        url(r'^revoke', app_views.revoke, name='revoke'),
        url(r'^$', app_views.home, name='home'),
        url(r'^login/$',
            auth_views.LoginView.as_view(
                template_name='app/login.html', 
                authentication_form=BootstrapAuthenticationForm,
                extra_context= {
                    'title':'Log in',
                    'year':datetime.now().year,
                }
            ),
            name='login'),
        url(r'^logout$',
            auth_views.LogoutView.as_view(),
            {
                'next_page': '/',
            },
            name='logout'),
    
        url(r'^admin/', admin.site.urls),
    ]
    
  14. Enregistrez tous les fichiers modifiés avec Ctrl+K S.

  15. Exécutez python manage.py makemigrations pour générer des scripts dans le dossier migrations qui migrent la base de données de son état actuel vers le nouvel état.

  16. Exécutez python manage.py migrate pour appliquer les scripts à la base de données réelle. Les scripts de migration enregistrent efficacement toutes les modifications incrémentielles que vous apportez à vos modèles de données (models.py) au fil du temps. En appliquant les migrations, Django met à jour la base de données pour qu’elle corresponde à vos modèles. Étant donné que chaque modification incrémentielle a son propre script, Django peut migrer automatiquement toute version précédente d’une base de données (y compris une nouvelle base de données) vers la version actuelle. Par conséquent, vous devez vous préoccuper uniquement de vos modèles dans models.py, jamais avec le schéma de base de données sous-jacent ou les scripts de migration. Tu laisses Django faire cette partie !

  17. Créez un compte de superutilisateur dans l’application en ouvrant un terminal dans VS Code pour votre environnement virtuel, puis en exécutant la commande python manage.py createsuperuser --username=<username> --email=<email>, en <username> remplaçant et <email>, bien sûr, par vos informations personnelles. Lorsque vous exécutez la commande, Django vous invite à entrer et à confirmer votre mot de passe.

    Importante

    Veillez à mémoriser votre combinaison de nom d’utilisateur et de mot de passe. Il s’agit des informations d’identification que vous utilisez pour vous authentifier dans le portail d’administration de l’application web.

  18. Dans le terminal VS Code, à nouveau avec l’environnement virtuel activé, exécutez le serveur de développement avec python manage.py runserver et ouvrez un navigateur pour http://127.0.0.1:8000/ afficher une page qui affiche « Hello, Django ».

  19. Dans le navigateur web, accédez à http://127.0.0.1:8000/admin/ et créez un utilisateur web Django sous Utilisateurs. Cela est distinct de vos informations d’identification utilisateur Microsoft Advertising, afin que plusieurs utilisateurs de Microsoft Advertising puissent se connecter à votre application séparément.

    Django Administration

  20. Connectez-vous avec le nouvel utilisateur (et non le super administrateur) et vous devez voir l’option permettant de vous authentifier avec un compte Microsoft.

    Authentifier le compte Microsoft

  21. Après avoir cliqué sur Authentifier le compte Microsoft , vous êtes invité à accorder à votre propre application web des autorisations pour gérer vos comptes Microsoft Advertising. Si vous y consentez et si vous avez accès à des comptes Microsoft Advertising, vous devez être redirigé vers une vue de vos noms et ID de compte.

Voir aussi

Prise en main de Python avec l’API Bing Ads