Einer auf dem Feld ist kein Krieger oder wie ein Full-Stack-Backend versucht hat, es zu werden

Ich liebe es, verschiedene Nebenprojekte zu starten. Ich denke, dies ist eine der besten Möglichkeiten, etwas Neues zu lernen, das sich wirklich lohnt. Und ich habe einen schwerwiegenden Fehler: Ich erledige fast nie Dinge. Hier geht es natürlich nicht um Studienprojekte, für die ich eine vom Arbeitgeber festgelegte Note oder Aufgaben erhalten werde. Ich spreche über meine eigenen Ideen, mit denen ich außerhalb ständiger Arbeit oder Studium aufleuchte. Jedes Mal, wenn ich eine völlig neue Fähigkeit beherrsche, die ich für gefragt halte, und ich nicht die Aussicht sehe, so etwas zu lernen, vergesse ich einfach das Projekt. Aber diesmal habe ich beschlossen, mich zu verbessern - das Projekt zu starten, es abzuschließen und über den Weg zu erzählen, den ich gegangen bin.



Ein bisschen über mich selbst



Ich habe eine Fachausbildung, einen Bachelor-Abschluss in Mathematik und einen Master-Abschluss in IT. Überraschenderweise waren mir viele Dinge, die ich an der Universität beherrschte, nützlich, insbesondere der Master-Abschluss. Auf jeden Fall gelang es mir, mein Gehirn in die richtige Richtung zu lenken, um die notwendigen Informationen produktiv aufzunehmen, mich in diesem Bereich gut zu zeigen, einen Job zu finden und meine Karriere voranzutreiben.



Während des Studiums war ich ein C ++ - Fan und ein Spieleentwickler. Dann habe ich eine selbstgeschriebene Engine entwickelt und Spiele darauf geschrieben, versucht. Ich hatte ein Diplom in C und war mit der Verwendung von Grafikprozessoren in Berechnungen verbunden. Dann interessierte ich mich für Java- und Android-Entwicklung. Er absolvierte mehrere Bildungsprojekte in dieser Sprache und schrieb dann im Rahmen eines Studentenprojekts mit Unterstützung eines internationalen Unternehmens ein Konsolendienstprogramm zur Analyse der Programmleistung. All dies entwickelte sich zu einer Android-Anwendung mit der Möglichkeit, Ihr Telefon hinsichtlich seiner Leistung zu testen und mit anderen zu vergleichen.



Die Pythonwelt war am Horizont. Auf Anregung meines guten Freundes interessierte ich mich unerwartet für Data Science und Python, es war vor mehr als vier Jahren. Zufälligerweise musste ich den Job wechseln und meine Fähigkeiten wurden als geeignet bewertet, um an Backends für interne Analysedienste zu arbeiten. Durch Datenanalyse kam ich zur Webentwicklung in dieser Sprache.



Aus Pflicht musste ich ein Full-Stack-Entwickler sein, wenn echte Front-End-Entwickler sehr beschäftigt waren oder wenn die Qualitätsstandards der Benutzeroberfläche nicht an erster Stelle standen.



Dies ist eine Beschreibung des Pfades, der zum Erstellen Ihrer eigenen vollwertigen Webanwendung ohne vollständiges Eintauchen in die technischen Details erforderlich war. Links zu Commits aus meinem Repository werden unterwegs gelöscht. Kurz über die Etappen dieser Reise:



  • UI
  • , , CI
  • production-
  • production-
  • https

- AWS. , .







Die Wahl des Themas der Anwendung ist eine andere Geschichte, die endgültige Wahl fiel auf die Verfolgung von Gewohnheiten. Die Homepage sollte eine Reihe von Schaltflächen mit nachverfolgten Gewohnheiten enthalten. Wir haben eine Aktion gemacht - einen Knopf gedrückt - und so jeden Tag. Die Daten sollten gespeichert und auf einer separaten Seite in Form einer Tabelle, Gewohnheiten in Zeilen und Kalendertagen in Spalten angezeigt werden. Eine gefüllte Zelle zeigt an, dass die erforderliche Aktion an diesem Tag ausgeführt wurde. Wie ein einfacher Papiergewohnheits-Tracker.





Der technologische Stack war für mich offensichtlich: Reagieren, Django, Postgres, Nginx, Uwsgi.



Layout anfängliche Benutzeroberfläche



Ich entschied mich für die Benutzeroberfläche und installierte nodejs.org/en/download/package-manager , github.com/facebook/create-react-app , und erstellte dann ein Projekt:



npx create-react-app easytrack


Und ich habe mit dem Layout begonnen. Ich konnte mir von Anfang an nichts Einfacheres vorstellen, als eine Liste von Geschäftslogikobjekten direkt im Programm fest zu codieren und sie als Liste im ul-Tag anzuzeigen. Diese Objekte sind: die Themengruppe, das verfolgte Element, die tatsächlichen Verfolgungsdatensätze für ein bestimmtes Element an einem bestimmten Tag.



Auf der ersten Seite hatte ich thematische Gruppen, und durch Klicken auf eine von ihnen wurde eine Liste von Elementen geöffnet, die verfolgt werden können.



Ich habe auch eine andere Seite erstellt, die eine einfache Tabelle mit Statistiken für die letzten Tage enthielt.



Entwickeln Sie ein Backend



Zu diesem Zeitpunkt war ein Backend erforderlich. Es ist erforderlich, um Objekte in der Datenbank zu speichern, Benutzer zu verwalten und Rechte zu differenzieren. Ich musste Django bereits für meine eigenen Projekte verwenden (natürlich nicht zu seinem logischen Abschluss gebracht), aber es gab eine Schwierigkeit - ich musste Django Rest Framework verwenden, mit dem ich mich überhaupt nicht befasst hatte. Dank des Buches Building Django 2.0 Web-Applications [1]. Ich habe es von Anfang bis Ende durchgearbeitet, bis auf das letzte Kapitel, in dem APIs auf DRF erstellt wurden, habe ich es mit meinen Augen durchgesehen. Im Laufe der Geschichte werde ich mich mehr als einmal an sie wenden.



Nirgendwo hin, öffnete die Dokumentation www.django-rest-framework.org und fing an zu rauchen, und wandte sich auch dem erwähnten Buch zu.



Ich habe die virtuelle Umgebung installiert und aktiviert, Django installiert und ein Django-Projekt im Stammverzeichnis des Projekts erstellt:



virtualenv venv
. ./venv/bin/activate
pip install django
django createproject config


Ich werde den Hauptordner in django umbenennen, so dass durch den Namen alles über seinen Inhalt sofort klar ist. Darin befindet sich ein Python-Modul namens config, was ebenfalls sehr praktisch ist. Frontend-Code im React-Ordner. So entwickelte sich die bis heute erhaltene allgemeine Ordnerstruktur ( siehe Github ).



Erstellen Sie im Stammverzeichnis des Projekts die Hauptanwendung:



django createapp core


Erstellt Klassen von Geschäftslogikmodellen in genau demselben Format, in dem ich sie vorne, Serialisierer und Ansichten fest codiert habe ( Link zum Festschreiben in Github ).

Wir kümmern uns nicht um die Datenbank und verwenden die Standard-SQLite. Über das Admin-Panel habe ich einige Testdatenbeispiele hochgeladen, die ich zuvor vorne fest codiert hatte. Wir versuchen, eine Verbindung zum Frontend herzustellen. python3 manage.py runserver in einem tab, garn start in einem anderen und fuhr.



Der React-Entwicklungsserver wird auf Port 3000 und Django auf Port 8000 ausgeführt. Nichts ist einfacher, als eine Abrufanforderung ('http: // localhost: 8000 / ...') in die Front zu schreiben. Aufgrund von cors-origin hat dies jedoch nicht funktioniert - ein spezieller Schutz, der verhindert, dass eine Site automatisch Anforderungen an einen Server sendet. Deshalb habe ich es ohne nachzudenken in das Backend eingebautdjango-cors-headers ), konfiguriert - es hat funktioniert. Erst dann habe ich geraten, einen Proxy-Abschnitt zu package.json hinzuzufügen und auf das Backend zu zeigen. Dann hat fetch ('/ api / v1 / ...') normal funktioniert und es waren keine zusätzlichen Einstellungen mehr erforderlich.



Anfangs war es furchtbar naiv, weil ich im Konstruktor asynchrone Anfragen gestellt habe - alles hat bei mir funktioniert und okay. Erst später erfuhr ich etwas über Lebenszyklusmethoden, wo Sie diese Art von Arbeit machen können und wo nicht. Jetzt wurden die Elemente angezeigt, neue Elemente konnten erstellt werden.



Implementieren Sie die Benutzerverwaltung und die Trennung von Rechten



Zu diesem Zeitpunkt fehlte lediglich die Trennung der Rechte an Datenelementen: Sie wurden alle im Auftrag eines anonymen entsperrten Benutzers erstellt. Ich musste mich irgendwie darin integrieren, ohne das Django-Ökosystem zu zerstören.



Zunächst habe ich das Login / Passwort im Frontend fest codiert und den Authorization-Header mit dem Wert 'Basic' + base64.encode (Benutzername + ":" + Passwort) erstellt. Dann dachte ich daran, eine Zeichenfolge im Base64-Format zu generieren und sie bei der Eingabe eines Benutzernamens / Passworts auf dem Client zu speichern. Aber es gab große Zweifel an dieser Entscheidung in Bezug auf die Sicherheit, ich wollte etwas anderes ausprobieren.



Ich kramte kurze Zeit im Internet und lernte die JWT-Technologie und das Django-Rest-Framework-SimpleJW-Modul kennenHiermit wurden Authentifizierungsklassen für DRF und Ansichten zum Abrufen eines Token-Paares und zum Aktualisieren eines Zugriffstokens bereitgestellt.



Auf der Frontend-Seite war es ausreichend, ein paar Token in localStorage zu speichern und den Authorization-Header mit dem Wert "Bearer Access-Token" zu übergeben. Schließlich habe ich die Anmeldeseiten angelegt und den Zugriff für nicht autorisierte Benutzer auf die Site mithilfe von Berechtigungsklassen ( Link zum Github-Commit ) geschlossen. Wenn auf der Vorderseite kein Aktualisierungstoken vorhanden war, habe ich zur Anmeldeseite weitergeleitet ( Link zum Github-Commit ).



Dann habe ich es möglich gemacht, mich auf der Site zu registrieren, eine Ansicht im Backend zu erstellen, eine Seite zu erstellen und das Senden von Anfragen einzurichten. In Zukunft war mein Traum, die Kontoaktivierung per E-Mail zu schreiben.



Refactor, fehlende Grundfunktionen implementieren, CI



In diesem Moment stellte sich eine minimal nutzbare Anwendung heraus und ich wollte Feedback sammeln. Ich zeigte die Anwendung meiner Frau und bat sie, sie ohne eine einzige Aufforderung von meiner Seite zu verwenden. Die Registrierung war ziemlich erfolgreich, aber dann lief nicht alles so, wie ich dachte. Dann wurde mir klar, dass Themenordner nicht im Vordergrund stehen sollten, sondern ein Hilfsmittel sein sollten, und wir müssen auch Hinweise hinzufügen, dass wir eine Reihe von Schaltflächen erstellen, damit wir sie einmal am Tag anklicken können. Sie erwartete, dass es wie ein normaler Papiergewohnheits-Tracker mit einer Tabelle sein würde, in der man Zellen übermalen muss. Als ich das merkte, begann ich mit dem Refactoring. Und außerdem gab es etwas zu überarbeiten. Ich habe die Modulstruktur fast von Grund auf durchgesehen.



Zu diesem Zeitpunkt habe ich beschlossen, Schönheit, CSS-Stile und ein ansprechendes Layout hinzuzufügen. Dabei bin ich nicht besonders stark und verlasse mich auf CSS-Frameworks. Die Wahl fiel auf Bulma , basierend auf der Anzahl der Sterne, Downloads von npmjs.com , obwohl ich Bootstrap nicht nehmen wollte. Zumindest habe ich diese Aufgabe gemeistert.



Parallel dazu habe ich die Backend-Funktionen verbessert. Vollständiges CRUD gemacht. Der Traum, die Registrierung per Mail zu bestätigen, wurde ebenfalls wahr. Ich habe die Funktionen des Versendens von Briefen herausgefunden und die Möglichkeit erhalten, alles über einen Debug-Mailserver zu debuggen.



python -m smtpd -n -c DebuggingServer localhost:1025


Für die Bereitstellung habe ich ein Junk-Google-Konto eingerichtet und es geschafft, das Versenden von Briefen per Google Mail einzurichten.



Was die Testabdeckung für das Backend betrifft, hat alles für sich ganz gut geklappt, aber für das Frontend ist alles bisher völlig träge. Aber ich verzweifle nicht, plötzlich wird es sich als angepasst herausstellen.



Der nächste Schritt war das Einrichten von CI. Ich habe GithubActions gestartet, um die Tests auszuführen, die Konfigurationskonstruktoren zum Ausführen verwendet, es ein wenig optimiert und fertig.



Generieren Sie Einstellungen für die Produktionsumgebung



Nachdem ich den Code und die kleinen Details der Logik kurz in Ordnung gebracht hatte, musste ich mit der Erstellung der Produktionskonfiguration beginnen. Dafür wurde ich von demselben Buch inspiriert [1]. Ich habe die Django-Konfigurationsdateien, Python-Abhängigkeiten, in 3 Teile aufgeteilt ( Link zum Github-Commit ):





  • gemeinsam - alles, was Sie für jede Umgebung benötigen
  • dev —
  • prod —


, .



uwsgi, nginx , dockerfile, .



[1] «1 — 1 », , , . phusion/baseimage, Ubuntu, .



, , postgres, . ( Github).



production-



, [1], AWS, . , - . , , , , . Free Tier, , , ? .



, AWS - , . , . , ECS.





Elastic Container Service



Ich habe gesehen, dass Sie mit dem Builder für Github-Aktionen eine Konfiguration für eine kontinuierliche Containerbereitstellungsaufgabe in AWS ECS erstellen können. Angenommen, ich habe mich mit diesem Service befasst und festgestellt, dass ich in der lokalen Konsole einen Cluster erstellen, eine Aufgabendefinition erstellen und den Container beschreiben muss, nachdem ich zuvor sein Image in einem anderen AWS ECR-Service gespeichert habe, nämlich Dockerhub nach Funktion. Die Konsole bot zwei Arten von Clustern: Fargate und EC2. Die erste Technologie ist vollständig serverlos, dh wir starten einfach den Container und die Laufzeit kümmert sich um alles. Container in einem Cluster des zweiten Typs werden auf ihrer eigenen Instanz der virtuellen Maschine in der Cloud ausgeführt. Da ich lange nicht darauf eingehen wollte, habe ich einen Cluster basierend auf Fargate erstellt. Aber ich stieß auf die Tatsache, dass ich keine geheimen Werte an den Container übergeben konnte,Aus diesem Grund fiel die Aufgabe ständig.



Während ich versuchte, den Container in einen funktionsfähigen Zustand zu versetzen, arbeitete der Cluster mehrere Stunden und Geld wurde mit der Zahlung für Dienstleistungen zu meinem Tab hinzugefügt. Die Technologie selbst hat sich als bezahlt erwiesen und gilt nicht für Free Tier. Ich zahlte den Cluster aus und beschloss, die Zahlung etwas später zu erledigen. Ich habe in der Dokumentation gelesen, dass Sie für die Verwendung von ECS zusätzlich zu EC2 keine zusätzlichen Gebühren zahlen müssen, außer für die Verwendung von EC2-Ressourcen. EC2 wird jedoch von Free Tier abgedeckt, und ich habe beschlossen, diesen Pfad auszuprobieren.



AWS-Support



Am Ende hat mich jemand angelogen und mir etwas mehr Geld für diese Konfiguration berechnet. Insgesamt 0,32 $, wenn auch ein wenig, aber immer noch eine Schande. Dann schrieb ich zur Unterstützung, dass ich Schwierigkeiten mit dem Setup hatte und die ganze Zeit dachte, dass ich in die Free Tier passe, aber nichts hat für mich geklappt, und das Geld wurde abgezogen. Ich bat um Hilfe. Als Antwort auf meinen Anruf antworteten sie glücklich und gaben einen Gutschein über 1 USD, der alle unerwarteten Ausgaben abdeckte. Schön.



Infolgedessen musste ich diesen Containerservice vergessen und EC2 in seiner reinsten Form beherrschen.



Elastic Computing Cloud



EC2 — . Free Tier 750 . , , - , .



[1] docker-machine, . , EC2. docker .



, dockre-machine create… EC2. docker-compose up -d . 80 . , «Public DNS» , .





Relational Database Service



AWS RDS. . , ( postgres) , Free Tier, . , , .



Simple Email Service



Ich musste mich auch der Tatsache stellen, dass die Briefe nicht verschickt wurden. Tatsache ist, dass alle Mail-Dienste IPs verbieten, die mit EC2-Instanzen übereinstimmen, um Spam entgegenzuwirken. Es war unbedingt erforderlich, SES zu verwenden. Ein weiterer AWS-Service.



Ich habe es auch konfiguriert und die Postfächer angegeben, von denen aus ich Briefe senden werde. Alles ist in Ordnung. Bisher ist jedoch nicht alles so rosig. Neue Konten befinden sich standardmäßig im Sandbox-Modus, sodass keine E-Mails an unbestätigte Postfächer gesendet werden können. Musste Boxen für meine Beta-Tester bestätigen.





Registrieren Sie eine Domain und konfigurieren Sie ein Zertifikat für den https-Zugriff



Um die Anwendung vollständig zu testen, musste eine https-Verbindung eingerichtet werden. Dies stellte sich als unmöglich heraus, ohne eine Domain zu registrieren. Ich wollte E-Mail-Adressen, Passwörter und Token nicht gefährden, indem ich sie über eine ungesicherte Verbindung übertrage. In diesem Fall habe ich das gesamte Internet durchsucht. Einige Registrare passten nicht, weil es teuer ist, aber irgendwo ist es sehr teuer, außerdem haben viele nur schreckliche Bewertungen. Während ich suchte, verstand das Yandex-Werbenetzwerk, was ich wollte, und bot mir sofort eine Firma an, bei der Sie eine Domain für 39 Rubel registrieren können. Es gab weitere Bewertungen zu diesem Service, daher habe ich ein Konto erstellt, eine kostenlose Domain ausgewählt und für mich registriert.



Um dann über diese Domain auf meine EC2-Instanz zuzugreifen, habe ich eine Hostzone im AWS Route 53-Dienst erstellt, die DNS-Einstellungen registriert und die NS-Einträge im persönlichen Konto des Dienstes neu geschrieben, bei dem die Domain bei Amazon registriert war.



Ich habe den Let's Encrypt-Dienst verwendet, um das Zertifikat zu erstellen. Ich habe bei dieser Konfiguration angehalten: Der lokale Nginx erstellt einen Proxy-Pass für die Containeradresse, der Container dreht sich und ist über Port 8080 zugänglich. Es war nicht schwierig, das Dienstprogramm certbot console zu verwenden, ein Zertifikat zu generieren und https automatisch zu konfigurieren. Zulassen erlauben Sie schließlich den Zugriff auf die virtuelle Maschine an Port 443.



Die Entwicklung des Projekts ist zu einem logischen Abschluss gekommen



, . , , SES , . , . , , , , , , , , . , , . :





  • , , . .
  • -
  • ,
  • , -


— , , . React , AWS, , , .



Aber die Hauptrealisierung ist, dass einer auf dem Feld überhaupt kein Krieger ist. Ich habe über zwei Monate an diesem Projekt gearbeitet, viele Stunden in meiner Freizeit ... Und weißt du was? Ich habe noch nicht so schrecklich genäht. Es fällt auf, dass je älter man wird, desto weniger der Wunsch, etwas "einfach so" zu lernen, desto weniger der Wunsch, viel an einigen Dingen zu arbeiten, die "nur interessant" sind. Gleichzeitig stellen Sie jedoch fest, dass es mehr Möglichkeiten gibt, etwas zum Guten und zum Nutzen zu tun. Sie beginnen, gezielte Anstrengungen, Teamwork sowie Entspannung und Zeit mit engen Menschen zu schätzen.



Code auf Github .



Links



  1. Erstellen von Django 2.0-Webanwendungen