Wie lade ich in Django 1.10 ein Bild von der Festplatte per Django Command hoch?

Für den Fall, dass man ein Bild in eine Django Applikation uploaden möchte, gibt es unzählige Tutorials – kniffelig wird es dann ein bisschen, wenn man ein Bild von der Festplatte des Servers, auf dem die Applikation läuft, mittels Django Command hochladen möchte. In meinem Beispiel importiere ich Bilder per Cronjob aus einem anderen Programm. Bisher ging der Upload auch ohne Probleme, aber seit Django 1.9 oder 1.10 wurde das Sicherheitskonzept geändert – man darf keine Dateien mehr ausserhalb des Media_Path Kontextes hochladen (Suspicious File Operation. Um das Problem zu umgehen, muss man das “normale” Fileobject, welches man normalerweise dann an das Model übergeben würde, in den Django File Wrapper packen. Dazu importiert ihr diesen Wrapper wie im Beispiel unten, übergebt den realen Pfad zum Bild und, und das ist nun wichtig, übergebt per “name” Parameter einen beliebigen Dateinamen, mit dem diese Datei dann im “Upload Prozess” von Django ankommt. Nun müsst ihr das “image” Objekt einfach nur an den Image Parameter eures Models hängen, und schon klappt das Einspielen der Datei wieder. Bei mir war es tatsächlich der fehlende “name” Parameter, der mich in die Verzweiflung getrieben hat 🙂

from django.core.files import File
image = File(open("[PATH_TO_REAL_FILE]", "rb"), name="[SOME_FILE_NAME]")

[Quicktip] Wie kann ich alle installierten Python pip Packages upgraden?

Über einen kleinen Umweg kann man auf der Bash ganz einfach alle aktuell installierten pip Pakete updaten / upgraden:

pip freeze | sed -e 's/==.*//g' > upgrade.txt
pip install --upgrade -r upgrade.txt
rm upgrade.txt

Das Script lässt sich alle installierten Pakete ausgeben, entfernt das “==[Versionsnummer]” hinter dem Namen und packt diese Liste in die Datei upgrade.txt. Anschließend wird diese Datei bei einem “pip upgrade” als “requirements.txt” übergeben und mit dem upgrade Befehl ausgeführt.

Readme driven Design – das etwas andere Pattern

Letzte Woche fiel mir ein sehr interessanter Beitrag (How I Develop Things and Why) zum Thema Entwicklungsstil in die Hände. Der Autor, Kenneth Reitz, vertrat dabei die Meinung, dass man alles sinnvoll designen sollte. Das mag jetzt zwar logisch klingen, ist es aber nicht. Wenn Entwickler von Design sprechen, dann ist meist das Design für den Endkunden gemeint. Die gleichen Regeln sollten aber auch für alle anderen gelten. Sprich, auch ein API oder eine Library sollte intuitiv und nutzerfreundlich sein.

Keneth, selbst ein bekennender Python Fan, geht darauf am Beispiel der http Library für eben diese Sprache ein. Sie tut zwar was sie soll, nervt den Entwickler aber mit unzähligen kryptischen Parametern und viel Schreibaufwand für einfachste Aufgaben. Um diesen Umstand zu verbessern, hat er eine Library geschrieben, die als Schnittstelle zwischen dem Entwickler und der ursprünglichen Library sitzt – spirch, ein Wrapper.

Und somit kommen wir zum Kern dieses Beitrages: Als Designphilosophie für diesen Wrapper wählte er das “Readme driven design”. Häh? So in etwa habe ich auch geschaut, als ich es zum ersten mal las. Das Prinzip ist aber recht sinnvoll: in der normalen Entwicklung fängt man mit einer simplen Idee an, baut das entsprechende API und alles ist toll. Nachdem die Grundfunktionen stehen, erweitert man das ganze, passt das API ein bisschen an, refactored ein bisschen, wieder wird das API angepasst usw. Irgendwann hat man zwar eine Library (bzw. ein Tool), die alles mögliche kann, was aber wiederum mit dem ursprünglichen API-Design nicht mehr realisierbar gewesen wäre. Heraus kommt dann ein Konstrukt aus undurchsichtigen Parametern und umständlichen Vorgehensweisen, um das gewünschte Ergebnis zu erhalten.

Die bessere Alternative ist nun folgende: man schreibt zuallererst die Readme Datei inkl. ausführlicher Syntax und Beispielen – genau so, als ob das Stückchen Software bereits existieren würde und fertig wäre. Und erst dann beginnt man mit der Umsetzung. Der Vorteil ist nun, dass man das API so designt hat, wie man gern damit arbeiten würde – unabhängig von auftretenden Hürden und Problemen. In der Regel sollte ein großer Teil der Entwickler in dieser Hinsicht ein gleiches Verständnis von “leicht” haben. Hinzu kommt: man “überdesignt” nicht – denn der Funktionsumfang ist ja nun genau definiert.

Wie man bereits feststellen kann, eignet sich diese Methode natürlich nicht für große Projekte – dafür macht sie für kleine Scripte oder Libraries umso mehr Sinn.

Was haltet ihr davon? Sinnvoll, oder Quatsch? Oder konntet ihr bereits Erfahrung damit sammeln?