"Si un trabajador quiere hacer bien su trabajo, primero debe afilar sus herramientas." - Confucio, "Las Analectas de Confucio. Lu Linggong"
Página delantera > Programación > Aplicación de gestión de finanzas personales con Django, HTMX, Alpine, Tailwind y Plaid

Aplicación de gestión de finanzas personales con Django, HTMX, Alpine, Tailwind y Plaid

Publicado el 2024-11-15
Navegar:423

Tenía muchas ganas de sumergirme en HTMX, especialmente después de ver la charla de DjangoCon Europe 2022 De React a HTMX en un proyecto SaaS del mundo real. He estado usando HTMX y Alpine en mi trabajo diario últimamente y juntos han hecho que el desarrollo de aplicaciones web interactivas sea mucho más divertido, especialmente para alguien a quien no le gusta mucho el desarrollo front-end.

No he sido un gran admirador de las plantillas de Django, pero HTMX, Alpine.js y Django Cotton han comenzado a cambiar mi perspectiva. Y con Tailwind CSS encima, se ha convertido en una de las mejores pilas con las que he trabajado hasta ahora.

Este proyecto es una aplicación de gestión de finanzas personales que integra Plaid para vincular cuentas bancarias y proporcionar información financiera. Utilicé los ejemplos oficiales de Plaid de su repositorio como referencia.

¿Quieres una descripción general rápida del código? Compruébalo en GitHub

Personal Finance Management App with Django, HTMX, Alpine, Tailwind, and Plaid

Características

  • Integración con Plaid para vincular cuentas bancarias, obtener datos de cuentas en tiempo real y realizar un seguimiento de transacciones.
  • Webhooks automatizados para:
    • Sincroniza y actualiza automáticamente los datos bancarios cada vez que hay nuevas transacciones disponibles.
    • Actualice y vuelva a autenticar cuentas fácilmente cuando entren en un mal estado (por ejemplo, es necesario iniciar sesión).
    • Detecta automáticamente nuevas cuentas bancarias y solicita a los usuarios que agreguen cuentas recién detectadas.
  • Proporciona información financiera como patrimonio neto, detalles específicos de la cuenta y desgloses de gastos basados ​​en categorías.
  • Autenticación de dos factores (2FA) con una aplicación de autenticación para una capa adicional de seguridad.

Gestión de la dependencia con poesía

Para gestionar las dependencias en este proyecto, utilicé Poetry. Poetry simplifica el proceso de gestión de paquetes y automatiza gran parte del trabajo pesado relacionado con las dependencias. Se basa en el archivo pyproject.toml, que ahora es el estándar para definir los requisitos de compilación en proyectos Python modernos.

¿Por qué poesía?

  • Resolución de dependencias más sencilla.
  • Crea y administra entornos virtuales, por lo que si alguna vez te olvidas de crear/activar uno, Poetry te respalda.
  • Bloquea las versiones exactas de los paquetes, asegurándose de que el entorno sea reproducible. Esto es muy útil, especialmente cuando se trabaja en un equipo más grande.

Fallar y precomprometerse

He estado usando Ruff, que es un formateador de código y linter de Python muy rápido, integrado en Rust. Maneja un montón de herramientas todo en uno, como Black, isort y más.

Lo que me gusta de Ruff:

  • Puedes configurarlo usando pyproject.toml, que mantiene todo limpio y centralizado.
  • Es todo en uno, por lo que no es necesario administrar herramientas independientes como Black, isort, etc.

También usé djlint para crear plantillas de Django. Es decente, pero todavía estoy buscando algo mejor. Si conoces alguna buena alternativa, ¡no dudes en compartirla!

Para obtener más información sobre cómo configurar ganchos de confirmación previa para formatear código y linting en Django, consulta mi artículo aquí.

Estructura del proyecto

django_finance/
├── apps/
│   ├── accounts/
│   ├── common/
│   └── plaid/
├── config/
│   ├── app_template/
│   ├── settings/
│   ├── asgi.py
│   ├── celery.py
│   ├── urls.py
│   └── wsgi.py
├── static/
│   ├── css/
│   ├── images/
│   └── js/
├── templates/
│   ├── account/
│   ├── components/
│   ├── errors/
│   ├── layouts/
│   ├── mfa/
│   ├── plaid/
│   ├── _base_dashboard.html
│   ├── _base.html
│   └── index.html
├── tests/
│   ├── accounts/
│   ├── common/
│   ├── plaid/
│   └── conftest.py
├── theme/
├── .pre-commit-config.yaml
├── db.sqlite3
├── manage.py
├── poetry.lock
├── pyproject.toml
└── README.md

En la aplicación común, agrego comandos de administración, validación, modelos base, etiquetas de plantilla, etc. El modelo base se ve así:

class BaseModel(models.Model):
    """
    Base model for common fields and methods.
    """

    id = models.AutoField(primary_key=True)
    uuid = models.UUIDField(default=uuid.uuid4, unique=True, editable=False)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    is_active = models.BooleanField(default=True, db_index=True, help_text="Used for soft deleting records.")

    objects = BaseModelManager()

    class Meta:
        abstract = True

    def soft_delete(self):
        self.is_active = False
        self.save()

    def restore(self):
        self.is_active = True
        self.save()

También he creado un comando de inicio de aplicación personalizado para generar aplicaciones Django con archivos predefinidos y contenido adecuado para mi caso de uso.

Pruebas

Para escribir pruebas, uso pytest junto con factory_boy, lo que facilita la declaración de campos específicos de la prueba y la creación de datos de prueba.

Al principio, solía colocar una carpeta de pruebas dentro de cada aplicación Django. Sin embargo, desde entonces cambié a tener una única carpeta de pruebas en la raíz del proyecto, con subcarpetas para cada aplicación. Este enfoque ha hecho que la navegación sea mucho más fluida y mantiene todo organizado. Además, hace que compartir dispositivos comunes sea mucho más fácil, ya que pueden definirse en un nivel superior y reutilizarse en múltiples módulos de prueba.

tests/
├── accounts/
│   ├── __init__.py
│   ├── factories.py
│   ├── test_managers.py
│   ├── test_models.py
├── common/
│   ├── __init__.py
│   ├── test_validators.py
├── plaid/
│   ├── conftest.py
│   ├── dummy_data.py
│   ├── factories.py
│   ├── test_models.py
│   ├── test_services.py
│   ├── test_tasks.py
│   ├── test_views.py
│   ├── test_webhooks.py
├── __init__.py/
└── conftest.py

Una prueba de muestra:

class TestCreatePlaidLinkToken:
    LINK_TOKEN = "link_token"

    class MockLinkTokenResponse:
        def to_dict(self):
            return {
                "link_token": TestCreatePlaidLinkToken.LINK_TOKEN,
                "expiration": "2020-03-27T12:56:34Z",
                "request_id": "request_id",
            }

    @pytest.fixture
    def setup_mocks(self, mocker):
        return {
            "mock_link_token": mocker.patch(
                "django_finance.apps.plaid.views.plaid_config.client.link_token_create",
                return_value=self.MockLinkTokenResponse(),
            ),
            "mock_logger": mocker.patch("django_finance.apps.plaid.views.logger"),
        }

    @pytest.fixture
    def create_link_token(self, client):
        def _create_link_token(data=None):
            return client.post(
                reverse("create_link_token"),
                json.dumps(data) if data else None,
                content_type="application/json",
            )

        return _create_link_token

    def test_create_plaid_link_token_success(self, login, setup_mocks, create_link_token):
        login()
        response = create_link_token()
        assert response.status_code == 201
        data = json.loads(response.content)
        assert "link_token" in data
        assert data["link_token"] == self.LINK_TOKEN
        setup_mocks["mock_link_token"].assert_called_once()

La interfaz

Este proyecto combina las siguientes herramientas frontend:

HTMX le permite agregar interacciones dinámicas a su proyecto sin necesidad de marcos de JavaScript pesados. Puedes organizar tus plantillas de Django con pequeños fragmentos HTMX reutilizables. Esto le permite actualizar partes específicas de la página según las acciones del usuario, sin necesidad de recargar la página completa. Este patrón funciona muy bien con las vistas de Django porque cada contenido puede tratarse como su propia vista y luego inyectarse dinámicamente en el DOM.

Alpine.js es otro marco de JavaScript liviano que se utiliza para agregar interactividad. Funciona muy bien con la estructura de plantillas de Django y proporciona un comportamiento declarativo rápido para cosas como modales, menús desplegables o alternancias. En combinación con HTMX, Alpine puede brindarle suficiente JavaScript para mejorar la UX sin tener que lidiar con algo como React o Vue. Por ejemplo, puede usar Alpine para administrar el estado en la interfaz, como abrir y cerrar modales o manejar la validación del lado del cliente.

Tailwind CSS maneja el estilo en este proyecto, lo que acelera el desarrollo de UI limpias y responsivas. Este proyecto también utiliza Flowbite para componentes de interfaz de usuario prediseñados como modales, información sobre herramientas y botones. Flowbite se integra bien con Tailwind y te ayuda a evitar reinventar la rueda para elementos comunes de la interfaz de usuario.

Django Cotton te permite crear plantillas Django reutilizables. Descubrí esta increíble biblioteca a mitad del proyecto mientras intentaba hacer un modal reutilizable. Inicialmente, intenté usar la etiqueta de plantilla de inclusión de Django, pero al pasar muchos datos de contexto, rápidamente se volvió abarrotada. Django-Cotton le permite crear componentes altamente reutilizables que se vinculan bien con su HTMX y Tailwind en una sintaxis similar a una etiqueta HTML. Por ejemplo:

Autenticación de dos factores con AllAuth

Para implementar la autenticación en este proyecto, utilicé la biblioteca AllAuth, que también brinda soporte para la autenticación multifactor (MFA). Ofrece un módulo MFA que se integra perfectamente con su configuración de autenticación de usuario existente. Puede habilitar 2FA a través de una aplicación de autenticación, agregando una capa adicional de seguridad. También puedes personalizar fácilmente las plantillas que proporciona AllAuth para que coincidan con la apariencia de tu aplicación.

Personal Finance Management App with Django, HTMX, Alpine, Tailwind, and Plaid Personal Finance Management App with Django, HTMX, Alpine, Tailwind, and Plaid

Conclusión

En general, este proyecto es principalmente educativo y tiene características suficientes para comenzar a integrar Django, HTMX, Alpine.js, Tailwind y Plaid.

Dicho esto, tenga en cuenta que puede haber algunos errores aquí y allá, y siempre hay margen de mejora y reutilización adicional de los componentes. Pero, en general, es una base sólida para cualquiera que desee explorar estas tecnologías.

Ver el proyecto en GitHub

Si quieres que explore los temas mencionados aquí con más detalle, házmelo saber en los comentarios.

¡Feliz codificación! ?

Declaración de liberación Este artículo se reproduce en: https://dev.to/earthcomfy/personal-finance-management-app-with-django-htmx-alpine-tailwind-and-plaid-2bl0?1 Si hay alguna infracción, comuníquese con Study_golang @163.com eliminar
Último tutorial Más>

Descargo de responsabilidad: Todos los recursos proporcionados provienen en parte de Internet. Si existe alguna infracción de sus derechos de autor u otros derechos e intereses, explique los motivos detallados y proporcione pruebas de los derechos de autor o derechos e intereses y luego envíelos al correo electrónico: [email protected]. Lo manejaremos por usted lo antes posible.

Copyright© 2022 湘ICP备2022001581号-3