Exemplarische Vorgehensweise: Bing Ads API-Webanwendung in Python

In diesem Lernprogramm erfahren Sie, wie Sie mit dem Bing Ads Python SDK, der Visual Studio Code-IDE und dem Django-Webframework eine Microsoft Advertising-Webanwendung ausführen.

In diesem Tutorial werden verschiedene Details über Django selbst nicht behandelt, z. B. die Arbeit mit Datenmodellen und das Erstellen einer administrativen Schnittstelle. Anleitungen zu diesen Aspekten finden Sie in der Django-Dokumentation. Weitere Informationen zum Arbeiten mit Django im VS Code-Terminal, -Editor und -Debugger finden Sie unter Verwenden von Django in Visual Studio Code. Dieses Tutorial lehnt sich stark an die Setupanweisungen unter Verwenden von Django in Visual Studio Code an.

Beispiel für eine Webanwendung Übersicht

Am Ende dieses Lernprogramms wird eine Webanwendung ausgeführt http://localhost , die Ihre Microsoft Advertising-Benutzeranmeldeinformationen authentifiziert und Ihre Benutzer- und Kontoinformationen anzeigt. Sie können dann mehrere Webanwendungsbenutzer hinzufügen, die den Zugriff für Ihre Anwendung auf die Verwendung ihrer Microsoft Advertising-Anmeldeinformationen aktivieren können. Diese Webanwendung bietet eine Eins-zu-Eins-Zuordnung eines Webanwendungsbenutzers, z. B. ContosoUser, zu einem Microsoft Advertising-Benutzer. Weitere Informationen zum Ändern des Datenmodells finden Sie in der Django-Dokumentation . Wenn Ihr Webanwendungsbenutzer den Zugriff auf seine Microsoft Advertising-Konten mit einem Microsoft-Konto aktiviert, wird ein Aktualisierungstoken in der SQL Lite-Datenbank auf Ihrem Webserver gespeichert.

Voraussetzungen

Du musst Visual Studio Code installiert haben, um diesem Tutorial folgen zu können. Zum Ausführen der Django-Web-App können Sie Visual Studio Community oder Visual Studio Professional verwenden; die Setupschritte unterscheiden sich jedoch von denen in diesem Tutorial.

Sie müssen Python 3 von python.org installiert haben; Verwenden Sie in der Regel die Schaltfläche "Python 3.7.0 herunterladen ", die zuerst auf der Seite angezeigt wird (oder was auch immer die neueste Version ist). Stellen Sie unter Windows sicher, dass der Speicherort Ihres Python-Interpreters in Ihrer PATH-Umgebungsvariablen enthalten ist. Sie können dies überprüfen, indem Sie es an der Eingabeaufforderung ausführen path . Wenn der Ordner des Python-Interpreters nicht enthalten ist, öffnen Sie die Windows-Einstellungen, suchen Sie nach "Umgebung", wählen Sie Umgebungsvariablen für Ihr Konto bearbeiten aus, und bearbeiten Sie dann die Pfadvariable so, dass dieser Ordner enthalten ist.

Sie müssen das Bing Ads Python SDKinstallieren. In diesem Tutorial werden Sie durch die Installation geführt.

Für die lokale Bereitstellung der Anwendung muss das Django-Webframework installiert sein. In diesem Tutorial werden Sie durch die Installation geführt.

Sie benötigen mindestens einen Benutzer mit Microsoft Advertising-Anmeldeinformationen und einem Entwicklertoken.

Sie müssen eine Anwendung registrieren und sich die Client-ID (registrierte Anwendungs-ID) und den geheimen Clientschlüssel (registriertes Kennwort) notieren. Für dieses Beispiel müssen Sie eine (nicht native) Web-App registrieren. Sie werden aufgefordert, eine oder mehrere Weiterleitungs-URLs zu registrieren, und für dieses Tutorial sollten Sie sich registrieren http://localhost/callback. Stattdessen sollten Sie bei der Bereitstellung auf einem Produktionsserver HTTPS verwenden. Weitere Informationen zum Registrieren einer Anwendung und zum Autorisierungscodegewährungsfluss finden Sie unter Authentifizierung mit OAuth.

Dieses Tutorial wurde unter Windows entwickelt. Obwohl Windows zum Ausführen des Beispiels nicht erforderlich ist, variieren einige der folgenden Schritte, wenn Sie ein anderes Betriebssystem verwenden, z. B. Linux oder MacOS.

Erstellen einer Projektumgebung für Django

In diesem Abschnitt erstellen Sie eine virtuelle Umgebung, in der Django installiert ist. Die Verwendung einer virtuellen Umgebung vermeidet die Installation von Django in einer globalen Python-Umgebung und gibt Ihnen eine genaue Kontrolle über die in einer Anwendung verwendeten Bibliotheken.

  1. Erstellen Sie in Ihrem Dateisystem einen Projektordner für dieses Tutorial, z. B hello_django.

  2. Öffnen Sie im hello_django Ordner PowerShell oder Ihre bevorzugte Skriptshell, und verwenden Sie den folgenden Befehl, um eine virtuelle Umgebung mit dem Namen env basierend auf Ihrem aktuellen Interpreter zu erstellen:

    py -3 -m venv env
    
  3. Öffnen Sie den hello_django Projektordner in VS Code, indem code .Sie ausführen, oder indem Sie VS Code ausführen und den> Befehl "Ordner öffnen" verwenden.

    Open VS Code

  4. Öffnen Sie in VS Code die Befehlspalette (Befehlspalette anzeigen> oder ).Ctrl+Shift+P Wählen Sie dann den Befehl Python: Select Interpreter aus .

  5. Der Befehl zeigt eine Liste verfügbarer Interpreter an, die VS Code automatisch finden kann. Ihre Liste wird variieren; Wenn der gewünschte Interpreter nicht angezeigt wird, lesen Sie Konfigurieren von Python-Umgebungen. Wählen Sie aus der Liste die virtuelle Umgebung in Ihrem Projektordner aus, die mit ./env oder .\envbeginnt:

    Auswahl der virtuellen Umgebung für Python

  6. Führen Sie Terminal: Neues Terminal (Ctrl+Shift+ ` ) aus der Befehlspalette aus, das ein Terminal erstellt und die virtuelle Umgebung automatisch aktiviert, indem das Aktivierungsskript ausgeführt wird.

    Hinweis

    Wenn Ihr Standardterminaltyp unter Windows PowerShell ist, wird möglicherweise ein Fehler angezeigt, dass die Ausführung nicht möglich ist activate.ps1 da das Ausführen von Skripts auf dem System deaktiviert ist. Der Fehler sollte einen Link mit Informationen zum Zulassen von Skripts enthalten. Verwenden Sie andernfalls Terminal: Wählen Sie Standardshell aus, um Ihren bevorzugten Standardwert festzulegen.

    Die ausgewählte Umgebung wird in der unteren linken Ecke der VS Code status-Leiste angezeigt. Beachten Sie den Indikator (venv), der Ihnen mitteilt, dass Sie eine virtuelle Umgebung verwenden:

    Ausgewählte Umgebung wird in der VS Code-Statusleiste angezeigt

  7. Installieren Sie Django in der virtuellen Umgebung über pip im VS Code Terminal:

    python -m pip install django
    
  8. Installieren Sie das Bing Ads Python SDK in der virtuellen Umgebung über pip im VS Code Terminal:

    python -m pip install bingads
    

Sie verfügen jetzt über eine eigenständige virtuelle Umgebung, die zum Schreiben von Django- und Microsoft Advertising-Code bereit ist.

Erstellen und Ausführen einer Django-App

In der Django-Terminologie besteht ein "Django-Projekt" aus mehreren Konfigurationsdateien auf Site-Ebene sowie einer oder mehreren "Apps", die Sie auf einem Webhost bereitstellen, um eine vollständige Webanwendung zu erstellen. Ein Django-Projekt kann mehrere Apps enthalten, von denen jede in der Regel eine unabhängige Funktion im Projekt hat, und dieselbe App kann sich in mehreren Django-Projekten befinden. Eine App ihrerseits ist nur ein Python-Paket, das bestimmten Konventionen folgt, die Django erwartet.

Um eine Django-App zu erstellen, ist es daher erforderlich, zuerst das Django-Projekt zu erstellen, das als Container für die App dienen soll, und dann die App selbst zu erstellen. Für beide Zwecke verwenden Sie das Verwaltungsprogramm Django, django-admindas bei der Installation des Django-Pakets installiert wird.

Erstellen des Django-Projekts

  1. Führen Sie im VS Code-Terminal, in dem Ihre virtuelle Umgebung aktiviert ist, den folgenden Befehl aus:

    django-admin startproject web_project .
    

    Dieser startproject Befehl setzt (durch Verwendung von . am Ende) voraus, dass der aktuelle Ordner Ihr Projektordner ist, und erstellt darin Folgendes:

    • manage.py: Das Django-Befehlszeilenverwaltungshilfsprogramm für das Projekt. Sie führen administrative Befehle für das Projekt mit python manage.py <command> [options]aus.

    • Ein Unterordner mit dem Namen web_project, der die folgenden Dateien enthält:

      • __init__.py: eine leere Datei, die Python mitteilt, dass es sich bei diesem Ordner um ein Python-Paket handelt.
      • wsgi.py: ein Einstiegspunkt für WSGI-kompatible Webserver zur Unterstützung Ihres Projekts. In der Regel lassen Sie diese Datei unverändert, da sie die Hooks für Produktionswebserver bereitstellt.
      • settings.py: enthält Einstellungen für das Django-Projekt, die Sie im Zuge der Entwicklung einer Web-App ändern.
      • urls.py: enthält ein Inhaltsverzeichnis für das Django-Projekt, das Sie im Laufe der Entwicklung auch ändern.

      Django Web Project

  2. Um das Django-Projekt zu überprüfen, stellen Sie sicher, dass Ihre virtuelle Umgebung aktiviert ist, und starten Sie dann den Entwicklungsserver von Django mit dem Befehl python manage.py runserver. Der Server wird auf dem Standardport 8000 ausgeführt, und im Ausgabefenster des VS Code-Terminals wird eine Ausgabe wie die folgende angezeigt:

    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.
    

    Wenn Sie den Server zum ersten Mal ausführen, wird in der Datei db.sqlite3eine SQLite-Standarddatenbank erstellt, die im Allgemeinen für Entwicklungszwecke vorgesehen ist, aber in der Produktion für Web-Apps mit geringem Volumen verwendet werden kann. Außerdem ist der integrierte Webserver von Django nur für lokale Entwicklungszwecke gedacht. Wenn Sie jedoch auf einem Webhost bereitstellen, verwendet Django stattdessen den Webserver des Hosts. Das wsgi.py Modul im Django-Projekt kümmert sich um die Einbindung in die Produktionsserver.

    Wenn Sie einen anderen Port als den Standardport 8000 verwenden möchten, geben Sie einfach die Portnummer in der Befehlszeile an, z. B python manage.py runserver 5000.

  3. Ctrl+click die http://127.0.0.1:8000/ URL im VS Code-Terminalausgabefenster, um Ihren Standardbrowser für diese Adresse zu öffnen. Wenn Django korrekt installiert ist und das Projekt gültig ist, wird die unten gezeigte Standardseite angezeigt. Im VS Code-Ausgabefenster wird auch das Serverprotokoll angezeigt.

    Standardansicht des leeren Django-Projekts

  4. Wenn Sie fertig sind, schließen Sie das Browserfenster, und beenden Sie den Server in VS Code, indem Ctrl+C Sie wie im Ausgabefenster des VS Code-Terminals angegeben verwenden.

Erstellen einer Django-App für Microsoft Advertising

  1. Führen Sie im VS Code Terminal mit aktivierter startapp virtueller Umgebung den Befehl des Verwaltungsprogramms in Ihrem Projektordner (in dem manage.py sich befindet) aus:

    python manage.py startapp app
    

    Der Befehl erstellt einen Ordner mit dem Namen app , der eine Reihe von Codedateien und einen Unterordner enthält. Von diesen arbeiten Sie häufig mit views.py (das die Funktionen enthält, die Seiten in Ihrer Web-App definieren) und models.py (das Klassen enthält, die Ihre Datenobjekte definieren). Der migrations Ordner wird vom administrativen Hilfsprogramm von Django zur Verwaltung von Datenbankversionen verwendet, wie später in diesem Tutorial erläutert. Es gibt auch die Dateien apps.py (App-Konfiguration) admin.py (zum Erstellen einer administrativen Schnittstelle) und tests.py (für Komponententests), die hier nicht behandelt werden.

  2. Fügen Sie darin app/settings.py den folgenden Code hinzu, und legen Sie Ihre eigenen CLIENT_ID-, CLIENT_SECRET-, DEVELOPER_TOKEN- und ENVIRONMENT-Werte fest.

    """
    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. Innerhalb app/settings.py der Liste der installierten Apps hinzufügen app .

        INSTALLED_APPS = [
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        'app',
    ]
    
  4. Erstellen Sie im VS Code Terminal die app/static/app Ordner "und app/templates/app ":

    (env) PS C:\dev\hello_django> mkdir app/static/app
    (env) PS C:\dev\hello_django> mkdir app/templates/app 
    
  5. Erstellen Sie in den app/static/app Ordnern eine neue Datei mit dem Namen site.css und fügen Sie den folgenden Inhalt hinzu.

    .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. Erstellen Sie innerhalb des app/templates/app Ordners index.html eine Datei mit dem folgenden Inhalt.

    {% 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. Erstellen Sie innerhalb des app/templates/app Ordners layout.html eine Datei mit dem folgenden Inhalt.

    <!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. Erstellen Sie innerhalb des app/templates/app Ordners login.html eine Datei mit dem folgenden Inhalt.

    {% 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. Erstellen Sie innerhalb des app/templates/app Ordners loginpartial.html eine Datei mit dem folgenden Inhalt.

    {% 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. Erstellen Sie innerhalb des app Ordners forms.py eine Datei mit dem folgenden Inhalt.

    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. Ändern app/models.py , um dem folgenden Code zu entsprechen.

    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. Ändern app/views.py , um dem folgenden Code zu entsprechen.

    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. Ersetzen Sie den Inhalt von web_project/urls.py durch den folgenden Inhalt. In dieser urls.py Datei geben Sie Muster an, um verschiedene URLs an ihre entsprechenden Ansichten weiterzuleiten. Der folgende Code ordnet beispielsweise die Stamm-URL der App ("") der home Funktion zu, die Sie gerade hinzugefügt haben 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. Speichern Sie alle geänderten Dateien mit Ctrl+K S.

  15. Führen Sie die Ausführung python manage.py makemigrations aus, um im Migrationsordner Skripts zu generieren, die die Datenbank aus ihrem aktuellen Zustand in den neuen Zustand migrieren.

  16. Führen Sie diese Schritte aus python manage.py migrate , um die Skripts auf die tatsächliche Datenbank anzuwenden. Die Migrationsskripts zeichnen effektiv alle inkrementellen Änderungen auf, die Sie im Laufe der Zeit an Ihren Datenmodellen vornehmen (models.py). Durch Anwenden der Migrationen aktualisiert Django die Datenbank entsprechend Ihren Modellen. Da jede inkrementelle Änderung über ein eigenes Skript verfügt, kann Django jede vorherige Version einer Datenbank (einschließlich einer neuen Datenbank) automatisch auf die aktuelle Version migrieren. Daher müssen Sie sich nur um Ihre Modelle in models.py kümmern, niemals um das zugrunde liegende Datenbankschema oder die Migrationsskripte. Du hast Django diesen Teil überlassen!

  17. Erstellen Sie ein Superuser-Konto in der App, indem Sie ein Terminal in VS Code für Ihre virtuelle Umgebung öffnen, dann den Befehl python manage.py createsuperuser --username=<username> --email=<email>ausführen , ersetzen <username> und <email>natürlich mit Ihren persönlichen Daten. Wenn Sie den Befehl ausführen, werden Sie von Django aufgefordert, Ihr Kennwort einzugeben und zu bestätigen.

    Wichtig

    Merken Sie sich unbedingt Ihre Kombination aus Benutzername und Kennwort. Dies sind die Anmeldeinformationen, die Sie für die Authentifizierung im Verwaltungsportal der Web-App verwenden.

  18. Führen Sie im VS Code Terminal, wiederum mit aktivierter virtueller Umgebung, den Entwicklungsserver mit python manage.py runserver aus, und öffnen Sie einen Browser, um eine Seite anzuzeigen http://127.0.0.1:8000/ , die "Hello, Django" rendert.

  19. Gehen Sie im Webbrowser zu http://127.0.0.1:8000/admin/ und erstellen Sie einen neuen Django-Webbenutzer unter Benutzer. Diese unterscheiden sich von Ihren Microsoft Advertising-Benutzeranmeldeinformationen, sodass sich mehrere Microsoft Advertising-Benutzer separat bei Ihrer App anmelden können.

    Django

  20. Melden Sie sich mit dem neuen Benutzer (nicht dem Super-Admin) an, und die Option zur Authentifizierung mit einem Microsoft-Konto sollte angezeigt werden.

    Microsoft-Konto authentifizieren

  21. Nachdem Sie auf "Microsoft-Konto authentifizieren" geklickt haben, werden Sie aufgefordert, Ihren eigenen Web-App-Berechtigungen zum Verwalten Ihrer Microsoft Advertising-Konten zu erteilen. Wenn Sie zustimmen und Zugriff auf Microsoft Advertising-Konten haben, sollten Sie zu einer Ansicht Ihrer Kontonamen und -IDs umgeleitet werden.

Siehe auch

Erste Schritte mit Python mit der Bing Ads-API