URL-Verkürzer mit Flask und MySQL erstellen

HTMLHTMLAdvanced
Jetzt üben

💡 Dieser Artikel wurde von AI-Assistenten übersetzt. Um die englische Version anzuzeigen, können Sie hier klicken

Einführung

Dieses Projekt führt Sie durch die Erstellung eines einfachen URL-Kürzers mit Flask und MySQL. Sie lernen, eine Datenbank einzurichten, eine Weboberfläche zu entwerfen und Funktionen zur URL-Kürzung, zum Suchen von URLs nach Tags und zur Anzeige von Analysen zu implementieren. Das Projekt ist für Einsteiger geeignet und bietet einen umfassenden Einblick in die Webanwendung mit Python und die Datenbankverwaltung.

Das Projekt basiert auf https://github.com/highoncarbs/shorty, das ursprünglich unter der MIT-Lizenz lizenziert ist.

👀 Vorschau

URL mit/ohne benutzerdefiniertes Suffix umwandeln, URLs nach Tag suchen, auf den Link zugreifen:

Informationen über das Betriebssystem und die Plattform, die zum Zugreifen auf den Link verwendet werden, anzeigen:

🎯 Aufgaben

In diesem Projekt lernen Sie:

  • Wie Sie eine Flask-Anwendung mit einer MySQL-Datenbank verbinden
  • Wie Sie ein MySQL-Datenbank-Schema zur Speicherung von URL-Informationen erstellen und verwalten
  • Wie Sie Frontend-Webseiten mit HTML und CSS implementieren, um mit dem Backend zu interagieren
  • Wie Sie Formulardaten und Anfragen in Flask verarbeiten, um kurze URLs zu erstellen
  • Wie Sie eine Funktion zur Umleitung von Benutzern von einer kurzen URL zur ursprünglichen URL entwickeln
  • Wie Sie eine einfache Analysefunktion zur Verfolgung der URL-Nutzung erstellen, einschließlich der Klickzahlen und grundlegenden Browser/Plattforminformationen
  • Wie Sie eine benutzerfreundliche Fehlerbehandlung und benutzerdefinierte 404-Seiten entwerfen, um die Benutzererfahrung zu verbessern

🏆 Errungenschaften

Nach Abschluss dieses Projekts können Sie:

  • Grundlegende Operationen mit MySQL durchführen, einschließlich der Erstellung von Datenbanken und Tabellen, des Einfügens von Daten und des Abfragens
  • Die Grundlagen von Flask verstehen, einschließlich der Routierung, der Anfragebehandlung und der Vorlagenrendering
  • Mit HTML-Formularen arbeiten und Daten in einer Flask-Anwendung verarbeiten
  • Grundlegende Frontend-Designprinzipien anwenden und CSS verwenden, um eine visuell ansprechende Weboberfläche zu erstellen
  • Einfache Analysen implementieren, um Daten über die URL-Nutzung zu sammeln und anzuzeigen
  • Best Practices für die Fehlerbehandlung in Webanwendungen implementieren, um die Zuverlässigkeit und die Benutzererfahrung zu verbessern

Projektsumgebung einrichten

Zunächst müssen wir unsere Projektsumgebung im Terminal einrichten. Dies umfasst das Installieren des erforderlichen Python-Pakets für die MySQL-Verbindung und das Starten des MySQL-Diensts. Sobald der Dienst gestartet ist, werden wir eine Datenbank und eine Tabelle erstellen, um unsere URLs zu speichern.

Installieren Sie PyMySQL:

pip install PyMySQL==1.1.0

Starten Sie den MySQL-Dienst und melden Sie sich an die MySQL-Shell an:

sudo service mysql start
mysql -u root

Innerhalb der MySQL-Shell führen Sie die folgenden Befehle aus, um die Datenbank und die Tabelle zu erstellen:

Datenbank erstellen:

CREATE DATABASE IF NOT EXISTS SHORTY;
USE SHORTY;

Tabelle erstellen:

CREATE TABLE IF NOT EXISTS WEB_URL
(
    ID             INT AUTO_INCREMENT,
    URL            VARCHAR(512),
    S_URL          VARCHAR(80),
    TAG            VARCHAR(80),
    COUNTER        INT DEFAULT 0,
    CHROME         INT DEFAULT 0,
    FIREFOX        INT DEFAULT 0,
    SAFARI         INT DEFAULT 0,
    OTHER_BROWSER  INT DEFAULT 0,
    ANDROID        INT DEFAULT 0,
    IOS            INT DEFAULT 0,
    WINDOWS        INT DEFAULT 0,
    LINUX          INT DEFAULT 0,
    MAC            INT DEFAULT 0,
    OTHER_PLATFORM INT DEFAULT 0,
    PRIMARY KEY (ID)
);

Dieser SQL-Befehl erstellt eine Tabelle namens WEB_URL in der SHORTY-Datenbank, die zur Speicherung von Informationen zu verkürzten URLs und einigen zugehörigen Analysen gedacht ist.

  • CREATE TABLE IF NOT EXISTS WEB_URL: Dieser Befehl erstellt eine neue Tabelle namens WEB_URL, wenn sie in der Datenbank noch nicht existiert. Dies hilft, Fehler beim mehrfachen Ausführen des Skripts zu vermeiden.
  • ID INT AUTO_INCREMENT: Diese Spalte wird als Primärschlüssel der Tabelle bezeichnet und ist so konfiguriert, dass sie sich automatisch um 1 erhöht, wenn ein neuer Eintrag hinzugefügt wird. Dies bedeutet, dass MySQL jederzeit, wenn ein neues Element hinzugefügt wird, automatisch eine eindeutige ID zuweist.
  • URL VARCHAR(512): In dieser Spalte werden die ursprünglichen URLs gespeichert, die verkürzt werden sollen. Der Datentyp VARCHAR(512) bedeutet, dass sie Zeichenketten beliebiger Länge bis zu 512 Zeichen aufnehmen kann.
  • S_URL VARCHAR(80): Hier wird die verkürzte URL gespeichert, mit einer maximalen Länge von 80 Zeichen.
  • TAG VARCHAR(80): Diese Spalte dient zur Speicherung von Tags, die mit den URLs assoziiert sind, um eine Kategorisierung oder Suche zu ermöglichen, mit einer maximalen Länge von 80 Zeichen.
  • COUNTER INT DEFAULT 0: Diese ganzzahlige Spalte wird wahrscheinlich verwendet, um die Anzahl der Zugriffe auf eine verkürzte URL zu verfolgen. Sie hat den Standardwert 0, wenn ein neuer Datensatz erstellt wird.
    Die nächsten Spalten sind zur Speicherung von Analyse-Daten für die verkürzten URLs gedacht:
  • CHROME, FIREFOX, SAFARI, OTHER_BROWSER: Diese Spalten werden verwendet, um die Anzahl der Besuche von verschiedenen Webbrowsern zu verfolgen. Jede ist eine ganzzahlige Spalte mit dem Standardwert 0.
  • ANDROID, IOS, WINDOWS, LINUX, MAC, OTHER_PLATFORM: Ähnlich wie die Browser-Spalten dienen diese dazu, Besuche von verschiedenen Betriebssystemen/Plattformen zu verfolgen, wobei jeder Spalte der Standardwert 0 zugewiesen wird.
  • PRIMARY KEY (ID): Dieser Teil des Befehls gibt an, dass die ID-Spalte der Primärschlüssel der Tabelle ist. Ein Primärschlüssel ist eine eindeutige Kennung für jeden Datensatz in der Tabelle, was gewährleistet, dass keine zwei Datensätze die gleiche ID haben.

Diese Tabellenstruktur ermöglicht das Speichern, Abrufen und Analysieren von Daten zu verkürzten URLs, einschließlich der Häufigkeit der Zugriffe, der Browser und der Betriebssysteme, von denen aus sie abgerufen werden.

Um die MySQL-Shell zu verlassen, können Sie folgenden Befehl ausführen:

EXIT;

Index-Seiten-Vorlage erstellen

Die Indexseite ist der Ort, an dem die Benutzer mit dem URL-Kürzer interagieren werden. Wir werden HTML und die Vorlagensprache von Flask verwenden, um dynamischen Inhalt zu erstellen.

Fügen Sie im Ordner templates/index.html folgenden HTML-Code hinzu:

<!doctype html>
<html>
  <head>
    <title>Shorty</title>
    <!-- Fügen Sie das lokale SVG-Bild hinzu, wenn Sie das Projekt hosten. -->
    <link
      href="https://fonts.googleapis.com/icon?family=Material+Icons"
      rel="stylesheet"
    />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/1.7.1/clipboard.min.js"></script>
    <link rel="stylesheet" type="text/css" href="../static/skeleton.css" />
    <link rel="stylesheet" type="text/css" href="../static/normalize.css" />
    <link rel="stylesheet" type="text/css" href="../static/main.css" />
    <link
      href="https://fonts.googleapis.com/css?family=Roboto:300,400,700,900"
      rel="stylesheet"
    />
  </head>
  <body>
    <div class="container  main_header">
      <h3 align="left"><a href="{{url_for('index')}}">Shorty</a></h3>
      <p>A very simple URL shortening service.</p>
    </div>

    <div class="u-full-width shorty">
      <div class="container"></div>
    </div>
  </body>
</html>

Hier ist ein Überblick über seine wichtigsten Komponenten:

  • Google Material Icons: Das <link>-Tag importiert die Google Material Icons-Bibliothek, die es ermöglicht, vordefinierte Symbole zu verwenden, um eine ansprechendere Benutzeroberfläche zu schaffen.
  • Clipboard.js: Das <script>-Tag enthält die Clipboard.js-Bibliothek, eine beliebte JavaScript-Bibliothek zum Kopieren von Inhalten in die Zwischenablage. Dies kann für einen URL-Kürzer nützlich sein, da es Benutzern ermöglicht, verkürzte URLs einfach zu kopieren.
  • Stylesheets: Die Vorlage verweist auf mehrere CSS-Dateien für die Gestaltung:
    • skeleton.css: Ein leichter CSS-Framework, das grundlegende Gestaltung und ein responsives Grid-System bietet.
    • normalize.css: Setzt die Browser-Standardstile zurück, um eine konsistente Gestaltung über verschiedene Browser hinweg zu gewährleisten.
    • main.css: Enthält benutzerdefinierte Stile, die speziell für den "Shorty"-Service sind.
  • Google Fonts: Ein weiteres <link>-Tag importiert die Schriftfamilie "Roboto" von Google Fonts, um eine Vielzahl von Schriftgewichten für die Typografie-Design zu bieten.
  • Innerhalb des <body> wird ein div mit der Klasse container main_header verwendet, um einen Header-Bereich zu erstellen, der umfasst:
    • Einen Überschriftstext (<h3>), der einen Link (<a>) enthält, der mit Hilfe der Flask-Funktion url_for zur Indexseite weiterleitet und die URL für die 'index'-Route dynamisch generiert.
    • Einen Absatz (<p>), der den Service als "A very simple URL shortening service." beschreibt.
✨ Lösung prüfen und üben

URL-Kürzung und tag-basierter Suchvorgang implementieren

In diesem Schritt werden wir die Weboberfläche durch die Integration zweier wichtiger Funktionen erweitern: die URL-Kürzung und der tag-basierte URL-Suchvorgang. Dadurch können Benutzer nicht nur URLs kürzen, sondern auch diese effizient mithilfe von Tags organisieren und abrufen.

URL-Kürzung

Zunächst werden wir ein Formular auf der Indexseite erstellen, in dem Benutzer die URL eingeben können, die sie kürzen möchten. Optionale Felder für benutzerdefinierte Suffixe und Tags ermöglichen individuelle kürzere URLs und eine Kategorisierung für eine einfachere Verwaltung.

Fügen Sie folgenden Code in templates/index.html hinzu:

<!-- Search URL block -->
<div class="search_url_block">
  <form method="post" action="/search" name="search_tag_block">
    <input type="text" name="search_url" placeholder="Search tags " />
    <button type="submit" class="button-primary search_url_btn" value="Search">
      Search
    </button>
  </form>
</div>
<!-- end block -->

Der erste Codeblock fügt ein Formular hinzu, das für das Suchen von URLs anhand ihrer zugeordneten Tags gedacht ist:

  • search_url_block: Dieser Container hält das Suchformular, wodurch es einen separaten Abschnitt auf der Seite für eine bessere Organisation und Gestaltung darstellt.
  • <form>: Definiert ein Formular, das einen POST-Anfrage an den Endpunkt /search sendet, wenn der Suchbutton geklickt wird. Dieses Formular wird als search_tag_block benannt zur Identifizierung.
  • <input>: Ein Text-Eingabefeld, in dem Benutzer die Tags eingeben können, nach denen sie suchen möchten. Das placeholder-Attribut gibt dem Benutzer einen Hinweis über den Zweck des Felds.
  • <button>: Ein Submit-Button, der die Formularübermittlung initiiert. Die Klasse button-primary fügt wahrscheinlich eine spezifische Gestaltung hinzu, die in der CSS definiert ist.

Tag-basierter Suchvorgang

Um die URL-Kürzungsfunktion zu ergänzen, implementieren wir auch eine Funktion, die es Benutzern ermöglicht, URLs anhand von Tags zu suchen. Diese Funktion wird in die Index-Vorlage integriert und bietet ein einfaches Formular, in dem Benutzer Tags eingeben können, um entsprechende URLs zu finden.

Fügen Sie folgenden Code in templates/index.html hinzu:

<!-- URL Input block -->
<form method="post" action="" name="generate_block">
  <div class="row">
    <input type="text" name="url_input" placeholder="Enter URL" />
    <input type="text" name="url_custom" placeholder="Enter Custom Suffix" />
    <input type="text" name="url_tag" placeholder="Tag URL" />
    <button class="button-primary generate">Generate</button>
  </div>
</form>
<!-- end block -->

Der zweite Codeblock stellt ein Formular für Benutzer bereit, um URLs zu kürzen, mit zusätzlichen Feldern für die Anpassung:

  • Das gesamte Formular ist in einem <form>-Element eingeschlossen mit method="post" und einem unspezifizierten action-Attribut. Dies bedeutet, dass die Formulardaten über eine POST-Anfrage an die aktuelle URL gesendet werden, wenn der Generieren-Button geklickt wird.
  • Innerhalb des Formulars ist ein <div> mit der Klasse row wahrscheinlich für die Layout- und Ausrichtungshilfe zuständig und stellt sicher, dass die Eingabefelder und der Button richtig organisiert sind.
  • Drei <input type="text">-Elemente werden für verschiedene Zwecke bereitgestellt:
    • Das erste Eingabefeld ist für Benutzer, um die ursprüngliche URL einzugeben, die sie kürzen möchten.
    • Das zweite ermöglicht einen optionalen benutzerdefinierten Suffix für die verkürzte URL und ermöglicht es Benutzern, ihre kürzen Links zu personalisieren.
    • Das dritte Feld ist für Tags bestimmt und ermöglicht es Benutzern, ihre verkürzten URLs zu kategorisieren oder beschreibende Labels hinzuzufügen, um eine einfachere Abrufung und Verwaltung zu ermöglichen.
  • Ein <button> mit der Klasse button-primary und dem Text "Generate" fungiert als Submissionsbutton des Formulars. Beim Klicken dieses Buttons werden die Daten an den Server gesendet, um eine verkürzte URL mit der bereitgestellten Information zu erstellen.

Diese Verbesserungen verbessern die Benutzererfahrung erheblich, indem sie Funktionen über die einfache URL-Kürzung hinaus bieten. Die Möglichkeit, URLs anhand von Tags zu suchen, ermöglicht eine effiziente Verwaltung und Abrufung von verkürzten Links, während die Option, benutzerdefinierte Suffixe und Tags hinzuzufügen, eine Personalisierung und Kategorisierung von URLs ermöglicht. Diese Einrichtung nutzt HTML-Formulare, um Benutzerinput zu sammeln, der dann von der serverseitigen Flask-Anwendung verarbeitet wird, um die gewünschten Aktionen auszuführen.

✨ Lösung prüfen und üben

Fehler behandeln und verkürzte URLs anzeigen

In diesem Schritt konzentrieren wir uns auf die Verbesserung der Benutzererfahrung durch die Behandlung von Fehlermeldungen und die Anzeige der verkürzten URLs.

Fehler behandeln

Zunächst fügen wir Funktionen hinzu, um Fehlermeldungen an die Benutzer anzuzeigen. Dies ist entscheidend für die Bereitstellung von Feedback, wenn etwas schief geht, wie wenn ein Benutzer eine ungültige URL oder einen nicht existierenden Tag einstellt. Eine richtige Fehlerbehandlung macht die Anwendung robuster und nutzerfreundlicher.

Fügen Sie folgenden Code in templates/index.html hinzu:

<!-- Error Display block -->
{% if error!= '' %}
<p class="error_disp">{{error}}</p>
{% endif %} {% if shorty_url %}
<!-- end block-->

Dieser Block ist dazu gedacht, dem Benutzer Feedback zu geben, wenn ein Fehler beim Kürzen der URL auftritt:

  • {% if error!= '' %}: Dies ist eine bedingte Anweisung, die die Templating-Syntax von Flask, Jinja2, verwendet. Sie überprüft, ob die Variable error nicht leer ist. Die Variable error wird von der Flask-Backendseite an die Vorlage übergeben. Wenn es eine Fehlermeldung gibt, bewertet die Bedingung als True.
  • <p class="error_disp">{{error}}</p>: Wenn die Bedingung True ist, wird dieses Absatzelement gerendert und zeigt die in der Variable error enthaltene Fehlermeldung an. Die Klasse error_disp wird wahrscheinlich für die Gestaltung der Fehlermeldung verwendet, um sie visuell auffällig zu machen und die Aufmerksamkeit des Benutzers zu ziehen.
  • {% endif %}: Dies schließt den bedingten Block. Wenn die Variable error leer ist, wird nichts aus diesem Block auf der Seite gerendert.

Verkürzte URLs anzeigen

Zweitens werden wir nach erfolgreicher Kürzung einer URL die verkürzte URL an den Benutzer anzeigen. Dies umfasst das Erstellen eines Abschnitts auf der Indexseite, der die verkürzte URL dynamisch nach der Formularübermittlung zeigt, zusammen mit einem Button zum Kopieren in die Zwischenablage für einfache Weitergabe.

Fügen Sie folgenden Code in templates/index.html hinzu:

<!-- URL Generator Display block -->
<div class="gen_block">
  <p class="gen_url">
    Shorty URL is
    <b><a id="short-url" href="{{shorty_url}}">{{shorty_url}}</a></b>
  </p>
  <button
    class="button-primary copy-btn"
    data-clipboard-action="copy"
    data-clipboard-target="#short-url"
  >
    Copy
  </button>
</div>
{% endif %}
<!-- end block -->

Dieser Block wird angezeigt, wenn eine URL erfolgreich gekürzt wurde, und bietet Benutzern eine Möglichkeit, die verkürzte URL einfach zu kopieren:

  • {% if shorty_url %}: Eine weitere bedingte Anweisung, die überprüft, ob die Variable shorty_url existiert und nicht leer ist. Diese Variable sollte die von dem Service generierte verkürzte URL enthalten.
  • <p class="gen_url">: Dieser Absatz zeigt eine Nachricht an, die die verkürzte URL angibt. Darin erstellt <a id="short-url" href="{{shorty_url}}">{{shorty_url}}</a> einen Hyperlink, wobei die verkürzte URL sowohl als Linktext als auch als href-Attribut verwendet wird, was es Benutzern ermöglicht, direkt darauf zu klicken.
  • <button>: Dieser Button ist dazu gedacht, die verkürzte URL in die Zwischenablage zu kopieren, um eine einfache Weitergabe zu ermöglichen. Er verwendet Klassen für die Gestaltung (button-primary) und die Funktionalität (copy-btn). Das data-clipboard-action-Attribut gibt die auszuführende Aktion (Kopieren) an, und data-clipboard-target gibt das Ziel-Element an, von dem kopiert werden soll (der Link zur verkürzten URL). Diese Einrichtung setzt die Integration von Clipboard.js (oder einer ähnlichen Bibliothek) voraus, um die Kopierfunktionalität zu behandeln.
  • {% endif %}: Schließt den bedingten Block für die Anzeige der verkürzten URL und des Kopierbuttons. Wenn shorty_url nicht festgelegt oder leer ist, wird dieser Abschnitt nicht gerendert.

Diese Verbesserungen tragen erheblich zur Benutzerfreundlichkeit des URL-Kürzers bei. Fehlermeldungen liefern essentielles Feedback, die Benutzer bei der Korrektur von Fehlern oder der Kenntnisnahme von Problemen unterstützt, während die Anzeige von verkürzten URLs mit einer einfachen Kopierfunktion für eine nahtlose Erfahrung bei der Erstellung und Weitergabe verkürzter Links sorgt.

✨ Lösung prüfen und üben

Verkürzte URLs auflisten und verwalten

Der letzte Schritt besteht darin, einen Abschnitt zu erstellen, in dem alle in der Datenbank gespeicherten verkürzten URLs aufgelistet werden, zusammen mit ihrer ursprünglichen URL, der Anzahl der auf sie erhaltenen Klicks und Links zu detaillierten Analysen. Diese Funktion ermöglicht es Benutzern, ihre verkürzten URLs an einem Ort zu sehen und zu verwalten, was die Anwendung funktionaler und nutzerfreundlicher macht.

Fügen Sie folgenden Code in templates/index.html hinzu:

        <!-- URL List Block -->
        {% if not error %}
        {% if not shorty_url %}
        <!-- Add Empty list case -> 'Wow. Such Empty!' -->
        <div style="overflow-x:auto;">
            <div class="table_list u-full-width">
                <table>
                    <thead>
                    <tr>
                        <th>Original URL</th>
                        <th>Short URL</th>
                        <th>Clicks</th>
                        <th>Info</th>
                    </tr>
                    </thead>

                    <tbody>
                    {% for url in table %}
                    <tr>
                        <td style="padding-left: 5px;">{{url[1]}}</td>
                        <td><a href="{{host+url[2]}}">{{ host+url[2]}}</a></td>
                        <td style="text-align: center;">{{url[4]}}</td>
                        <td id="info"><a href=" {{url_for('analytics',short_url=url[2])}} "><i class="material-icons">info_outline</i></a>
                        </td>
                    </tr>

                    {% endfor %}
                    </tbody>
                </table>
            </div>
        </div>
        {% endif %}
        {% endif %}
    </div>
</div>
<script type="text/javascript">
    var clipboard = new Clipboard('.copy-btn');
</script>
</html>

Dieser Code ist dazu gedacht, alle in der Datenbank gespeicherten verkürzten URLs aufzulisten und Informationen wie die ursprüngliche URL, die verkürzte URL, die Anzahl der Klicks und Links zu detaillierteren Analysen bereitzustellen. Hier ist eine detaillierte Aufteilung seiner Komponenten:

  • Der Block beginnt mit einer bedingten Anweisung {% if not error %}, um sicherzustellen, dass die Liste nur dann angezeigt wird, wenn kein Fehler auftritt. Dies hilft dabei, eine saubere Benutzeroberfläche zu halten, insbesondere wenn Fehlermeldungen angezeigt werden müssen.
  • Eine weitere bedingte Anweisung {% if not shorty_url %} überprüft, ob gerade keine neue verkürzte URL generiert wurde. Diese Bedingung kann verwendet werden, um zu verhindern, dass die Liste sofort nach dem Kürzen einer neuen URL angezeigt wird und stattdessen die Aufmerksamkeit des Benutzers auf die neu erstellte verkürzte URL richtet.
  • Ein Stil overflow-x:auto; wird auf ein div angewendet, um sicherzustellen, dass die Tabelle auf kleineren Bildschirmen horizontal scrollbar ist, was die Reaktionsfähigkeit und Benutzerfreundlichkeit verbessert.
  • Das table-Element ist strukturiert mit einem thead-Abschnitt, der Spaltenüberschriften für "Original URL", "Short URL", "Clicks" und "Info" definiert. Dieses Layout hilft Benutzern, die präsentierten Daten zu verstehen.
  • Der tbody-Abschnitt wird dynamisch mit Daten gefüllt, indem eine Flask/Jinja2-Schleife verwendet wird: {% for url in table %}. Diese Schleife iteriert über eine Sammlung von URLs (table), die von der Flask-Backendseite übergeben werden, und zeigt die Daten jeder URL in einer neuen Tabellenzeile (<tr>) an.
  • Innerhalb jeder Zeile wird die ursprüngliche URL in einer Zelle (<td>) mit etwas Innenabstand für die Ästhetik angezeigt. Die verkürzte URL wird als anklickbarer Link (<a>) dargestellt, der durch Anhängen des verkürzten Pfads (url[2]) zum Hostnamen (host) konstruiert wird, der ebenfalls von der Backendseite übergeben werden sollte.
  • Die "Clicks"-Spalte zeigt die Anzahl der Male an, wie oft die verkürzte URL abgerufen wurde, zentriert für eine bessere Lesbarkeit.
  • Die "Info"-Spalte enthält einen Link zur Analyse-Seite für jede verkürzte URL. Dieser Link wird mithilfe der Flask-Funktion url_for generiert, indem dynamisch eine URL zur Analyse-Route erstellt wird, wobei die verkürzte URL als Parameter verwendet wird. Ein Symbol (<i class="material-icons">info_outline</i>) aus der Google Material Icons-Sammlung wird verwendet, um den Analyse-Link visuell darzustellen.
  • Das {% endfor %}-Tag schließt die Schleife, um sicherzustellen, dass für jede URL in der table-Sammlung eine Zeile erstellt wird.
  • Die bedingten Blöcke werden mit {% endif %}-Tags geschlossen.
  • Am Ende initialisiert ein <script>-Tag Clipboard.js für die .copy-btn-Klasse, die möglicherweise in den vorherigen Abschnitten verwendet wurde (z.B. zum Kopieren der verkürzten URL). Dieses Skript stellt sicher, dass jedes Element mit der copy-btn-Klasse die Funktion zum Kopieren in die Zwischenablage aktiviert hat, indem die Clipboard.js-Bibliothek genutzt wird.

Dieser letzte Schritt rundet die Funktionalität des "Shorty"-URL-Kürzers ab, indem Benutzern einen umfassenden Überblick über ihre verkürzten URLs gegeben wird, was es einfacher macht, ihre Links zu verwalten und zu analysieren. Die Integration der dynamischen Datenrendierung mit Flask/Jinja2, kombiniert mit einem bedachten UI-Design, gewährleistet eine nutzerfreundliche Erfahrung.

✨ Lösung prüfen und üben

Suche-Seiten-Vorlage erstellen

Um Benutzern die Möglichkeit zu geben, URLs anhand von Tags zu suchen, benötigen wir eine Suchseite.

Fügen Sie im Ordner templates/search.html folgenden HTML-Code hinzu:

<!DOCTYPE html>
<html>
<head>
    <title>Shorty</title>
    <link href="https://fonts.googleapis.com/icon?family=Material+Icons"
          rel="stylesheet">
    <link rel="stylesheet" type="text/css" href="../static/skeleton.css">
    <link rel="stylesheet" type="text/css" href="../static/normalize.css">
    <link rel="stylesheet" type="text/css" href="../static/main.css">
    <link href="https://fonts.googleapis.com/css?family=Roboto:300,400,700,900" rel="stylesheet">
</head>
<body>
<div class="container main_header">
    <h3 align="left"><a href="{{url_for('index')}}">Shorty</a></h3>
    <p>A dead simple URL shortener service.</p>
</div>
<!-- Search results  -->
<div class=" container search_header">
    <h4>Search Results for : <b> {{ search_tag }} <b></h4>

    <div style="overflow-x:auto;">
        <div class="table_list u-full-width">
            <table>
                <thead>
                <tr>
                    <th>Original URL</th>
                    <th>Short URL</th>
                    <th>Clicks</th>
                    <th>Info</th>

                </tr>
                </thead>

                <tbody>
                {% for url in table %}
                <tr>
                    <td style="padding-left: 5px;">{{url[1]}}</td>
                    <td><a href="{{ host+url[2]}}">{{host+url[2]}}</a></td>
                    <td style="text-align: center;">{{url[4]}}</td>
                    <td id="info"><a href=" {{url_for('analytics',short_url=url[2])}} "><i class="material-icons">info_outline</i></a>
                    </td>
                </tr>
                {% endfor %}
                </tbody>
            </table>
        </div>
    </div>
</div>
</body>
</html>

Dieser Code erstellt eine Vorlage für die Suchergebnisse-Seite im "Shorty"-URL-Kürzer-Service. Diese Seite ist dazu gedacht, die Ergebnisse einer Benutzersuche nach URLs anhand von Tags anzuzeigen. Hier ist eine detaillierte Aufteilung der Vorlage:

  • Innerhalb des <body> spiegelt der Header-Abschnitt (<div class="container main_header">) die Indexseite wider und bietet ein einheitliches Aussehen. Er enthält den Dienstnamen ("Shorty") als einen anklickbaren Link, der zur Indexseite weiterleitet ({{url_for('index')}}), und eine kurze Beschreibung des Diensts.
  • Der <div class="container search_header">-Abschnitt führt den Bereich mit den Suchergebnissen ein, beginnend mit einem Header (<h4>), der dynamisch den für die Suche verwendeten Tag ({{ search_tag }}) anzeigt.
  • Die Ergebnisse werden in einer Tabelle innerhalb eines div dargestellt, das für horizontales Scrollen gestylt ist (overflow-x:auto;), um eine Zugänglichkeit auf Geräten mit kleineren Bildschirmen zu gewährleisten.
  • Die Tabellenstruktur (<table>) besteht aus einem Header (<thead>) und einem Körper (<tbody>)-Abschnitt. Der Header definiert Spalten für "Original URL", "Short URL", "Clicks" und "Info", ähnlich wie die Liste, die auf der Indexseite angezeigt wird.
  • Der Körper der Tabelle wird dynamisch mit einer Schleife ({% for url in table %}) gefüllt, die über eine Sammlung von URLs (table) iteriert, die von der Flask-Backendseite übergeben werden. Jede Iteration erstellt eine neue Zeile (<tr>) in der Tabelle für eine URL:
    • Die ursprüngliche URL wird mit etwas Innenabstand für eine bessere Lesbarkeit angezeigt.
    • Die verkürzte URL wird als einen anklickbaren Link dargestellt, der durch Anhängen des verkürzten Pfads zum Hostnamen konstruiert wird, wobei beide dynamisch mithilfe der Flask-Templating-Syntax eingefügt werden.
    • Die "Clicks"-Spalte zeigt an, wie oft die verkürzte URL abgerufen wurde, wobei der Text zentriert ist für eine bessere Übersichtlichkeit.
    • Die "Info"-Spalte bietet einen Link zu detaillierten Analysen für jede URL, indem die Flask-Funktion url_for verwendet wird, um die URL dynamisch zu generieren, und ein Symbol (<i class="material-icons">info_outline</i>) für die visuelle Darstellung.

Diese Suchergebnisse-Vorlage verbessert den "Shorty"-Dienst, indem Benutzern die Möglichkeit gibt, URLs effektiv anhand von Tags zu finden und zu verwalten, und bietet eine nahtlose und intuitive Benutzererfahrung. Die konsistente Verwendung von Stilen und Layout-Elementen aus der Indexseite gewährleistet ein kohärentes Design über die gesamte Anwendung.

✨ Lösung prüfen und üben

Analytics-Seiten-Vorlage erstellen

Die Analytics-Seite wird detaillierte Informationen über die Nutzung einer verkürzten URL anzeigen, einschließlich der Anzahl der Klicks, der Browser- und Plattformstatistiken.

Fügen Sie im Ordner templates/data.html folgenden HTML-Code hinzu:

<!doctype html>
<html>
  <head>
    <title>Shorty</title>

    <!-- Add Local SVG image when hosting. -->
    <link
      href="https://fonts.googleapis.com/icon?family=Material+Icons"
      rel="stylesheet"
    />

    <link rel="stylesheet" type="text/css" href="../static/skeleton.css" />
    <link rel="stylesheet" type="text/css" href="../static/normalize.css" />
    <link rel="stylesheet" type="text/css" href="../static/main.css" />
    <link
      href="https://fonts.googleapis.com/css?family=Roboto:300,400,700,900"
      rel="stylesheet"
    />
  </head>
  <body>
    <div class="container  main_header">
      <h3 align="left"><a href="{{url_for('index')}}">Shorty</a></h3>
      <p>A dead simple URL shortener service.</p>
    </div>
    <div class=" container modal-content">
      <!-- Array index -> 
      broswer : 
          CHROME,
          FIREFOX,
          SAFARI,
          OTHER_BROWSER,
      platform:
          ANDROID,
          IOS,
          WINDOWS,
          LINUX,
          MAC,
          OTHER_PLATFORM
       -->
      <div class="url_info">
        <h4>
          Analytics data for :
          <a href="{{host+info[1]}}">{{'localhost/'+info[1]}}</a>
        </h4>
        <p>
          Original URL :
          <a style="text-decoration: none" href="{{info[0]}}">{{info[0]}}</a>
        </p>
      </div>
      <div class="data_block">
        <div class="browser_list">
          <h4>Browser</h4>
          <table>
            <thead>
              <tr>
                <th>Chrome</th>
                <th>Firefox</th>
                <th>Safari</th>
                <th>Other Broswers</th>
              </tr>
            </thead>

            <tbody>
              <tr>
                <td style="padding-left: 5px;">{{browser[0]}}</td>
                <td>{{browser[1]}}</td>
                <td>{{browser[2]}}</td>
                <td>{{browser[3]}}</td>
              </tr>
            </tbody>
          </table>
        </div>
        <div class="platform_list">
          <h4>Platform</h4>
          <table>
            <thead>
              <tr>
                <th>Android</th>
                <th>IOS</th>
                <th>Windows</th>
                <th>Linux</th>
                <th>Mac</th>
                <th>Other Platforms</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td style="padding-left: 5px;">{{platform[0]}}</td>
                <td>{{platform[1]}}</td>
                <td>{{platform[2]}}</td>
                <td>{{platform[3]}}</td>
                <td>{{platform[4]}}</td>
                <td>{{platform[5]}}</td>
              </tr>
            </tbody>
          </table>
        </div>
      </div>
    </div>
  </body>
</html>

Dieser Code enthält Informationen über die Anzahl der Klicks, die Browser-Nutzung und die Plattformverteilung. Hier ist eine Aufteilung seiner Struktur und Komponenten:

  • Ein div mit den Klassen container modal-content umschließt die Analytics-Informationen und ist als Modal oder als separates Inhaltsblock innerhalb der Seite gestaltet.
  • Der url_info-div zeigt:
    • Ein <h4>-Überschrift, die angibt, dass die folgenden Daten zu den Analytics einer bestimmten verkürzten URL gehören. Die verkürzte URL wird als einen anklickbaren Link dargestellt, der mithilfe der Variablen host und info[1] konstruiert wird, wobei info[1] den verkürzten Pfad enthält.
    • Ein Absatz (<p>), der die ursprüngliche URL als einen anklickbaren Link zeigt, um den Zugang zum ursprünglichen Inhalt zu erleichtern.
  • Zwei separate Abschnitte, browser_list und platform_list, enthalten jeweils eine Tabelle, die die Nutzungstatistiken für Browser und Plattformen anzeigt:
    • Der browser_list-Abschnitt enthält eine Tabelle mit Überschriften für Chrome, Firefox, Safari und Other Browsers. Der <tbody>-Abschnitt zeigt die entsprechenden Statistiken an, die aus dem Array-Variable browser abgerufen werden, das an die Vorlage übergeben wird.
    • Ähnlich hat der platform_list-Abschnitt eine Tabelle für die Plattformnutzung mit Überschriften für Android, iOS, Windows, Linux, Mac und Other Platforms. Die Nutzungstatistiken werden im Tabellenkörper gezeigt, die aus dem Array-Variable platform stammen.
  • Die Tabellen verwenden <thead> für die Überschriften und <tbody> für die tatsächlichen Daten, um ein semantisches HTML zu gewährleisten und die Gestaltung und Zugänglichkeit zu erleichtern.
  • Die Datenzellen (<td>) innerhalb der Tabellen zeigen die jeweiligen Zählungen für jeden Browser und jede Plattform an, die für die Lesbarkeit ausgerichtet und gestaltet sind.

Diese Vorlage kommuniziert die Analytics-Daten effektiv an den Benutzer und bietet Einblicke in die Art und Weise, wie die verkürzte URL abgerufen wird, einschließlich der Browser und Plattformen, die von der Zielgruppe verwendet werden. Das saubere Layout, kombiniert mit der klaren Trennung der Daten in verschiedene Abschnitte, macht es Benutzern leicht, die Leistung ihrer URL zu verstehen und zu interpretieren.

✨ Lösung prüfen und üben

404-Seiten-Vorlage erstellen

Eine benutzerdefinierte 404-Seite verbessert die Benutzererfahrung, indem eine hilfreichere Fehlermeldung angezeigt wird, wenn eine verkürzte URL nicht gefunden wird.

Fügen Sie im Ordner templates/404.html folgenden HTML-Code hinzu:

<!doctype html>
<html>
  <head>
    <title>Shorty</title>

    <!-- Add Local SVG image when hosting. -->
    <link
      href="https://fonts.googleapis.com/icon?family=Material+Icons"
      rel="stylesheet"
    />

    <link rel="stylesheet" type="text/css" href="../static/skeleton.css" />
    <link rel="stylesheet" type="text/css" href="../static/normalize.css" />
    <link rel="stylesheet" type="text/css" href="../static/main.css" />
    <link
      href="https://fonts.googleapis.com/css?family=Roboto:300,400,700,900"
      rel="stylesheet"
    />
  </head>
  <body>
    <div class="lost">
      <h2>Oi, chap you seem lost!</h2>
    </div>
  </body>
</html>

Diese benutzerdefinierte 404-Seiten-Vorlage kommuniziert effektiv an die Benutzer, dass die Seite, nach der sie suchen, nicht existiert, und bewahrt dabei eine leichtfertige Tonart auf.

✨ Lösung prüfen und üben

Designen der Weboberfläche

Als nächstes werden wir die Weboberfläche gestalten. Beginnen Sie mit der Erstellung der Haupt-CSS-Datei, um unsere Anwendung zu stylen.

Fügen Sie im Ordner static/main.css folgenden CSS-Code hinzu, um die HTML-Elemente zu stylen:

html {
  border-top: 5px solid #d9edf7;
}
body {
  font-family: "Roboto", sans-serif;
  margin-top: 50px;
  margin-bottom: 0;
}
h3 {
  padding: 0;
  margin: 0;
}
h3 a {
  font-weight: 700;
  text-decoration: none;
  color: black;
}
h3 a:hover {
  color: grey;
  transition: 0.2s all;
}
/** Hauptheader */
.main_header {
  margin-bottom: 20px;
}
/* Suchblock */
.search_url_block {
  padding: 15px;
  background-color: #d9edf7;
  color: #31708f;
  border-radius: 5px;
  margin-bottom: 10px;
}
form {
  margin: 0;
}

.search_header {
  margin-top: 20px;
}

.material-icons {
  padding: 5px;
  padding-top: 7px;
  opacity: 0.7;
}

.material-icons:hover {
  opacity: 1;
}
/* URL-Generierungsblock */

.gen_block {
  margin-top: 10px;
  padding: 15px;
  background-color: #dff0d8;
  color: #2b542c;
  border-radius: 5px;
  width: auto;
  font-size: 20px;
}
/* Fehleranzeige */
.error_disp {
  padding: 15px;
  border-radius: 5px;
  background-color: #fcf8e3;
  color: #b84442;
  width: auto;
  font-size: 20px;
  margin-top: 10px;
}

/* Tabellenanzeige-Block*/

.table_list {
  padding-top: 10px;
  margin-top: 40px;
  border-top: 2px solid lightgrey;
}
table {
  font-size: 20px;
  width: 100%;
}
thead {
  font-weight: 700;
  padding: 2px;
}
tbody {
  font-weight: 400;
}
th {
  padding: 5px;
}
td {
  padding: 5px;
}
tr {
  padding: 5px;
}
tbody tr:hover {
  background-color: #f5f5f5;
  transition: 0.1s all ease-out;
}

/* Analytics-Block*/
.url_info {
  margin-top: 10px;
  padding: 15px;
  background-color: #d9edf7;
  color: #31708f;
  border-radius: 5px;
  margin-bottom: 10px;
}
.url_info h4,
p {
  margin: 0;
  padding: 0;
}
.data_block {
  margin-top: 20px;
}

/* 404. Verloren */
.lost {
  margin-top: 20px;
}
.lost h2 {
  font-weight: 700;
  font-size: 40px;
  text-align: center;

  color: #31708f;
}
.lost p {
  font-weight: 400;
  font-size: 20px;
  text-align: center;
}

Das Gesamtlayout verwendet eine Kombination aus Hintergrundfarben, Textfarben und Innenabständen, um eine saubere, moderne Oberfläche zu schaffen, die einfach zu durchlaufen ist. Die Verwendung von Radius bei verschiedenen Elementen gibt der Oberfläche ein weicheres, zugänglichereres Gefühl, während Hover-Effekte die Interaktivität verbessern. Die konsistente Verwendung der Roboto-Schrift gewährleistet ein zusammenhängendes Aussehen über die gesamte Anwendung.

✨ Lösung prüfen und üben

Datenbankverbindung und Betriebsfunktionen

Hilfsfunktionen werden die Datenbankverbindung, die URL-Validierung, die Aktualisierung der Browser- und Plattformzähler und die Generierung von Zufallstoken für verkürzte URLs handhaben.

Datenbankverbindung

Zunächst werden Sie die Datenbankverbindung mit pymysql einrichten. Dies ist entscheidend, um Ihre Flask-Anwendung mit der MySQL-Datenbank interagieren zu können.

Fügen Sie im Ordner utils.py folgenden Python-Code hinzu:

from urllib.parse import urlparse
import random
import string

import pymysql


db_config = {
    "host": "localhost",
    "user": "root",
    "password": "",
    "db": "SHORTY"
}


def get_db_connection() -> pymysql.Connection:
    """Erstellt und gibt eine neue Datenbankverbindung zurück."""
    return pymysql.connect(**db_config)
  • Die pymysql-Bibliothek wird verwendet, um sich mit der MySQL-Datenbank zu verbinden. Diese Bibliothek ermöglicht es Python-Anwendungen, mit MySQL-Datenbanken über eine einfache API zu interagieren.
  • Das db_config-Dictionary enthält die Datenbankverbindungsparameter wie Host, Benutzer, Passwort und Datenbankname. Diese werden aus einem separaten config-Modul importiert, vermutlich zur besseren Sicherheit und Modularität. Das Trennen der Konfigurationsparameter ermöglicht einfachere Anpassungen ohne die Hauptcodebasis zu ändern.
  • Die get_db_connection()-Funktion erstellt und gibt eine neue Verbindung zur Datenbank zurück, indem die pymysql.connect(**db_config)-Funktion verwendet wird. Die **db_config-Syntax wird verwendet, um das Dictionary in Schlüsselwortargumente zu entpacken.

Datenbankbetriebsfunktionen

Nachdem eine Datenbankverbindung hergestellt wurde, folgt der nächste Schritt, die Erstellung von Funktionen, die Operationen auf der Datenbank ausführen. Dazu gehören das Auflisten von Daten für eine gegebene verkürzte URL und die Aktualisierung der Zähler basierend auf der Browser- und Plattformnutzung.

Fügen Sie im Ordner utils.py folgenden Python-Code hinzu:

def list_data(shorty_url: str) -> tuple:
    """
    Nimmt die verkürzte URL als Eingabe.
    Gibt Zähler, Browser, Plattform-Zählungen zurück.
    """
    with get_db_connection() as conn, conn.cursor() as cursor:

        su = [shorty_url]
        info_sql = "SELECT URL, S_URL, TAG FROM WEB_URL WHERE S_URL = %s; "
        counter_sql = "SELECT COUNTER FROM WEB_URL WHERE S_URL = %s; "
        browser_sql = "SELECT CHROME, FIREFOX, SAFARI, OTHER_BROWSER FROM WEB_URL WHERE S_URL = %s;"
        platform_sql = "SELECT ANDROID, IOS, WINDOWS, LINUX, MAC, OTHER_PLATFORM FROM WEB_URL WHERE S_URL = %s;"

        cursor.execute(info_sql, su)
        info_fetch = cursor.fetchone()
        cursor.execute(counter_sql, su)
        counter_fetch = cursor.fetchone()
        cursor.execute(browser_sql, su)
        browser_fetch = cursor.fetchone()
        cursor.execute(platform_sql, su)
        platform_fetch = cursor.fetchone()

    return info_fetch, counter_fetch, browser_fetch, platform_fetch

def update_counters(cursor: pymysql.Connection, short_url: str, browser_dict: dict, platform_dict: dict) -> None:
    """Aktualisiert die Browser- und Plattformzähler in der Datenbank für die gegebene verkürzte URL."""
    counter_sql = """UPDATE WEB_URL SET COUNTER = COUNTER + 1,
                     CHROME = CHROME + %s, FIREFOX = FIREFOX + %s, SAFARI = SAFARI + %s, OTHER_BROWSER = OTHER_BROWSER + %s,
                     ANDROID = ANDROID + %s, IOS = IOS + %s, WINDOWS = WINDOWS + %s, LINUX = LINUX + %s, MAC = MAC + %s, OTHER_PLATFORM = OTHER_PLATFORM + %s
                     WHERE S_URL = %s;"""
    cursor.execute(counter_sql, (browser_dict['chrome'], browser_dict['firefox'], browser_dict['safari'], browser_dict['other'],
                                 platform_dict['android'], platform_dict['iphone'], platform_dict[
                                     'windows'], platform_dict['linux'], platform_dict['macos'], platform_dict['other'],
                                 short_url))
  • Die list_data(shorty_url)-Funktion ist dazu bestimmt, verschiedene Informationen aus der WEB_URL-Tabelle für eine gegebene verkürzte URL (shorty_url) abzurufen. Sie etabliert eine Verbindung zur Datenbank und führt vier SQL-Abfragen aus, um die ursprüngliche URL, das zugehörige Tag, den Zugangszähler, den Browser und die Plattform-Analysen abzurufen. Jede Abfrage wird separat ausgeführt, und die Ergebnisse werden abgerufen und zurückgegeben.
  • Die update_counters(cursor, short_url, browser_dict, platform_dict)-Funktion aktualisiert den Zugangszähler, den Browser und die Plattformzähler für eine gegebene verkürzte URL in der Datenbank. Diese Funktion nimmt einen Datenbankcursor, die verkürzte URL und zwei Dictionaries mit Zählungen für jeden Browser und jede Plattform als Argumente. Sie konstruiert einen UPDATE-SQL-Befehl, um die Zähler für die verkürzte URL basierend auf den bereitgestellten Daten zu erhöhen. Die Funktion nimmt an, dass die Browser- und Plattforminformationen vor dem Aufruf dieser Funktion bestimmt wurden und dass diese Informationen als Dictionaries (browser_dict und platform_dict) übergeben werden, mit Schlüsseln, die den Spalten in der WEB_URL-Tabelle entsprechen.

Dieser Aufbau ist ein typisches Muster für Webanwendungen, die Flask und MySQL verwenden, wobei Hilfsfunktionen für häufige Datenbankoperationen definiert werden. Diese Funktionen können dann importiert und im gesamten Anwendungsbereich verwendet werden, um mit der Datenbank zu interagieren, indem der direkte Datenbankzugang und die SQL-Abfragen von der Hauptanwendungslogik abstrahiert werden.

✨ Lösung prüfen und üben

Implementieren von nicht-datenbankabhängigen Hilfsfunktionen

Als letztes implementieren Sie Hilfsfunktionen, die nicht mit der Datenbank interagieren. Dazu gehören die Generierung von Zufallstoken für verkürzte URLs und die Validierung von URLs.

Fügen Sie im Ordner utils.py folgenden Python-Code hinzu:

def random_token(size: int = 6) -> str:
    """
    Generiert einen Zufallscode mit 6 Zeichen. Verwenden Sie den size-Argument,
    um die Größe des Tokens zu ändern.
    Gibt ein gültiges Token der gewünschten Größe zurück.
    *Standard ist 6 Zeichen
    """
    BASE_LIST = string.digits + string.ascii_letters

    token = ''.join((random.choice(BASE_LIST)) for char in range(size))
    return token


def url_check(url: str) -> bool:
    """
    Erwartet einen String als Argument.
    Gibt True zurück, wenn die URL gültig ist, andernfalls False.
    Für detaillierte Dokumentation siehe urlparse.
    """
    try:
        result = urlparse(url)
        if all([result.scheme, result.netloc]):
            return True
        else:
            return False
    except:
        return False
  • Die random_token-Funktion generiert einen Zufallscode, der als Token für die Erstellung verkürzter URLs dient. Standardmäßig erstellt es ein Token mit 6 Zeichen, kann jedoch mit dem size-Argument angepasst werden.
    • Sie verwendet eine Kombination aus Ziffern (string.digits) und Buchstaben (string.ascii_letters) als Basisliste für die Token-Erzeugung.
    • Das Token wird erzeugt, indem aus der BASE_LIST für die Anzahl von Zeichen, die durch den size-Parameter angegeben ist, zufällig ausgewählte Zeichen kombiniert werden. Dies geschieht mit einer List Comprehension und random.choice(), die ein zufälliges Element aus der angegebenen Sequenz auswählt.
    • Das generierte Token wird als String zurückgegeben. Dieses Token kann als Identifikator für die verkürzte URL verwendet werden.
  • Die url_check-Funktion validiert eine gegebene URL, um sicherzustellen, dass sie im richtigen Format vorliegt.
    • Sie verwendet die urlparse-Funktion aus dem urllib.parse-Modul, um die gegebene URL in Komponenten zu zerlegen.
    • Die Funktion überprüft, ob die URL sowohl ein Schema (wie http, https) als auch einen Netzwerkort (Netzwerkadresse, z.B. www.example.com) hat. Beide sind essentielle Komponenten für die Gültigkeit einer URL.
    • Wenn beide Komponenten vorhanden sind, gibt die Funktion True zurück, was bedeutet, dass die URL gültig ist. Wenn einer der beiden fehlt oder wenn während der Parsing ein Fehler auftritt (z.B. wenn die Eingabe kein String ist), gibt die Funktion False zurück.
    • Diese Validierung ist wichtig, um sicherzustellen, dass nur gültige URLs von der Anwendung verarbeitet und gespeichert werden.

Diese Hilfsfunktionen sind für den URL-Verkürzungsservice unerlässlich und bieten essentielle Funktionen für die Generierung eindeutiger Identifikatoren für verkürzte URLs und sicherstellen, dass das System nur gültige URLs akzeptiert.

✨ Lösung prüfen und üben

Initialisierung und Implementierung der Index-Route

Schließlich bauen wir den Kern unseres URL-Verkürzungsservice - die Flask-Anwendung.

Beginnen Sie mit der Einrichtung der Index-Route. Diese Route wird die Hauptseite anzeigen und sowohl GET- als auch POST-Anfragen verarbeiten. Bei einer GET-Anfrage zeigt sie alle verkürzten URLs an. Bei einer POST-Anfrage nimmt sie eine neue URL entgegen, um sie zu verkürzen, generiert ein einzigartiges Token und speichert es in der Datenbank.

Fügen Sie im Ordner app.py folgenden Python-Code hinzu:

from flask import Flask, request, redirect, render_template, make_response

from utils import get_db_connection, list_data, random_token, update_counters, url_check


app = Flask(__name__)


@app.route('/', methods=['GET', 'POST'])
def index():
    with get_db_connection() as conn, conn.cursor() as cursor:
        ## Hole alle Daten, um sie auf der Indexseite anzuzeigen
        cursor.execute("SELECT * FROM WEB_URL;")
        result_all_fetch = cursor.fetchall()

        if request.method == 'POST':
            og_url = request.form.get('url_input')
            custom_suff = request.form.get('url_custom', '')
            tag_url = request.form.get('url_tag', '')

            token_string = random_token() if not custom_suff else custom_suff

            if og_url and url_check(og_url):
                cursor.execute(
                    "SELECT S_URL FROM WEB_URL WHERE S_URL = %s FOR UPDATE", (token_string,))
                if cursor.fetchone() is None:
                    cursor.execute(
                        "INSERT INTO WEB_URL(URL, S_URL, TAG) VALUES(%s, %s, %s)", (og_url, token_string, tag_url))
                    conn.commit()
                    return render_template('index.html', shorty_url=f"{shorty_host}{token_string}")
                else:
                    error = "Der benutzerdefinierte Suffix existiert bereits. Bitte verwenden Sie einen anderen Suffix oder lassen Sie es leer, um einen zufälligen zu erhalten."
            else:
                error = "Ungültige URL angegeben. Bitte geben Sie eine gültige URL ein."

            return render_template('index.html', table=result_all_fetch, host=shorty_host, error=error)

        return render_template('index.html', table=result_all_fetch, host=shorty_host)

Die index-Funktion in app.py setzt die Kernfunktionalität des URL-Verkürzungsservices mit Flask, einem mikro Web-Framework, das in Python geschrieben ist, ein. Diese Funktion definiert, wie die Index-Route (/) der Anwendung verhält und wie sie sowohl GET- als auch POST-Anfragen verarbeitet. Hier ist eine detaillierte Erklärung des Codes:

Flask-Einrichtung

  • Die Flask-Anwendung wird mit app = Flask(__name__) initialisiert.
  • Der @app.route('/', methods=['GET', 'POST'])-Decorator gibt an, dass die index-Funktion Anfragen an die Wurzel-URL (/) verarbeitet und sowohl GET- als auch POST-Methoden akzeptiert.

Behandlung von GET-Anfragen

  • Wenn die Funktion eine GET-Anfrage erhält, verbindet sie sich mit der Datenbank mithilfe der get_db_connection()-Hilfsfunktion und holt alle Datensätze aus der WEB_URL-Tabelle. Dies ist, um alle verkürzten URLs auf der Indexseite anzuzeigen.
  • Die abgerufenen Datensätze werden zusammen mit der Host-URL (shorty_host) an die render_template-Funktion übergeben, um das index.html-Template zu rendern. Dieses Template enthält wahrscheinlich eine Tabelle oder Liste, um jede verkürzte URL und ihre Details anzuzeigen.

Behandlung von POST-Anfragen

  • Für POST-Anfragen, die typischerweise von einem Formular auf der Indexseite gesendet werden, extrahiert die Funktion die ursprüngliche URL (og_url), einen optionalen benutzerdefinierten Suffix (custom_suff) und einen optionalen Tag (tag_url) aus den Formulardaten.
  • Anschließend generiert es ein Zufallstoken für die verkürzte URL mit random_token(), es sei denn, ein benutzerdefinierter Suffix wird angegeben. Dieses Token (oder benutzerdefinierter Suffix) dient als einzigartiger Bezeichner für die verkürzte URL.
  • Bevor es fortfährt, validiert die Funktion die ursprüngliche URL mit url_check(og_url). Wenn die URL gültig ist und das Token/Suffix einzigartig ist (nicht bereits in der Datenbank), wird ein neuer Datensatz in die WEB_URL-Tabelle eingefügt, mit der ursprünglichen URL, dem Token/Suffix als verkürzte URL und dem Tag.
  • Wenn die Operation erfolgreich ist, rendert die Funktion das index.html-Template erneut, wobei die neu verkürzte URL (shorty_url) zusammen mit allen vorhandenen Datensätzen angezeigt wird.
  • Wenn das Token/Suffix bereits in der Datenbank existiert oder die ursprüngliche URL ungültig ist, wird eine Fehlermeldung festgelegt, und das index.html-Template wird mit der Fehlermeldung und den vorhandenen Datensätzen gerendert.

Fehlerbehandlung und Template-Rendering

  • Die render_template-Funktion wird häufig verwendet, um das index.html-Template zu rendern, wobei verschiedene Parameter wie die Liste aller Datensätze (table), die Basis-Host-URL für die verkürzten Links (host), die neu verkürzte URL (shorty_url) und alle Fehlermeldungen (error) übergeben werden. Diese Funktion erleichtert das dynamische Inhaltsrendering in Flask, indem Python-Variablen in HTML-Templates interpoliert werden.

Diese Flask-Anwendung fungiert als Backend für den URL-Verkürzungsservice, indem sie die Datenbankinteraktionen, die URL-Validierung und die Token-Generierung behandelt, und gleichzeitig dynamische Webseiten basierend auf Benutzerinteraktionen und Datenbankinhalten generiert.

✨ Lösung prüfen und üben

Implementieren der Umleitungsroute und der Analyse-Route

Umleitungsroute

Als nächstes erstellen Sie eine Route, um die Umleitung von einer verkürzten URL zur ursprünglichen URL zu behandeln. Diese Route erfasst jede verkürzte URL, sucht sie in der Datenbank nach und leitet den Benutzer zur ursprünglichen URL um.

Fügen Sie folgenden Code zu app.py hinzu:

@app.route('/<short_url>')
def reroute(short_url):
    with get_db_connection() as conn, conn.cursor() as cursor:
        platform = request.user_agent.platform or 'other'
        browser = request.user_agent.browser or 'other'
        browser_dict = {'firefox': 0, 'chrome': 0,'safari': 0, 'other': 0}
        platform_dict = {'windows': 0, 'iphone': 0,
                         'android': 0, 'linux': 0,'macos': 0, 'other': 0}

        ## Inkrementieren der Browser- und Plattformzähler
        browser_dict[browser] = browser_dict.get(browser, 0) + 1
        platform_dict[platform] = platform_dict.get(platform, 0) + 1

        cursor.execute(
            "SELECT URL FROM WEB_URL WHERE S_URL = %s;", (short_url,))
        try:
            new_url = cursor.fetchone()[0]
            update_counters(cursor, short_url, browser_dict, platform_dict)
            conn.commit()
            return redirect(new_url)
        except Exception:
            return render_template('404.html'), 404
  • Der @app.route('/<short_url>')-Decorator erstellt eine dynamische Route, die mit jedem Pfadsegment übereinstimmt, das der Wurzel-URL folgt. Dieses Segment (short_url) wird als Argument an die reroute-Funktion übergeben.
  • Innerhalb der Funktion wird eine Datenbankverbindung hergestellt und Dictionaries initialisiert, um den Browser und die Plattform zu verfolgen, von der die Anfrage stammt. Flask's request.user_agent wird verwendet, um den Browser und die Plattform zu bestimmen.
  • Anschließend wird eine SQL-Abfrage ausgeführt, um die ursprüngliche URL zu finden, die der angegebenen short_url zugeordnet ist. Wenn gefunden, werden die Zähler für den Browser und die Plattform in der Datenbank mithilfe der update_counters-Funktion aktualisiert.
  • Nachdem die Änderungen an der Datenbank committet wurden, verwendet die Funktion Flask's redirect-Funktion, um den Benutzer zur ursprünglichen URL zu senden.
  • Wenn die short_url in der Datenbank nicht gefunden wird oder ein anderer Fehler auftritt, rendert die Funktion eine 404-Fehlerseite mit render_template('404.html').

Analyse-Route

Erstellen Sie eine Analyse-Route, die detaillierte Informationen zu einer bestimmten verkürzten URL anzeigt, wie oft sie abgerufen wurde und von welchen Plattformen und Browsern.

Fügen Sie folgenden Code zu app.py hinzu:

@app.route('/analytics/<short_url>')
def analytics(short_url):
    info_fetch, counter_fetch, browser_fetch, platform_fetch = list_data(
        short_url)
    return render_template("data.html", host=shorty_host, info=info_fetch, counter=counter_fetch, browser=browser_fetch, platform=platform_fetch)
  • Der @app.route('/analytics/<short_url>')-Decorator definiert eine Route für den Zugang zu Analysen zu einer bestimmten verkürzten URL. Die short_url wird aus dem URL-Pfad erfasst und an die analytics-Funktion übergeben.
  • Die Funktion ruft list_data(short_url) auf, die die Datenbank abfragt, um Informationen über die verkürzte URL zu erhalten, einschließlich der Anzahl der Aufrufe und der Verteilung der Zugriffe über verschiedene Browser und Plattformen.
  • Die abgerufenen Daten (info_fetch, counter_fetch, browser_fetch, platform_fetch) werden dann zusammen mit der Host-URL (shorty_host) an die render_template-Funktion übergeben, um das data.html-Template zu rendern. Dieses Template stellt die Analyse-Daten wahrscheinlich in einem benutzerfreundlichen Format wie Tabellen oder Diagrammen dar.

Diese Routen erweitern die Funktionalität des URL-Verkürzungsservices, sodass er nicht nur Benutzer von verkürzten URLs zu ihren ursprünglichen Zielen umleiten kann, sondern auch Aufschluss darüber gibt, wie diese verkürzten URLs genutzt werden, einschließlich der Zugangszählungen und der Arten von Geräten und Browsern, von denen die Links abgerufen werden. Diese Informationen können wertvoll sein, um die Reichweite und den Einfluss von geteilten URLs zu verstehen.

✨ Lösung prüfen und üben

Implementieren der Suchroute und Ausführen der Anwendung

Suchroute

Setzen Sie eine Suchroute auf, um es Benutzern zu ermöglichen, verkürzte URLs nach Tags zu finden. Diese Route behandelt sowohl GET- als auch POST-Anfragen und zeigt jeweils ein Suchformular an oder verarbeitet Suchanfragen.

Fügen Sie folgenden Code zu app.py hinzu:

@app.route('/search', methods=['GET', 'POST'])
def search():
    s_tag = request.form.get('search_url', '')
    if not s_tag:
        return render_template('index.html', error="Bitte geben Sie einen Suchbegriff ein.")

    with get_db_connection() as conn, conn.cursor() as cursor:
        cursor.execute("SELECT * FROM WEB_URL WHERE TAG = %s", (s_tag,))
        search_tag_fetch = cursor.fetchall()
        return render_template('search.html', host=shorty_host, search_tag=s_tag, table=search_tag_fetch)
  • Der @app.route('/search', methods=['GET', 'POST'])-Decorator setzt die Route bei /search auf und behandelt sowohl GET- als auch POST-Anfragen. Während die GET-Anfrage möglicherweise verwendet werden kann, um ein Suchformular anzuzeigen, verarbeitet die POST-Anfrage die vom Benutzer übermittelten Formulardaten.
  • Innerhalb der search-Funktion versucht request.form.get('search_url', ''), den Suchbegriff aus den übermittelten Formulardaten zu extrahieren. Der zweite Parameter ('') ist der Standardwert, wenn 'search_url' nicht gefunden wird, was effektiv dazu führt, dass der Suchbegriff in solchen Fällen eine leere Zeichenkette ist.
  • Wenn kein Suchbegriff angegeben wird (not s_tag), leitet die Funktion den Benutzer zur Indexseite mit einer Fehlermeldung, die angibt, dass ein Suchbegriff erforderlich ist.
  • Wenn ein Suchbegriff angegeben wird, verbindet die Funktion sich mit der Datenbank und führt eine SQL-Abfrage aus, um alle Datensätze in der WEB_URL-Tabelle zu finden, in denen die TAG-Spalte mit dem angegebenen Suchbegriff übereinstimmt. Dies ermöglicht es Benutzern, alle verkürzten URLs zu finden, die mit einem bestimmten Tag assoziiert sind.
  • Die Ergebnisse dieser Abfrage (search_tag_fetch) werden dann zusammen mit der Host-URL (shorty_host) und dem Suchbegriff (s_tag) an die render_template-Funktion übergeben, um das search.html-Template zu rendern. Dieses Template zeigt die Ergebnisse wahrscheinlich in einer Liste oder Tabelle an, sodass Benutzer alle übereinstimmenden Datensätze sehen und möglicherweise interagieren können (z.B. die ursprünglichen URLs besuchen, Analysen anzeigen).

Ausführen der Anwendung

Schließlich fügen Sie den Code hinzu, um Ihre Flask-Anwendung auszuführen. Dies umfasst das Festlegen des Hosts und Ports, auf dem die Anwendung lauscht, sowie die Angabe von Umgebungsvariablen.

Fügen Sie folgenden Code am Ende von app.py hinzu:

shorty_host = "https://****.labex.io/"

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8080)

Hinweis: Sie sollten die URL in shorty_host durch die URL der aktuellen Umgebung ersetzen. Sie können sie finden, indem Sie zur Registerkarte Web 8080 wechseln, und die URL sollte mit / enden.

Web 8080 tab URL

Jetzt können Sie das Projekt mit dem folgenden Befehl ausführen:

python app.py

Wechseln Sie zur Registerkarte "Web 8080" und laden Sie die Webseite neu, um die folgenden Effekte zu sehen.

Konvertieren Sie die URL mit/ohne benutzerdefinierten Suffix, Suchen Sie URLs nach Tag, Greifen Sie auf den Link zu:

Zeigen Sie Informationen über das Betriebssystem und die Plattform an, die zum Zugang zum Link verwendet wurde:

✨ Lösung prüfen und üben

Zusammenfassung

Herzlichen Glückwunsch zum Abschluss des URL-Verkürzungsprojekts! Dieses Tool vereinfacht das Teilen langer URLs, indem es kürzere, leichter verwaltbare Links erstellt. Denken Sie jedoch an einige wichtige Aspekte:

  1. Länge der Basis-URL: Wenn die Basis-URL des Verkürzers selbst lang ist, können die resultierenden verkürzten URLs nicht so kurz sein, wie erwartet (wie im Projekt). Die Gesamtlänge der verkürzten URL umfasst die Basis-URL, was die Effizienz des Verkürzers einschränken kann. Um die kürzesten URLs zu erhalten, sollten Sie für Ihren Service eine kürzere Basis-URL oder Domainname verwenden.

  2. Einschränkungen bei der Website-Einbettung: Sie können Probleme wie "Refused to display 'https://scholar.google.com/' in a frame because it set 'X-Frame-Options' to'sameorigin'." erhalten. Dieser Fehler tritt auf, weil einige Websites den HTTP-Header X-Frame-Options verwenden, um zu verhindern, dass ihr Inhalt in Iframes auf anderen Domains angezeigt wird, was die Sicherheit gegen "Clickjacking"-Angriffe erhöht. Wenn eine Website diesen Header auf sameorigin setzt, wird die Einbettung auf Iframes beschränkt, die denselben Ursprung teilen. Dies ist keine Beschränkung des URL-Verkürzers, sondern eine Sicherheitsmaßnahme, die von der Zielwebsite implementiert wird. Für eine nahtlose Umleitung ist es am besten, die verkürzten URLs als direkte Links zu verwenden, anstatt sie in Iframes einzubetten.

Diese Überlegungen verdeutlichen das Gleichgewicht zwischen Bequemlichkeit und Sicherheit in der Webentwicklung und die Wichtigkeit der Benutzerbewusstsein für die optimale Nutzung des Tools.