Tutoriales avanzados: Cómo escribir aplicaciones reutilizables

Este tutoria avanzado comienza donde Tutorial 8 dejó de lado. Vamos a convertir nuestra encuesta web en un paquete Python independiente que puedes reutilizar en nuevos proyectos y compartir con otras personas.

Si no has completado recientemente los tutoriales 1-8, te animamos a revisarlos para que tu proyecto de ejemplo coincida con el descrito a continuación.

La reutilización importa

Es mucho trabajo diseñar, construir, probar y mantener una aplicación web. Muchos proyectos Python y Django comparten problemas comunes. ¿No sería genial si pudiéramos ahorrar algo de este trabajo repetido?

La reutilización es la forma de vida en Python. El Índice de Paquetes de Python (PyPI) tiene una amplia gama de paquetes que puedes utilizar en tus propios programas Python. Revisa Paquetes Django para encontrar aplicaciones reutilizables existentes que podrías incorporar en tu proyecto. Django mismo es un paquete normal de Python. Esto significa que puedes tomar paquetes de Python existentes o aplicaciones Django y componerlas en tu propio proyecto web. Solo necesitas escribir las partes que hacen que tu proyecto sea único.

Digamos que estabas empezando un nuevo proyecto que necesitaba una aplicación de encuestas como la que hemos estado trabajando. ¿Cómo haces que esta aplicación sea reutilizable? Afortunadamente, ya estás bien encaminado. En Tutorial 1, vimos cómo podíamos desacoplar las encuestas del URLconf a nivel de proyecto utilizando un include. En este tutorial, iremos más allá para hacer que la aplicación sea fácil de usar en nuevos proyectos y lista para publicar para que otros puedan instalarla y utilizarla.

Paquete? Aplicación?

Un paquete Python proporciona una forma de agrupar código relacionado de Python para su reutilización fácil. Un paquete contiene uno o más archivos de código Python (también conocidos como «módulos»).

Un paquete se puede importar con import foo.bar o from foo import bar. Para que un directorio (como polls) forme un paquete, debe contener un archivo especial __init__.py, incluso si este archivo está vacío.

Una aplicación Django es un paquete Python específicamente diseñado para su uso en un proyecto de Django. Una aplicación puede utilizar convenciones de Django comunes, como tener submódulos models, tests, urls y views.

Más adelante utilizamos el término empaquetamiento para describir el proceso de hacer que un paquete Python sea fácil de instalar para otros. Puede ser un poco confuso, lo sabemos.

Tu proyecto y tu aplicación reutilizable

Después de los tutoriales anteriores, nuestro proyecto debería parecerse a esto:

djangotutorial/
    manage.py
    mysite/
        __init__.py
        settings.py
        urls.py
        asgi.py
        wsgi.py
    polls/
        __init__.py
        admin.py
        apps.py
        migrations/
            __init__.py
            0001_initial.py
        models.py
        static/
            polls/
                images/
                    background.png
                style.css
        templates/
            polls/
                detail.html
                index.html
                results.html
        tests.py
        urls.py
        views.py
    templates/
        admin/
            base_site.html

You creaste djangotutorial/templates en Tutorial 7 y polls/templates en Tutorial 3. Ahora tal vez sea más claro por qué elegimos tener directorios de plantillas separados para el proyecto y la aplicación: todo lo que forma parte de la aplicación polls está en polls. Esto hace que la aplicación esté contenida y sea más fácil de insertar en un nuevo proyecto.

El directorio polls podría copiarse ahora en una nueva instalación de Django y utilizarse inmediatamente. No está listo para ser publicado, sin embargo. Para eso necesitamos empaquetarlo para hacer que sea fácil para otros instalarlo.

Instalando algunas dependencias

El estado actual del empaquetamiento de Python es un poco confuso con varias herramientas. Para este tutorial, vamos a utilizar setuptools para construir nuestro paquete. Es la herramienta recomendada (fusionada con el distribute fork). También vamos a utilizar pip para instalar y desinstalarlo. Deberías instalar estas dos herramientas ahora. Si necesitas ayuda, puedes referirte a cómo instalar Django con pip. Puedes instalar setuptools de la misma manera.

Empaquetando tu aplicación

El empaquetamiento de Python se refiere a preparar tu aplicación en un formato específico que pueda instalarse y utilizarse fácilmente. Django mismo está empaquetado de esta manera. Para una pequeña aplicación como polls, este proceso no es demasiado difícil.

  1. Primero, crea un directorio padre para el paquete, fuera de tu proyecto de Django. Llama a este directorio django-polls.

    Elegir un nombre para tu aplicación

    Cuando elijas un nombre para tu paquete, verifica PyPI para evitar conflictos de nombres con paquetes existentes. Recomendamos utilizar un prefijo django- para los nombres de paquete, para identificar tu paquete como específico de Django, y un correspondiente prefijo django_ para el nombre del módulo. Por ejemplo, el paquete django-ratelimit contiene el módulo django_ratelimit.

    Etiquetas de aplicación (es decir, la parte final del camino punteado a los paquetes de aplicaciones) deben ser únicas en INSTALLED_APPS. Evita utilizar el mismo etiqueta que cualquier de las paquetes contribuyentes de Django, por ejemplo auth, admin o messages.

  2. Move el directorio polls al directorio django-polls, y renómbralo a django_polls.

  3. Edita django_polls/apps.py para que name se refiera al nuevo nombre de módulo y agrega label para dar un nombre corto para la aplicación:

    django-polls/django_polls/apps.py
    from django.apps import AppConfig
    
    
    class PollsConfig(AppConfig):
        default_auto_field = "django.db.models.BigAutoField"
        name = "django_polls"
        label = "polls"
    
  4. Crea un archivo django-polls/README.rst con el siguiente contenido:

    django-polls/README.rst
    ============
    django-polls
    ============
    
    django-polls is a Django app to conduct web-based polls. For each
    question, visitors can choose between a fixed number of answers.
    
    Detailed documentation is in the "docs" directory.
    
    Quick start
    -----------
    
    1. Add "polls" to your INSTALLED_APPS setting like this::
    
        INSTALLED_APPS = [
            ...,
            "django_polls",
        ]
    
    2. Include the polls URLconf in your project urls.py like this::
    
        path("polls/", include("django_polls.urls")),
    
    3. Run ``python manage.py migrate`` to create the models.
    
    4. Start the development server and visit the admin to create a poll.
    
    5. Visit the ``/polls/`` URL to participate in the poll.
    
  5. Crea un archivo django-polls/LICENSE. Elige una licencia, ya que es más allá del alcance de este tutorial, pero basta decir que el código lanzado públicamente sin una licencia es inútil. Django y muchas aplicaciones compatibles con Django se distribuyen bajo la licencia BSD; sin embargo, estás libre de elegir tu propia licencia. Solo ten en cuenta que tu elección de licencia afectará quién puede utilizar tu código.

  6. A continuación, crearemos el archivo pyproject.toml que detalla cómo construir y instalar la aplicación. Una explicación completa de este archivo está más allá del alcance de este tutorial, pero el Guía del usuario para paquetes de Python tiene una buena explicación. Crea el archivo django-polls/pyproject.toml con el siguiente contenido:

    django-polls/pyproject.toml
    [build-system]
    requires = ["setuptools>=77.0.3"]
    build-backend = "setuptools.build_meta"
    
    [project]
    name = "django-polls"
    version = "0.1"
    dependencies = [
        "django>=X.Y",  # Replace "X.Y" as appropriate
    ]
    description = "A Django app to conduct web-based polls."
    readme = "README.rst"
    license = "BSD-3-Clause"
    requires-python = ">= 3.10"
    authors = [
        {name = "Your Name", email = "yourname@example.com"},
    ]
    classifiers = [
        "Environment :: Web Environment",
        "Framework :: Django",
        "Framework :: Django :: X.Y",  # Replace "X.Y" as appropriate
        "Intended Audience :: Developers",
        "Operating System :: OS Independent",
        "Programming Language :: Python",
        "Programming Language :: Python :: 3",
        "Programming Language :: Python :: 3 :: Only",
        "Programming Language :: Python :: 3.10",
        "Programming Language :: Python :: 3.11",
        "Programming Language :: Python :: 3.12",
        "Programming Language :: Python :: 3.13",
        "Programming Language :: Python :: 3.14",
        "Topic :: Internet :: WWW/HTTP",
        "Topic :: Internet :: WWW/HTTP :: Dynamic Content",
    ]
    
    [project.urls]
    Homepage = "https://www.example.com/"
    
  7. Muchos archivos y módulos de Python y paquetes están incluidos en el paquete por defecto. Para incluir archivos adicionales, necesitaremos crear un archivo MANIFEST.in. Para incluir los templates y archivos estáticos, crea un archivo django-polls/MANIFEST.in con el siguiente contenido:

    django-polls/MANIFEST.in
    recursive-include django_polls/static *
    recursive-include django_polls/templates *
    
  8. It’s optional, but recommended, to include detailed documentation with your app. Create an empty directory django-polls/docs for future documentation.

    Ten en cuenta que el directorio docs no se incluirá en tu paquete a menos que agregues algunos archivos a él. Muchas aplicaciones de Django también proporcionan su documentación en línea a través de sitios como readthedocs.org.

    Muchos proyectos de Python, incluyendo Django y Python mismo, utilizan Sphinx para construir su documentación. Si decides utilizar Sphinx puedes vincular a la documentación de Django configurando Intersphinx y incluyendo un valor para Django en el valor intersphinx_mapping de tu proyecto:

    intersphinx_mapping = {
        # ...
        "django": (
            "https://docs.djangoproject.com/en/stable/",
            None,
        ),
    }
    

    Con eso en su lugar, puedes vincular a entradas específicas, del mismo modo que en la documentación de Django, como «:attr:`django.test.TransactionTestCase.databases`».

  9. Verifica que esté instalado el paquete build (python -m pip install build) y trata de construir tu paquete ejecutando python -m build dentro de django-polls. Esto crea un directorio llamado dist y construye tu nuevo paquete en formatos fuente y binario, django_polls-0.1.tar.gz y django_polls-0.1-py3-none-any.whl.

Para obtener más información sobre la empaquetización, consulta el Tutorial de empaquetización y distribución de proyectos de Python.

Utilizando tu propio paquete

Dado que movimos el directorio polls fuera del proyecto, ya no funciona. Ahora lo arreglaremos instalando nuestro nuevo paquete django-polls.

Instalación como biblioteca de usuario

Los siguientes pasos instalan django-polls como una biblioteca de usuario. Las instalaciones por usuario tienen muchas ventajas sobre la instalación del paquete en el sistema, como ser utilizables en sistemas donde no tienes acceso administrador así como evitar que el paquete afecte servicios del sistema y otros usuarios de la máquina.

Ten en cuenta que las instalaciones por usuario pueden afectar aún el comportamiento de herramientas del sistema que se ejecutan como ese usuario, por lo tanto utilizar un entorno virtual es una solución más robusta (ver a continuación).

  1. Para instalar la paqueta, utiliza pip (ya la instalaste , ¿verdad?):

    python -m pip install --user django-polls/dist/django_polls-0.1.tar.gz
    
  2. Actualiza mysite/settings.py para que apunte al nuevo nombre de módulo:

    INSTALLED_APPS = [
        "django_polls.apps.PollsConfig",
        ...,
    ]
    
  3. Actualiza mysite/urls.py para que apunte al nuevo nombre de módulo:

    urlpatterns = [
        path("polls/", include("django_polls.urls")),
        ...,
    ]
    
  4. Ejecuta el servidor de desarrollo para confirmar que el proyecto sigue funcionando.

Publicación de tu aplicación

Ahora que hemos empaquetado y probado django-polls, está listo para compartir con el mundo! Si esto no era solo un ejemplo, podrías ahora:

Instalando paquetes de Python con un entorno virtual

Hace poco instalamos django-polls como biblioteca del usuario. Esto tiene algunas desventajas:

  • Modificar las bibliotecas del usuario puede afectar a otros software de Python en tu sistema.

  • No podrás ejecutar varias versiones de este paquete (o otros con el mismo nombre).

Normalmente, estas situaciones solo surgen una vez que estés manteniendo varios proyectos Django. Cuando lo hacen, la mejor solución es utilizar venv. Esta herramienta te permite mantener múltiples entornos de Python aislados, cada uno con su propia copia de las bibliotecas y el espacio de nombres del paquete.