„Wenn ein Arbeiter seine Arbeit gut machen will, muss er zuerst seine Werkzeuge schärfen.“ – Konfuzius, „Die Gespräche des Konfuzius. Lu Linggong“
Titelseite > Programmierung > Persönliche Finanzmanagement-App mit Django, HTMX, Alpine, Tailwind und Plaid

Persönliche Finanzmanagement-App mit Django, HTMX, Alpine, Tailwind und Plaid

Veröffentlicht am 15.11.2024
Durchsuche:883

Ich wollte unbedingt in HTMX eintauchen, insbesondere nachdem ich den DjangoCon Europe 2022-Talk Von React zu HTMX bei einem realen SaaS-Projekt gesehen habe. Ich verwende in letzter Zeit HTMX und Alpine in meiner täglichen Arbeit und zusammen haben sie die Entwicklung interaktiver Web-Apps viel angenehmer gemacht, insbesondere als jemand, der sich nicht besonders für Front-End-Entwicklung interessiert.

Ich war kein großer Fan von Django-Vorlagen, aber HTMX, Alpine.js und Django Cotton haben begonnen, meine Perspektive zu ändern. Und mit Tailwind CSS an der Spitze ist es zu einem der besten Stacks geworden, mit denen ich bisher gearbeitet habe.

Bei diesem Projekt handelt es sich um eine persönliche Finanzmanagement-App, die Plaid integriert, um Bankkonten zu verknüpfen und finanzielle Einblicke bereitzustellen. Ich habe die offiziellen Beispiele von Plaid aus ihrem Repository als Referenz verwendet.

Möchten Sie einen schnellen Überblick über den Code? Schauen Sie es sich auf GitHub an

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

Merkmale

  • Plaid-Integration zum Verknüpfen von Bankkonten, zum Abrufen von Kontodaten in Echtzeit und zum Verfolgen von Transaktionen.
  • Automatisierte Webhooks für:
    • Bankdaten automatisch synchronisieren und aktualisieren, sobald neue Transaktionen verfügbar sind.
    • Konten einfach aktualisieren und erneut authentifizieren, wenn sie einen fehlerhaften Status aufweisen (z. B. Anmeldung erforderlich).
    • Erkennen Sie automatisch neue Bankkonten und fordern Sie Benutzer auf, neu erkannte Konten hinzuzufügen.
  • Bietet finanzielle Einblicke wie Nettovermögen, kontospezifische Details und kategoriebasierte Ausgabenaufschlüsselung.
  • Zwei-Faktor-Authentifizierung (2FA) mit einer Authentifizierungs-App für zusätzliche Sicherheit.

Abhängigkeitsmanagement mit Poesie

Um Abhängigkeiten in diesem Projekt zu verwalten, habe ich Poetry verwendet. Poetry vereinfacht den Paketverwaltungsprozess und automatisiert einen Großteil der schweren Arbeit, die mit Abhängigkeiten verbunden ist. Es basiert auf der Datei pyproject.toml, die heute der Standard zum Definieren von Build-Anforderungen in modernen Python-Projekten ist.

Warum Poesie?

  • Einfachere Abhängigkeitsauflösung.
  • Es erstellt und verwaltet virtuelle Umgebungen. Wenn Sie also jemals vergessen, eine zu erstellen/aktivieren, ist Poetry für Sie da.
  • Es sperrt die genauen Versionen von Paketen und stellt so sicher, dass die Umgebung reproduzierbar ist. Dies ist insbesondere bei der Arbeit in einem größeren Team sehr hilfreich.

Ruff und Pre-Commit

Ich habe Ruff verwendet, einen sehr schnellen Python-Linter und Code-Formatierer, der in Rust erstellt wurde. Es verwaltet eine Reihe von Tools in einem, wie Black, isort und mehr.

Was ich an Ruff mag:

  • Sie können es mit pyproject.toml konfigurieren, wodurch alles sauber und zentralisiert bleibt.
  • Es handelt sich um ein All-in-One-Gerät – Sie müssen also keine separaten Tools wie Black, Isort usw. verwalten.

Ich habe djlint auch zum Flusen von Django-Vorlagen verwendet. Es ist in Ordnung, aber ich bin immer noch auf der Suche nach etwas Besserem. Wenn Sie gute Alternativen kennen, teilen Sie diese gerne mit!

Weitere Informationen zum Einrichten von Pre-Commit-Hooks für die Codeformatierung und Linting in Django finden Sie in meinem Artikel hier.

Projektstruktur

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

In der allgemeinen App füge ich Verwaltungsbefehle, Validierung, Basismodelle, Vorlagen-Tags usw. hinzu. Das BaseModel sieht folgendermaßen aus:

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

Ich habe außerdem einen benutzerdefinierten Startapp-Befehl erstellt, um Django-Apps mit vordefinierten Dateien und Inhalten zu generieren, die für meinen Anwendungsfall geeignet sind.

Tests

Zum Schreiben von Tests verwende ich pytest zusammen mit Factory_boy, wodurch es einfach ist, testspezifische Felder zu deklarieren und Testdaten zu erstellen.

Anfangs habe ich in jeder Django-App einen Testordner platziert. Allerdings bin ich inzwischen dazu übergegangen, einen einzigen Testordner im Stammverzeichnis des Projekts zu haben, mit Unterordnern für jede App. Dieser Ansatz hat die Navigation viel reibungsloser gemacht und sorgt dafür, dass alles organisiert ist. Darüber hinaus erleichtert es die gemeinsame Nutzung gemeinsamer Vorrichtungen erheblich, da diese auf einer höheren Ebene definiert und in mehreren Testmodulen wiederverwendet werden können.

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

Ein Beispieltest:

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

Das Frontend

Dieses Projekt kombiniert die folgenden Frontend-Tools:

HTMX ermöglicht Ihnen das Hinzufügen dynamischer Interaktionen zu Ihrem Projekt, ohne dass umfangreiche JavaScript-Frameworks erforderlich sind. Sie können Ihre Django-Vorlagen mit kleinen, wiederverwendbaren HTMX-Snippets organisieren. Dadurch können Sie bestimmte Teile der Seite basierend auf Benutzeraktionen aktualisieren, ohne dass die gesamte Seite neu geladen werden muss. Dieses Muster funktioniert hervorragend mit Djangos Ansichten, da jeder Inhalt als eigene Ansicht behandelt und dann dynamisch in das DOM eingefügt werden kann.

Alpine.js ist ein weiteres leichtes JavaScript-Framework, das zum Hinzufügen von Interaktivität verwendet wird. Es harmoniert gut mit der Vorlagenstruktur von Django und bietet schnelles, deklaratives Verhalten für Dinge wie Modalitäten, Dropdowns oder Umschaltungen. In Kombination mit HTMX kann Ihnen Alpine gerade genug JavaScript zur Verfügung stellen, um die UX zu verbessern, ohne sich mit etwas wie React oder Vue auseinandersetzen zu müssen. Sie können Alpine beispielsweise verwenden, um den Status im Frontend zu verwalten, z. B. das Öffnen und Schließen von Modalitäten oder die Durchführung der clientseitigen Validierung.

Tailwind CSS übernimmt in diesem Projekt das Styling, was die Entwicklung sauberer und reaktionsfähiger Benutzeroberflächen beschleunigt. Dieses Projekt verwendet Flowbite auch für vorgefertigte UI-Komponenten wie Modalitäten, Tooltips und Schaltflächen. Flowbite lässt sich gut in Tailwind integrieren und hilft Ihnen, das Rad für gängige UI-Elemente nicht neu erfinden zu müssen.

Mit Django Cotton können Sie wiederverwendbare Django-Vorlagen erstellen. Ich habe diese großartige Bibliothek in der Mitte des Projekts entdeckt, als ich versuchte, ein Modal wiederverwendbar zu machen. Anfangs habe ich versucht, das Include-Vorlagen-Tag von Django zu verwenden, aber bei der Übergabe vieler Kontextdaten wurde es schnell unübersichtlich. Mit Django-Cotton können Sie in einer HTML-Tag-ähnlichen Syntax hochgradig wiederverwendbare Komponenten erstellen, die sich gut mit Ihrem HTMX und Tailwind verbinden lassen. Zum Beispiel:


Zwei-Faktor-Authentifizierung mit AllAuth

Zur Implementierung der Authentifizierung in diesem Projekt habe ich die AllAuth-Bibliothek verwendet, die auch Unterstützung für die Multi-Faktor-Authentifizierung (MFA) bietet. Es bietet ein MFA-Modul, das sich nahtlos in Ihr bestehendes Benutzerauthentifizierungs-Setup integrieren lässt. Sie können 2FA über eine Authentifizierungs-App aktivieren und so eine zusätzliche Sicherheitsebene hinzufügen. Sie können die von AllAuth bereitgestellten Vorlagen auch ganz einfach an das Erscheinungsbild Ihrer App anpassen.

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

Abschluss

Insgesamt ist dieses Projekt in erster Linie lehrreich und verfügt über gerade genug Funktionen, um Ihnen den Einstieg in die Integration von Django, HTMX, Alpine.js, Tailwind und Plaid zu erleichtern.

Beachten Sie jedoch, dass es hier und da ein paar Fehler geben kann und es immer Raum für Verbesserungen und die weitere Wiederverwendung von Komponenten gibt. Aber insgesamt ist es eine solide Grundlage für jeden, der diese Technologien erkunden möchte.

Schauen Sie sich das Projekt auf GitHub an

Wenn Sie möchten, dass ich die hier genannten Themen genauer untersuche, lassen Sie es mich in den Kommentaren wissen.

Viel Spaß beim Codieren! ?

Freigabeerklärung Dieser Artikel ist abgedruckt unter: https://dev.to/earthcomfy/personal-finance-management-app-with-django-htmx-alpine-tailwind-and-plaid-2bl0?1 Bei Verstößen wenden Sie sich bitte an Study_golang @163.com löschen
Neuestes Tutorial Mehr>

Haftungsausschluss: Alle bereitgestellten Ressourcen stammen teilweise aus dem Internet. Wenn eine Verletzung Ihres Urheberrechts oder anderer Rechte und Interessen vorliegt, erläutern Sie bitte die detaillierten Gründe und legen Sie einen Nachweis des Urheberrechts oder Ihrer Rechte und Interessen vor und senden Sie ihn dann an die E-Mail-Adresse: [email protected] Wir werden die Angelegenheit so schnell wie möglich für Sie erledigen.

Copyright© 2022 湘ICP备2022001581号-3