Criar um Encurtador de URL com Python e Flask

PythonBeginner
Pratique Agora

Introdução

Neste projeto, aprenderemos como criar um encurtador de URL usando Python e Flask. Um encurtador de URL é uma ferramenta que pega uma URL longa e a converte em uma URL mais curta e gerenciável. Isso pode ser útil para compartilhar links em mídias sociais ou em e-mails, bem como para tornar URLs longas mais amigáveis.

👀 Pré-visualização

URL shortener interface preview

🎯 Tarefas

Neste projeto, você aprenderá:

  • Como configurar uma pasta de projeto e criar os arquivos necessários para o encurtador de URL.
  • Como configurar um banco de dados SQLite para armazenar as URLs originais e suas URLs encurtadas correspondentes.
  • Como gerar URLs curtas usando caracteres aleatórios.
  • Como criar uma página de índice onde os usuários podem enviar uma URL para ser encurtada e exibir a URL encurtada.
  • Como redirecionar os usuários para a URL original quando eles digitam uma URL encurtada.
  • Como criar uma página de histórico para exibir todas as URLs que foram encurtadas.
  • Como executar o projeto e testá-lo em um navegador da web.

🏆 Conquistas

Após concluir este projeto, você será capaz de:

  • Entender como configurar um projeto Flask e criar os arquivos necessários.
  • Utilizar SQLite para criar um banco de dados e executar consultas.
  • Gerar caracteres aleatórios para as URLs curtas.
  • Desenvolver templates HTML e estender templates base.
  • Lidar com envios de formulários e exibir conteúdo dinâmico usando Flask.
  • Implementar redirecionamento de URL com base na entrada do usuário.

Criando os Arquivos do Projeto

Para começar, precisamos criar uma pasta de projeto e adicionar os seguintes arquivos a ela:

  • app.py: Este arquivo conterá todo o código para o nosso encurtador de URL.
  • templates/index.html: Este arquivo conterá o código HTML para a página de índice do nosso site.
  • templates/history.html: Este arquivo conterá o código HTML para a página de histórico do nosso site.
  • templates/base.html: Este arquivo conterá o código HTML base que será usado tanto em index.html quanto em history.html.
cd ~/project
touch app.py
mkdir templates
touch templates/index.html templates/history.html templates/base.html
✨ Verificar Solução e Praticar

Configurando o Banco de Dados

Nosso encurtador de URL precisará de um banco de dados para armazenar as URLs originais e suas URLs encurtadas correspondentes. Usaremos SQLite para nosso banco de dados, que é um sistema de gerenciamento de banco de dados leve e fácil de usar.

Para configurar o banco de dados, primeiro precisamos importar os módulos necessários em app.py:

## app.py
from flask import Flask, render_template, request, redirect
import string
import random
import sqlite3

Em seguida, precisamos conectar-nos ao banco de dados SQLite e criar um objeto cursor:

## Connect to the SQLite database
conn = sqlite3.connect("urls.db", check_same_thread=False)
db = conn.cursor()

Então, podemos criar uma tabela em nosso banco de dados para armazenar as URLs:

## Create the URLs table if it doesn't exist
db.execute(
    """CREATE TABLE IF NOT EXISTS urls
              (id INTEGER PRIMARY KEY AUTOINCREMENT,
               original_url TEXT NOT NULL,
               short_url TEXT NOT NULL,
               created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP)"""
)
conn.commit()
✨ Verificar Solução e Praticar

Gerando URLs Curtas

Para gerar URLs curtas, usaremos uma combinação de letras e números aleatórios. Isso pode ser alcançado usando os módulos string e random em Python. Criaremos uma função chamada generate_short_url() que retornará uma string aleatória de 6 caracteres:

def generate_short_url():
    characters = string.ascii_letters + string.digits
    short_url = "".join(random.choice(characters) for _ in range(6))
    return short_url
✨ Verificar Solução e Praticar

Criando a Página de Índice

A página de índice do nosso site permitirá que os usuários enviem uma URL para ser encurtada. Ela também exibirá a URL encurtada assim que for gerada. O código HTML para esta página pode ser encontrado em templates/index.html.

Primeiro, precisamos estender o template base.html e criar um formulário para os usuários enviarem suas URLs:

{% extends "base.html" %} {% block content %}
<div class="text-center">
  <h1 class="text-3xl font-bold text-gray-900 mb-8">Shorten Your URL</h1>
  <form action="/" method="POST" class="w-full max-w-sm mx-auto">
    <div
      class="flex items-center border-2 border-blue-500 rounded overflow-hidden"
    >
      <input
        type="text"
        name="original_url"
        placeholder="Enter URL"
        class="appearance-none bg-transparent border-none w-full text-gray-700 py-2 px-4 leading-tight focus:outline-none"
      />
      <button
        type="submit"
        class="bg-blue-500 hover:bg-blue-700 text-white py-2 px-4 rounded-r focus:outline-none"
      >
        Shorten
      </button>
    </div>
  </form>
  {% if short_url %}
  <div class="mt-4">
    <p class="text-lg text-gray-700">
      Short URL:
      <a href="{{ request.host_url }}{{ short_url }}" class="text-blue-500"
        >{{ request.host_url }}{{ short_url }}</a
      >
    </p>
  </div>
  {% endif %}
</div>
{% endblock %}

Em index.html, temos um formulário com um único campo de entrada para o usuário inserir sua URL. O formulário será enviado para a mesma página, então definimos o atributo action como /. Também definimos o atributo method como POST para que os dados do formulário sejam enviados no corpo da requisição.

Agora, precisamos adicionar templates/base.html:

<!doctype html>
<html>
  <head>
    <title>URL Shortener</title>
    <link
      href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css"
      rel="stylesheet"
    />
  </head>
  <body>
    <nav class="p-6 bg-white flex justify-between items-center">
      <a href="/" class="text-2xl font-bold text-gray-900">URL Shortener</a>
      <div>
        <a href="/" class="text-gray-800 mr-6">Home</a>
        <a href="/history" class="text-gray-800">History</a>
      </div>
    </nav>
    <main class="container mx-auto max-w-xl pt-8 min-h-screen">
      {% block content %} {% endblock %}
    </main>
  </body>
</html>

Em base.html, temos uma barra de navegação no topo da página com links para a página inicial e a página de histórico. Também temos um elemento main que conterá o conteúdo de cada página. O bloco content é onde o conteúdo de cada página será inserido.

Também precisamos adicionar o código necessário em app.py para lidar com os envios de formulários e gerar a URL encurtada:

@app.route("/", methods=["GET", "POST"])
def index():
    if request.method == "POST":
        original_url = request.form["original_url"]
        short_url = generate_short_url()

        ## Insert the original and short URLs into the database
        db.execute(
            "INSERT INTO urls (original_url, short_url) VALUES (?, ?)",
            (original_url, short_url),
        )
        conn.commit()

        return render_template("index.html", short_url=short_url)

    return render_template("index.html")

Em index(), verificamos se o método da requisição é POST. Se for, pegamos a URL original dos dados do formulário e geramos uma URL curta. Em seguida, inserimos as URLs original e curta no banco de dados e renderizamos o template index.html com a URL curta.

✨ Verificar Solução e Praticar

Redirecionando para a URL Original

Quando um usuário digita uma URL encurtada, queremos redirecioná-lo para a URL original correspondente. Para fazer isso, precisamos criar uma função que recuperará a URL original do banco de dados com base na URL encurtada:

@app.route("/<short_url>")
def redirect_to_url(short_url):
    ## Retrieve the original URL from the database based on the short URL
    db.execute("SELECT original_url FROM urls WHERE short_url=?", (short_url,))
    result = db.fetchone()

    if result:
        original_url = result[0]
        return redirect(original_url)

    return render_template("index.html")
✨ Verificar Solução e Praticar

Criando a Página de Histórico

A página de histórico exibirá todas as URLs que foram encurtadas, juntamente com suas URLs originais e a data em que foram adicionadas. O código HTML para esta página pode ser encontrado em templates/history.html.

Primeiro, precisamos estender o template base.html e adicionar uma tabela para exibir as URLs:

{% extends "base.html" %} {% block content %}
<div class="w-full overflow-x-auto">
  <table class="w-full bg-white rounded shadow overflow-hidden">
    <thead class="bg-gray-200">
      <tr>
        <th
          class="text-left py-3 px-4 uppercase font-semibold text-sm text-gray-700"
        >
          Original URL
        </th>
        <th
          class="text-left py-3 px-4 uppercase font-semibold text-sm text-gray-700"
        >
          Short URL
        </th>
        <th
          class="text-left py-3 px-4 uppercase font-semibold text-sm text-gray-700"
        >
          Date
        </th>
      </tr>
    </thead>
    <tbody>
      {% for result in results %}
      <tr class="hover:bg-gray-100">
        <td class="border-t">
          <p class="py-3 px-4">{{ result[0] }}</p>
        </td>
        <td class="border-t">
          <a
            href="{{ request.host_url }}{{ result[1] }}"
            class="py-3 px-4 text-blue-500 hover:text-blue-700"
            >{{ request.host_url }}{{ result[1] }}</a
          >
        </td>
        <td class="border-t">
          <p class="py-3 px-4">{{ result[2] }}</p>
        </td>
      </tr>
      {% endfor %}
    </tbody>
  </table>
</div>
{% endblock %}

Também precisamos adicionar o código necessário em app.py para recuperar as URLs do banco de dados e passá-las para o template:

@app.route("/history")
def history():
    ## Retrieve all URLs from the database, ordered by the most recent ones
    db.execute(
        "SELECT original_url, short_url, created_at FROM urls ORDER BY created_at DESC"
    )
    results = db.fetchall()
    return render_template("history.html", results=results)
✨ Verificar Solução e Praticar

Executando o Projeto

Adicione o seguinte código ao final de app.py:

if __name__ == "__main__":
    app.run(debug=True, host="0.0.0.0", port=8080)

Depois que os módulos estiverem instalados, podemos executar nosso projeto executando python app.py em nosso terminal. Isso iniciará o servidor de desenvolvimento Flask e nosso site estará acessível em http://localhost:8080.

Mude para a aba 8080 e atualize a página. Você deve ver o seguinte:

Flask server running successfully
✨ Verificar Solução e Praticar

Resumo

Neste projeto, aprendemos como criar um encurtador de URL usando Python e Flask. Primeiro, configuramos os arquivos de projeto e o banco de dados necessários, depois criamos funções para gerar URLs curtas e lidar com envios de formulários. Também aprendemos como recuperar e exibir as URLs do banco de dados. Com este projeto, você agora pode criar seu próprio encurtador de URL e personalizá-lo ao seu gosto.