Создание сервиса сокращения URL-адресов с использованием Flask и MySQL

HTMLHTMLAdvanced
Практиковаться сейчас

💡 Этот учебник переведен с английского с помощью ИИ. Чтобы просмотреть оригинал, вы можете перейти на английский оригинал

Введение

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

Проект основан на https://github.com/highoncarbs/shorty, который изначально лицензирован под лицензией MIT.

👀 Предпросмотр

Преобразовать ссылку с/без пользовательского суффикса, Поиск ссылок по тегу, Перейти по ссылке:

Просмотреть информацию об операционной системе и платформе, использованной для доступа по ссылке:

🎯 Задачи

В этом проекте вы научитесь:

  • Как подключить приложение Flask к базе данных MySQL
  • Как создавать и управлять схемой базы данных MySQL для хранения информации о ссылках
  • Как реализовать фронтенд-страницы с использованием HTML и CSS для взаимодействия с бэкендом
  • Как обрабатывать данные форм и запросы в Flask для создания коротких ссылок
  • Как разработать функциональность для перенаправления пользователей из короткой ссылки на исходную ссылку
  • Как создать простую функцию аналитики для отслеживания использования ссылок, включая количество кликов и базовую информацию о браузере/платформе
  • Как спроектировать удобный для пользователя обработчик ошибок и настраиваемую страницу 404 для улучшения пользовательского опыта

🏆 Достижения

После завершения этого проекта вы сможете:

  • Выполнять базовые операции с MySQL, включая создание базы данных и таблиц, вставку данных и запросы
  • Разбираться в основах Flask, включая маршрутизацию, обработку запросов и рендеринг шаблонов
  • Работать с HTML-формами и обрабатывать данные в приложении Flask
  • Применять основные принципы фронтенд-дизайна и использовать CSS для создания визуально привлекательного веб-интерфейса
  • Реализовать простую аналитику для сбора и отображения данных о использовании ссылок
  • Реализовать лучшие практики обработки ошибок в веб-приложениях для повышения надежности и качества пользовательского опыта

Настройка окружения проекта

Во - первых, нам нужно настроить окружение проекта в терминале. Это включает в себя установку необходимого Python - пакета для подключения к MySQL и запуск службы MySQL. Когда служба запущена, мы создадим базу данных и таблицу для хранения наших ссылок.

Установить PyMySQL:

pip install PyMySQL==1.1.0

Запустить службу MySQL и войти в MySQL - консоль:

sudo service mysql start
mysql -u root

Внутри MySQL - консоли выполните следующие команды для создания базы данных и таблицы:

Создать базу данных:

CREATE DATABASE IF NOT EXISTS SHORTY;
USE SHORTY;

Создать таблицу:

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)
);

Этот SQL - запрос создает таблицу под названием WEB_URL в базе данных SHORTY, предназначенную для хранения информации о сокращенных ссылках и некоторой связанной аналитики.

  • CREATE TABLE IF NOT EXISTS WEB_URL: Эта команда создает новую таблицу с именем WEB_URL только в том случае, если она еще не существует в базе данных. Это помогает избежать ошибок при повторном запуске скрипта.
  • ID INT AUTO_INCREMENT: Этот столбец назначен в качестве первичного ключа таблицы и настроен на автоматическое увеличение с каждым новым записью. Это означает, что каждый раз, когда добавляется новая запись, MySQL автоматически назначает ей уникальный ID, увеличивая его на 1 от предыдущего.
  • URL VARCHAR(512): Этот столбец хранит исходные ссылки, которые сокращаются. Тип данных VARCHAR(512) означает, что он может хранить строки переменной длины, до 512 символов.
  • S_URL VARCHAR(80): Это столбец для строки сокращенной ссылки, с максимальной длиной 80 символов.
  • TAG VARCHAR(80): Этот столбец предназначен для хранения тегов, связанных с ссылками, для классификации или поиска, с максимальной длиной 80 символов.
  • COUNTER INT DEFAULT 0: Этот целочисленный столбец, вероятно, используется для отслеживания количества раз, которое сокращенная ссылка была посещена. Он по умолчанию равен 0 при создании новой записи.
    Следующие несколько столбцов предназначены для хранения аналитических данных по сокращенным ссылкам:
  • CHROME, FIREFOX, SAFARI, OTHER_BROWSER: Эти столбцы используются для отслеживания количества посещений с разных веб - браузеров. Каждый из них является целочисленным столбцом, который по умолчанию равен 0.
  • ANDROID, IOS, WINDOWS, LINUX, MAC, OTHER_PLATFORM: Подобно столбцам для браузеров, эти столбцы предназначены для отслеживания посещений с разных операционных систем/платформ, и каждый столбец по умолчанию равен 0.
  • PRIMARY KEY (ID): Эта часть запроса задает, что столбец ID является первичным ключом таблицы. Первичный ключ - это уникальный идентификатор каждой записи в таблице, что гарантирует, что у двух записей не будет одинаковых ID.

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

Для выхода из MySQL - консоли можно выполнить следующую команду:

EXIT;

Создать шаблон главной страницы

Главная страница - это то место, где пользователи будут взаимодействовать с сервисом сокращения ссылок. Мы будем использовать HTML и шаблонизатор Flask для создания динамического контента.

В templates/index.html добавьте следующий HTML - код:

<!doctype html>
<html>
  <head>
    <title>Shorty</title>
    <!-- Добавить локальное SVG - изображение при размещении. -->
    <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>

Вот обзор основных компонентов этого шаблона:

  • Google Material Icons: Теги <link> импортируют библиотеку Google Material Icons, позволяя использовать предопределенные иконки для более привлекательного пользовательского интерфейса.
  • Clipboard.js: Теги <script> включают библиотеку Clipboard.js, популярную JavaScript - библиотеку для копирования содержимого в буфер обмена. Это может быть полезно для сервиса сокращения ссылок, позволяя пользователям легко копировать сокращенные ссылки.
  • Стили: Шаблон ссылается на несколько CSS - файлов для стилизации:
    • skeleton.css: Легкий CSS - фреймворк, который обеспечивает базовую стилизацию и адаптивную систему сетки.
    • normalize.css: Сбрасывает стандартные стили браузера для обеспечения一致ной стилизации на разных браузерах.
    • main.css: Содержит пользовательские стили, специфичные для сервиса "Shorty".
  • Google Fonts: Еще один тег <link> импортирует семейство шрифтов "Roboto" из Google Fonts, обеспечивая различные веса шрифтов для дизайна типографики.
  • Внутри <body> используется div с классом container main_header для создания заголовочной секции, которая включает:
    • Заголовок (<h3>), содержащий ссылку (<a>), которая перенаправляет на главную страницу, с помощью функции url_for Flask, динамически генерирующей URL для маршрута 'index'.
    • Абзац (<p>), описывающий сервис как "A very simple URL shortening service."
✨ Проверить решение и практиковаться

Реализовать сокращение ссылок и поиск по тегам

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

Сокращение ссылок

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

Добавьте следующий код в templates/index.html:

<!-- 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 -->

Первый блок кода добавляет форму, предназначенную для поиска ссылок по их связанным тегам:

  • search_url_block: Этот контейнер содержит поисковую форму, делая ее отдельным разделом на странице для лучшей организации и стилизации.
  • <form>: Определяет форму, которая отправляет POST - запрос на конечную точку /search, когда кнопка поиска нажата. Эта форма имеет имя search_tag_block для идентификации.
  • <input>: Текстовое поле ввода, где пользователи могут ввести теги, по которым они хотят искать. Атрибут placeholder дает подсказку пользователю о назначении поля.
  • <button>: Кнопка отправки, которая инициирует отправку формы. Класс button-primary, вероятно, добавляет специфическую стилизацию, определенную в CSS.

Поиск по тегам

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

Добавьте следующий код в templates/index.html:

<!-- 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 -->

Второй блок кода представляет форму для пользователей, чтобы сократить ссылки, с дополнительными полями для настройки:

  • Весь форма заключается в элемент <form> с method="post" и неуказанным атрибутом action. Это означает, что данные формы будут отправлены по POST - запросу на текущий URL, когда кнопка "Generate" нажата.
  • Внутри формы <div> с классом row вероятно помогает с макетом и выравниванием, обеспечивая правильную организацию полей ввода и кнопки.
  • Три элемента <input type="text"> предназначены для разных целей:
    • Первое поле ввода позволяет пользователям ввести исходную ссылку, которую они хотят сократить.
    • Второе позволяет указать необязательный пользовательский суффикс для сокращенной ссылки, позволяя пользователям персонализировать свои короткие ссылки.
    • Третье поле предназначено для тегов, позволяя пользователям классифицировать или добавлять описательные метки к своим сокращенным ссылкам для более удобного извлечения и управления.
  • <button> с классом button-primary и текстом "Generate" служит кнопкой отправки формы. Нажатие этой кнопки отправляет данные на сервер для создания сокращенной ссылки с предоставленной информацией.

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

✨ Проверить решение и практиковаться

Обработка ошибок и отображение сокращенных ссылок

В этом шаге мы сосредоточимся на улучшении пользовательского опыта путем обработки сообщений об ошибках и отображения сокращенных ссылок.

Обработка ошибок

Во - первых, мы добавим функциональность для отображения сообщений об ошибках пользователям. Это至关重要 для предоставления обратной связи, когда что - то идет не так, например, когда пользователь отправляет недействительную ссылку или тег, который не существует. Корректная обработка ошибок делает приложение более устойчивым и удобным для пользователя.

Добавьте следующий код в templates/index.html:

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

Этот блок предназначен для предоставления обратной связи пользователю, если во время процесса сокращения ссылки произошла ошибка:

  • {% if error!= '' %}: Это условное выражение, использующее синтаксис шаблонизатора Flask, Jinja2. Он проверяет, не пуста ли переменная error. Переменная error ожидается быть переданной из Flask - бэкенда в шаблон. Если есть сообщение об ошибке, условие оценивается как True.
  • <p class="error_disp">{{error}}</p>: Когда условие истинно, этот элемент абзаца отображается, отображающий сообщение об ошибке, содержащееся в переменной error. Класс error_disp вероятно используется для стилизации сообщения об ошибке, чтобы сделать его визуально выделенным и привлечь внимание пользователя.
  • {% endif %}: Закрывает условный блок. Если переменная error пуста, ничего из этого блока не отображается на странице.

Отображение сокращенных ссылок

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

Добавьте следующий код в templates/index.html:

<!-- 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 -->

Этот блок отображается, когда ссылка успешно сокращена, и предоставляет пользователям способ легко скопировать сокращенную ссылку:

  • {% if shorty_url %}: Еще одно условное выражение, которое проверяет, существует ли переменная shorty_url и не является пустой. Эта переменная должна содержать сокращенную ссылку, сгенерированную сервисом.
  • <p class="gen_url">: Этот абзац отображает сообщение, указывающее на сокращенную ссылку. Внутри него <a id="short-url" href="{{shorty_url}}">{{shorty_url}}</a> создает гиперссылку, где сокращенная ссылка является как текст ссылки, так и значением атрибута href, позволяя пользователям нажать на нее напрямую.
  • <button>: Эта кнопка предназначена для копирования сокращенной ссылки в буфер обмена для простой передачи. Она использует классы для стилизации (button-primary) и функциональности (copy-btn). Атрибут data-clipboard-action задает действие для выполнения (копирование), а data-clipboard-target указывает на элемент - цель для копирования (ссылку на сокращенную ссылку). Эта настройка предполагает интеграцию Clipboard.js (или аналогичной библиотеки) для обработки функции копирования.
  • {% endif %}: Закрывает условный блок для отображения сокращенной ссылки и кнопки копирования. Если shorty_url не задан или пуста, этот раздел не будет отображаться.

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

✨ Проверить решение и практиковаться

Перечисление и управление сокращенными ссылками

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

Добавьте следующий код в templates/index.html:

        <!-- 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>

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

  • Блок начинается с условного {% if not error %}, чтобы убедиться, что список отображается только в отсутствие ошибок. Это помогает поддерживать чистый пользовательский интерфейс, особенно когда нужно отображать сообщения об ошибках.
  • Еще одно условное {% if not shorty_url %} проверяет, не был ли только что сгенерирован новый сокращенный URL. Эта проверка может использоваться для предотвращения мгновенного отображения списка после сокращения новой ссылки, сосредоточив внимание пользователя на недавно созданной сокращенной ссылке.
  • Стиль overflow-x:auto; применяется к div, чтобы обеспечить горизонтальную прокрутку таблицы на меньших экранах, улучшая отзывчивость и удобство использования.
  • Элемент table имеет структуру с разделом thead, определяющим заголовки столбцов для "Original URL", "Short URL", "Clicks" и "Info". Этот макет помогает пользователям понять представленные данные.
  • Раздел tbody динамически заполняется данными с использованием цикла Flask/Jinja2: {% for url in table %}. Этот цикл перебирает коллекцию URL (table), переданную из Flask - бэкенда, отображая данные каждой ссылки в новой строке таблицы (<tr>).
  • В каждой строке исходная ссылка отображается в ячейке (<td>) с некоторым отступом для эстетики. Сокращенная ссылка представлена в виде кликабельной ссылки (<a>), составленной путем добавления сокращенного пути (url[2]) к имени хоста (host), который также должен быть передан из бэкенда.
  • Столбец "Clicks" показывает количество раз, которое сокращенная ссылка была посещена, выровненный по центру для лучшей читаемости.
  • Столбец "Info" содержит ссылку на страницу аналитики для каждой сокращенной ссылки. Эта ссылка генерируется с использованием функции url_for Flask, динамически создавая URL для маршрута аналитики с сокращенной ссылкой в качестве параметра. Иконка (<i class="material-icons">info_outline</i>) из набора Google Material Icons используется для визуального представления ссылки на аналитику.
  • Тег {% endfor %} закрывает цикл, обеспечивая создание строки для каждой ссылки в коллекции table.
  • Условные блоки закрываются тегами {% endif %}.
  • Внизу тег <script> инициализирует Clipboard.js для класса .copy-btn, который, возможно, был использован в предыдущих разделах (например, для копирования сокращенной ссылки). Этот скрипт обеспечивает, что любой элемент с классом copy-btn будет иметь функцию копирования в буфер обмена, используя библиотеку Clipboard.js.

Этот последний шаг завершает функциональность сервиса сокращения ссылок "Shorty", предоставляя пользователям полный обзор своих сокращенных ссылок, что делает их управление и анализ ссылками проще. Интеграция динамического рендеринга данных с Flask/Jinja2, сочетающаяся с тщательным дизайном интерфейса, обеспечивает удобный для пользователя опыт.

✨ Проверить решение и практиковаться

Создать шаблон страницы поиска

Чтобы позволить пользователям искать ссылки по тегам, нам понадобится страница поиска.

В templates/search.html добавьте следующий HTML - код:

<!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>

Этот код создает шаблон для страницы результатов поиска в сервисе сокращения ссылок "Shorty". Эта страница предназначена для отображения результатов поиска пользователя по ссылкам по тегам. Вот подробный разбор шаблона:

  • Внутри <body> секция заголовка (<div class="container main_header">) отображает аналогичную секцию на главной странице, обеспечивая единый стиль и ощущение. Она включает название сервиса ("Shorty") в виде кликабельной ссылки, которая перенаправляет на главную страницу ({{url_for('index')}}), и краткое описание сервиса.
  • Секция <div class="container search_header"> представляет область результатов поиска, начиная с заголовка (<h4>), который динамически отображает тег, использованный для поиска ({{ search_tag }}).
  • Результаты отображаются в таблице внутри div, стилизованного для горизонтальной прокрутки (overflow-x:auto;), обеспечивая доступность на устройствах с меньшими экранами.
  • Структура таблицы (<table>) состоит из секций заголовка (<thead>) и тела (<tbody>). Заголовок определяет столбцы для "Original URL", "Short URL", "Clicks" и "Info", аналогично списку, отображаемому на главной странице.
  • Тело таблицы динамически заполняется с использованием цикла ({% for url in table %}), перебирая коллекцию URL (table), переданную из Flask - бэкенда. Каждая итерация создает новую строку (<tr>) в таблице для каждой ссылки:
    • Исходная ссылка отображается с некоторым отступом для лучшей читаемости.
    • Сокращенная ссылка представлена в виде кликабельной ссылки, составленной путем добавления сокращенного пути к имени хоста, оба из которых динамически вставляются с использованием синтаксиса шаблонизатора Flask.
    • Столбец "Clicks" показывает, сколько раз сокращенная ссылка была посещена, с текстом выровненным по центру для ясности.
    • Столбец "Info" предоставляет ссылку на подробную аналитику для каждой ссылки, используя функцию url_for Flask для динамического генерации URL и иконку (<i class="material-icons">info_outline</i>) для визуального представления.

Этот шаблон результатов поиска улучшает сервис "Shorty", позволяя пользователям эффективно искать и управлять ссылками на основе тегов, обеспечивая беспрепятственный и интуитивный пользовательский опыт.一致ное использование стилей и элементов макета с главной страницы обеспечивает единый дизайн по всему приложению.

✨ Проверить решение и практиковаться

Создать шаблон страницы аналитики

Страница аналитики будет отображать подробную информацию о использовании сокращенной ссылки, включая количество кликов, статистику по браузерам и платформам.

В templates/data.html добавьте следующий HTML - код:

<!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>

Этот код включает информацию о количестве кликов, использовании браузеров и распределении по платформам. Вот разбор его структуры и компонентов:

  • div с классами container modal-content заключает аналитическую информацию, стилизованную как модальное окно или отдельный блок контента на странице.
  • div url_info представляет:
    • Заголовок <h4>, указывающий, что следующие данные относятся к аналитике для определенной сокращенной ссылки. Сокращенная ссылка отображается в виде кликабельной ссылки, составленной с использованием переменных host и info[1], где info[1] содержит сокращенный путь.
    • Абзац (<p>), показывающий исходную ссылку в виде кликабельной ссылки, обеспечивая доступ к исходному контенту.
  • Два отдельных раздела, browser_list и platform_list, каждый содержит таблицу, отображающую статистику использования для браузеров и платформ соответственно:
    • Раздел browser_list включает таблицу с заголовками для Chrome, Firefox, Safari и Другие браузеры. Раздел <tbody> отображает соответствующие статистики, которые извлекаются из массива переменной browser, переданного в шаблон.
    • Аналогично, раздел platform_list имеет таблицу для использования платформ, с заголовками для Android, iOS, Windows, Linux, Mac и Другие платформы. Статистика использования показывается в теле таблицы, взятая из массива переменной platform.
  • Таблицы используют <thead> для заголовков и <tbody> для фактических данных, обеспечивая семантический HTML и облегчая стилизацию и доступность.
  • Ячейки данных (<td>) внутри таблиц отображают соответствующие количества для каждого браузера и платформы, выровнены и стилизованы для лучшей читаемости.

Этот шаблон эффективно передает аналитические данные пользователю, предоставляя информацию о том, как сокращенная ссылка используется, включая браузеры и платформы, используемые аудиторией. Чистый макет, сочетающийся с четким разделением данных на отдельные секции, делает it easy для пользователей понять и интерпретировать производительность их ссылки.

✨ Проверить решение и практиковаться

Создать шаблон страницы 404

Настраиваемая страница 404 улучшает пользовательский опыт, предоставляя более полезное сообщение об ошибке, когда сокращенная ссылка не найдена.

В templates/404.html добавьте следующий HTML - код:

<!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>

Этот настраиваемый шаблон страницы 404 эффективно сообщает пользователям, что страница, которую они ищут, не существует, при этом поддерживая легкомысленный тон.

✨ Проверить решение и практиковаться

Создать веб - интерфейс

Далее мы создадим веб - интерфейс. Начнем с создания основного файла CSS для стилизации нашего приложения.

В static/main.css добавьте следующий CSS - код для стилизации HTML - элементов:

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;
}
/** Main Header */
.main_header {
  margin-bottom: 20px;
}
/* Search Block */
.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;
}
/* Gen URL block */

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

/* Table Display 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. Lost*/
.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;
}

В целом дизайн использует комбинацию цветов фона, цветов текста и отступов для создания чистого, современного интерфейса, который легко использовать. Использование скругления углов у различных элементов дает интерфейсу более мягкий, доступный вид, в то время как эффекты наведения мыши повышают интерактивность. Consistentное использование шрифта Roboto обеспечивает единый стиль по всему приложению.

✨ Проверить решение и практиковаться

Функции подключения к базе данных и операции с ней

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

Подключение к базе данных

Сначала вы настроите подключение к базе данных с использованием pymysql. Это至关重要 для взаимодействия вашего Flask-приложения с базой данных MySQL.

В utils.py добавьте следующий Python-код:

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:
    """Создает и возвращает новое подключение к базе данных."""
    return pymysql.connect(**db_config)
  • Библиотека pymysql используется для подключения к базе данных MySQL. Эта библиотека позволяет Python-приложениям взаимодействовать с базами данных MySQL с использованием простого API.
  • Словарь db_config содержит параметры подключения к базе данных, такие как хост, пользователь, пароль и имя базы данных. Эти параметры импортируются из отдельного модуля config,大概是出于更好的安全性和模块化考虑。Разделение настроек позволяет更容易进行调整,而无需修改主要的代码库。
  • Функция get_db_connection() создает и возвращает новое подключение к базе данных с использованием функции pymysql.connect(**db_config). Синтаксис **db_config используется для распаковки словаря в именованные аргументы.

Функции операций с базой данных

После установления подключения к базе данных следующим шагом является создание функций, которые выполняют операции с базой данных. Это включает перечисление данных для заданного сокращенного URL-адреса и обновление счетчиков на основе использования браузера и платформы.

В utils.py добавьте следующий Python-код:

def list_data(shorty_url: str) -> tuple:
    """
    Принимает short_url в качестве входных данных.
    Возвращает счетчик, браузер, количество обращений по платформам.
    """
    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:
    """Обновляет счетчики браузера и платформы в базе данных для заданного short_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))
  • Функция list_data(shorty_url) предназначена для извлечения различных частей информации из таблицы WEB_URL для заданного сокращенного URL-адреса (shorty_url). Она устанавливает соединение с базой данных и выполняет четыре SQL-запроса для извлечения исходного URL-адреса, связанного тега, счетчика доступов, информации о браузере и платформе. Каждый запрос выполняется отдельно, и результаты извлекаются и возвращаются.
  • Функция update_counters(cursor, short_url, browser_dict, platform_dict) обновляет счетчик доступов, информацию о браузере и платформе для заданного сокращенного URL-адреса в базе данных. Эта функция принимает курсор базы данных, сокращенный URL-адрес и два словаря, содержащих подсчеты для каждого браузера и платформы, в качестве аргументов. Она строит SQL-запрос UPDATE, чтобы увеличить счетчики для сокращенного URL-адреса на основе предоставленных данных. Функция предполагает, что информация о браузере и платформе была определена перед вызовом этой функции, и что эта информация передается в виде словарей (browser_dict и platform_dict), с ключами, соответствующими столбцам в таблице WEB_URL.

Это стандартная схема для веб-приложений, использующих Flask и MySQL, где определяются утилита-функции для общих операций с базой данных. Затем эти функции могут быть импортированы и использованы в приложении для взаимодействия с базой данных, выделяя непосредственный доступ к базе данных и SQL-запросы от основной логики приложения.

✨ Проверить решение и практиковаться

Реализация утилитарных функций, не связанных с базой данных

Наконец, реализуйте утилитарные функции, которые не взаимодействуют с базой данных. Это включает в себя генерацию случайных токенов для сокращенных URL-адресов и проверку валидности URL-адресов.

В utils.py добавьте следующий Python-код:

def random_token(size: int = 6) -> str:
    """
    Генерирует случайную строку длиной 6 символов, используя аргумент size
    для изменения размера токена.
    Возвращает валидный токен заданного размера,
    *по умолчанию размер 6 символов
    """
    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:
    """
    Ожидает строку в качестве аргумента.
    Возвращает True, если URL-адрес валиден, иначе False.
    Для более подробной документации ознакомьтесь с urlparse.
    """
    try:
        result = urlparse(url)
        if all([result.scheme, result.netloc]):
            return True
        else:
            return False
    except:
        return False
  • Функция random_token генерирует случайную строку, которая служит токеном для создания сокращенных URL-адресов. По умолчанию она создает токен длиной 6 символов, но его размер можно изменить с помощью аргумента size.
    • Она использует комбинацию цифр (string.digits) и букв (string.ascii_letters) в качестве базового списка для генерации токена.
    • Токен генерируется путем случайного выбора символов из BASE_LIST в количестве, указанном параметром size. Это делается с использованием списочного выражения и random.choice(), который выбирает случайный элемент из указанной последовательности.
    • Затем сгенерированный токен возвращается в виде строки. Этот токен может быть использован в качестве идентификатора сокращенного URL-адреса.
  • Функция url_check проверяет валидность заданного URL-адреса, чтобы убедиться, что он имеет правильный формат.
    • Она использует функцию urlparse из модуля urllib.parse для разбора заданного URL-адреса на компоненты.
    • Функция проверяет, содержит ли URL-адрес как схему (например, http, https), так и сетевой адрес (netloc, например, www.example.com). Оба эти компонента являются обязательными для того, чтобы URL-адрес считался валидным.
    • Если оба компонента присутствуют, функция возвращает True, что означает, что URL-адрес валиден. Если какой-либо из них отсутствует, или если во время разбора возникает исключение (например, если входные данные не являются строкой), функция возвращает False.
    • Эта проверка важна для обеспечения того, чтобы только валидные URL-адреса обрабатывались и хранились приложением.

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

✨ Проверить решение и практиковаться

Инициализация и реализация маршрута главной страницы

Наконец, мы построим ядро нашего сервиса сокращения URL-адресов - приложение Flask.

Начните с настройки маршрута главной страницы. Этот маршрут будет обслуживать главную страницу и обрабатывать как GET-, так и POST-запросы. При GET-запросе он отображает все сокращенные URL-адреса. При POST-запросе он принимает новый URL-адрес для сокращения, генерирует уникальный токен и сохраняет его в базу данных.

В app.py добавьте следующий Python-код:

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:
        ## Получить все данные для отображения на главной странице
        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 = "The custom suffix already exists. Please use another suffix or leave it blank for a random one."
            else:
                error = "Invalid URL provided. Please enter a valid URL."

            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)

Функция index в app.py настраивает основную функциональность сервиса сокращения URL-адресов с использованием Flask, микрофреймворка для веб-приложений, написанного на Python. Эта функция определяет, как маршрут главной страницы (/) приложения ведет себя и обрабатывает как GET-, так и POST-запросы. Вот подробное объяснение кода:

Настройка Flask

  • Приложение Flask инициализируется с помощью app = Flask(__name__).
  • Декоратор @app.route('/', methods=['GET', 'POST']) указывает, что функция index обрабатывает запросы к корневому URL (/) и принимает как GET-, так и POST-методы.

Обработка GET-запросов

  • Когда функция получает GET-запрос, она подключается к базе данных с использованием утилитарной функции get_db_connection() и извлекает все записи из таблицы WEB_URL. Это для отображения всех сокращенных URL-адресов на главной странице.
  • Извлеченные записи передаются в функцию render_template, вместе с URL-адресом хоста (shorty_host), для отображения шаблона index.html. Этот шаблон, вероятно, содержит таблицу или список для отображения каждого сокращенного URL-адреса и его деталей.

Обработка POST-запросов

  • Для POST-запросов, обычно отправляемых из формы на главной странице, функция извлекает исходный URL (og_url), необязательный пользовательский суффикс (custom_suff) и необязательный тег (tag_url) из данных формы.
  • Затем она генерирует случайный токен для сокращенного URL-адреса с использованием random_token(), если не предоставлен пользовательский суффикс. Этот токен (или пользовательский суффикс) служит уникальным идентификатором для сокращенного URL-адреса.
  • Перед выполнением функция проверяет валидность исходного URL-адреса с использованием url_check(og_url). Если URL-адрес валиден и токен/суффикс уникален (не существует в базе данных), новая запись вставляется в таблицу WEB_URL с исходным URL-адресом, токеном/суффиксом в качестве сокращенного URL-адреса и тегом.
  • Если операция прошла успешно, функция переотображает шаблон index.html, отображая новый сокращенный URL-адрес (shorty_url), вместе с всеми существующими записями.
  • Если токен/суффикс уже существует в базе данных или исходный URL-адрес невалиден, устанавливается сообщение об ошибке, и шаблон index.html отображается с сообщением об ошибке и существующими записями.

Обработка ошибок и рендеринг шаблонов

  • Функция render_template широко используется для отображения шаблона index.html, передав в него различные параметры, такие как список всех записей (table), базовый URL-адрес хоста для сокращенных ссылок (host), новый сокращенный URL-адрес (shorty_url) и любые сообщения об ошибке (error). Эта функция облегчает динамическое отображение содержимого в Flask путем вставки переменных Python в HTML-шаблоны.

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

✨ Проверить решение и практиковаться

Реализация маршрута перенаправления и маршрута аналитики

Маршрут перенаправления

Далее, создайте маршрут для обработки перенаправления от сокращенного URL-адреса к исходному URL-адресу. Этот маршрут ловит любой сокращенный URL-адрес, ищет его в базе данных и перенаправляет пользователя на исходный URL-адрес.

Добавьте следующий код в app.py:

@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}

        ## Увеличить счетчики браузера и платформы
        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
  • Декоратор @app.route('/<short_url>') создает динамический маршрут, который соответствует любому сегменту пути, следующему за корневым URL-адресом. Этот сегмент (short_url) передается в функцию reroute в качестве аргумента.
  • Внутри функции она устанавливает соединение с базой данных и инициализирует словари для отслеживания браузера и платформы, из которой пришел запрос. Используется request.user_agent Flask для определения браузера и платформы.
  • Затем она выполняет SQL-запрос, чтобы найти исходный URL-адрес, связанный с заданным short_url. Если найден, она обновляет счетчики для браузера и платформы в базе данных с использованием функции update_counters.
  • После внесения изменений в базу данных функция использует функцию redirect Flask для отправки пользователя на исходный URL-адрес.
  • Если short_url не найден в базе данных или возникает любое другое исключение, функция отображает страницу ошибки 404 с использованием render_template('404.html').

Маршрут аналитики

Создайте маршрут аналитики, который отображает подробную информацию о конкретном сокращенном URL-адресе, таких как количество раз, которое он был посещен, и с каких платформ и браузеров.

Добавьте следующий код в app.py:

@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)
  • Декоратор @app.route('/analytics/<short_url>') определяет маршрут для доступа к аналитике о конкретном сокращенном URL-адресе. short_url извлекается из пути URL-адреса и передается в функцию analytics.
  • Функция вызывает list_data(short_url), которая запрашивает базу данных для получения информации о сокращенном URL-адресе, включая количество раз, которое он был посещен, и распределение доступов по разным браузерам и платформам.
  • Затем полученные данные (info_fetch, counter_fetch, browser_fetch, platform_fetch) передаются в функцию render_template вместе с URL-адресом хоста (shorty_host) для отображения шаблона data.html. Этот шаблон, вероятно, представляет аналитические данные в удобочитаемом формате, таких как таблицы или диаграммы.

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

✨ Проверить решение и практиковаться

Реализация маршрута поиска и запуск приложения

Маршрут поиска

Настройте маршрут поиска, чтобы пользователи могли искать сокращенные URL-адреса по тегам. Этот маршрут обрабатывает как GET-, так и POST-запросы, отображает форму поиска и обрабатывает запросы поиска соответственно.

Добавьте следующий код в app.py:

@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="Please enter a search term.")

    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)
  • Декоратор @app.route('/search', methods=['GET', 'POST']) настраивает маршрут по адресу /search, обрабатывая как GET-, так и POST-запросы. Хотя GET-запрос может быть использован для отображения формы поиска, POST-запрос обрабатывает данные формы, отправленные пользователями.
  • Внутри функции search request.form.get('search_url', '') пытается извлечь термин поиска из отправленных данных формы. Второй параметр ('') является значением по умолчанию, если 'search_url' не найден, тем самым делающий термин поиска пустой строкой в таких случаях.
  • Если не предоставлен термин поиска (not s_tag), функция перенаправляет пользователя на главную страницу с сообщением об ошибке, указывающим на необходимость ввода термина поиска.
  • Если термин поиска предоставлен, функция подключается к базе данных и выполняет SQL-запрос, чтобы найти все записи в таблице WEB_URL, где столбец TAG соответствует предоставленному термину поиска. Это позволяет пользователям найти все сокращенные URL-адреса, связанные с определенным тегом.
  • Результаты этого запроса (search_tag_fetch) затем передаются в функцию render_template, вместе с URL-адресом хоста (shorty_host) и термином поиска (s_tag), для отображения шаблона search.html. Этот шаблон, вероятно, отображает результаты в виде списка или таблицы, позволяя пользователям увидеть все соответствующие записи и, возможно, взаимодействовать с ними (например, посетить исходные URL-адреса, просмотреть аналитику).

Запуск приложения

Наконец, добавьте код для запуска вашего приложения Flask. Это включает настройку хоста и порта, на котором приложение будет слушать, а также указание переменных окружения.

Добавьте следующий код в конец app.py:

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

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

Примечание: Вы должны заменить URL в shorty_host на URL текущей среды. Вы можете найти его, перейдя в вкладку Web 8080, и URL должен заканчиваться на /.

URL вкладки Web 8080

Теперь вы можете запустить проект с помощью следующей команды:

python app.py

Перейдите в вкладку "Web 8080" и обновите веб-страницу, чтобы увидеть следующие эффекты.

Преобразуйте URL с/без пользовательского суффикса, Поиск URL-адресов по тегу, Перейдите по ссылке:

Просмотрите информацию об операционной системе и платформе, использованной для доступа к ссылке:

✨ Проверить решение и практиковаться

Обзор

Поздравляем с завершением проекта по сокращению URL-адресов! Эта утилита упрощает обмен длинными URL-адресами, создавая более короткие и удобные для управления ссылки. Однако, необходимо иметь в виду несколько важных аспектов:

  1. Длина базового URL-адреса: Если базовый URL-адрес самого сервиса сокращения длинный, результирующие сокращенные URL-адреса могут быть не такими короткими, как ожидается (как в проекте). Общая длина сокращенного URL-адреса включает в себя базовый URL-адрес, что может ограничить эффективность сервиса сокращения. Чтобы получить наиболее компактные URL-адреса, рассмотрите использование более короткого базового URL-адреса или доменного имени для вашего сервиса.

  2. Ограничения внедрения на веб-сайте: Вы можете столкнуться с ошибками, такими как "Refused to display 'https://scholar.google.com/' in a frame because it set 'X-Frame-Options' to'sameorigin'." Эта ошибка возникает потому, что некоторые веб-сайты используют HTTP-заголовок X-Frame-Options, чтобы предотвратить отображение их содержимого в iframe на других доменах, повышая безопасность против атак "clickjacking". Когда сайт устанавливает этот заголовок в sameorigin, он ограничивает внедрение до iframe, которые имеют одинаковый источник. Это не ограничение сервиса сокращения URL-адресов, а мера безопасности, реализованная целевым веб-сайтом. Для бесперебойного перенаправления лучше использовать сокращенные URL-адреса в качестве прямых ссылок, а не внедрять их в iframe.

Эти аспекты подчеркивают баланс между удобством и безопасностью в веб-разработке и важность осведомленности пользователей для оптимального использования инструментов.