PROJET AUTOBLOG


Sam et Max

source: Sam et Max

⇐ retour index

Permettre de télécharger un fichier proprement avec Django et nginx

dimanche 26 mai 2013 à 09:07

À un moment vous allez devoir proposer à vos utilisateurs de télécharger un fichier. Mais Django n’est pas du tout fait pour streamer des données, et du coup lui laisser cette tâche est un gros gouffre à performance qui va bloquer un de vos workers pendant tout le transfert.

Seulement parfois, il faut quand même générer le fichier via Django, ou au moins checker des permissions, bref, faire un traitement quelconque du côté du code Python. Comment faire alors ?

La solution est le header X-Accel-Redirect :

from django.http import HttpResponse
 
# ici ou pourrait mettre @login_required si on veut
def telecharger_fichier(request):
    # Faire un truc ici qui génère le fichier
    # ou qui récupère un fichier existant.
    # l'important est d'avoir le chemin ABSOLU du fichier
    chemin_vers_fichier = get_chemin_absolu()
 
    # On crée la réponse à la main
    response = HttpResponse() 
 
    # On laisse nginx s'occuper de détecter le mimetype
    del response['content-type'] 
    # On met un header que nginx va comprendre comme "sert le fichier à ma place"
    response['X-Accel-Redirect'] = chemin_vers_fichier
    return response

Et voilà, vous pouvez plugger telecharger_fichier comme vue n’importe où dans urls.py. Quand nginx va voir X-Accel-Redirect, il va servir le fichier automatiquement. Django lui, n’a a gérer que cette vue très légère et passe tout de suite la main au serveur en front.

Afin de rendre votre setup plus sécurisé, mettez la même url que vous avez dans urls.py dans votre fichier de conf nginx :

location /url/de/urls.py/pour/télécharger/les/fichiers {
    internal; # interdit l'accès au fichier depuis l'exterieur du serveur
    alias /chemin/vers/le/dossier/contenant/les/fichiers/;
}

Il existe d’autres headers selon les serveurs en front (WSGI, lighttpd, etc) et parfois en développement, on peut vouloir servir le fichier via Django quand même pour éviter d’installer nginx. L’application django-sendfile fournit des fonctions pour chacun de ces cas d’utilisations, car même si c’est facile à coder, il faut être feinéant.

flattr this!

Plus besoin d’images pour les smileys grâce à Unicode

samedi 25 mai 2013 à 16:03

Maintenant ça passe partout ce genre de truc. Et c’est dingue ce qu’ils ont réussi à stuffer dans cet encoding.

Des formes géométriques :

Des tas de faces :

—————

Grace au support absolument minable de l’encoding de wordpress, cet article est à moité tronqué. Merci codeur PHP de merde qui n’a jamais su gérer le texte correctement de ta putain de viiiiiiiiiiiiiiie.

Afin de pouvoir lire l’article en entier, je l’ai déporté sur 0bin. Putain.

Moralité, non en fait on ne peut pas utiliser ces smileys partout. Les navigateurs les supportent, les fonts sont sur vos systèmes, les OS les supportent. Mais les développeurs sont toujours trop cons. 10 ans bordel, wordpress a 10 ans et des millions de users. Vous pourriez penser qu’ils font au minimum le traitement des chaînes de caractères correctement, non ? Je sais pas, un blog, le principe, c’est pas de TRAITER DU PUTAIN DE TEXTE, MERDE ?

flattr this!

Forcer une identity SSH pour un host en particulier

vendredi 24 mai 2013 à 12:25

Vous avez accumulé un certain nombre de clés SSH, et pour certains serveur ou certains sites Web (github, bitbucket…), vous voulez utiliser une clé SSH et pas une autre. Ce serait en effet dommage de pusher votre commit Git avec la mauvaise identité.

Sous unix, le fichier ~/.ssh/config est votre ami, rajoutez lui :

Host Un alias pour l'host
HostName Une IP ou un nom de domaine pour l'host
User votre nom d'utilisateur
IdentityFile le fichier de clé public à utiliser

Par exemple :

Host bitbucket.org
HostName bitbucket.org
User sam
IdentityFile ~/.ssh/sam.pub

Host local-dev
HostName 192.169.0.10
User dev
IdentityFile ~/.ssh/local-dev.pub

On peut créer plusieurs Host pour le même hostname, avec des résultats intéressant quand on a plusieurs identités en ligne.

flattr this!

Avez vous une méthode “propre” pour jouer avec des Objets du model sans les sauvegarder en BDD sur #Django ?

jeudi 23 mai 2013 à 09:53

Mais oui cher interlocuter du Web.

Créer un fichier “settings_test.py” à côté du fichier de settings, qui contient ça:

from settings import *
 
DATABASES['default'] = {
    'ENGINE': 'django.db.backends.sqlite3',
    'NAME': ':memory:',
}

Et lancer les commandes ./manage.py avec --settings=settings_test :

Par exemple :

./manage.py shell --settings=settings_test
 
./manage.py runserver --settings=settings_test

Et voilà, toute manipulation va automatiquement sauvegarder les données en mémoire vive, et pas dans votre base de données initiale. Elles seront perdues à chaque redémarrage.

D’une manière générale, souvenez vous que vous pouvez faire autant de configurations alternatives et même dynamiques que vous le souhaitez avec les fichiers de settings : c’est juste du Python.

Si vous avez besoin des données de votre base de données initiale, vous pouvez faire une copie de la base de données et changer DATABASES pour pointer sur cette copie. Du coup vous manipulerez votre copie, et pas la base de données initiale.

Enfin, on peut manipuler plusieurs bases de données en même temps en faisant plusieurs entrées dans DATABASES (une ‘default’, une ‘test’, une ‘prod’, etc), par exemple :

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'USER': 'postgres',
        'PASSWORD': 'secret of mana'
    }
    'test': {
    'ENGINE': 'django.db.backends.sqlite3',
    'NAME': ':memory:',
    }
}

On peut alors spécifier la base de données à utiliser, soit par paramètre de ./manage.py (--database=bdd_a_utiliser), soit directement dans le code de manipulation de l’ORM avec using :

>>> Model.objects.all() # tape dans le BDD par défaut
>>> Model.objects.using('test').all() # tape dans la bdd de test
>>> mon_model.save(using='test') # sauvegarde dans la bdd de test

flattr this!

Ça ferait de très bons noms de serveur…

mercredi 22 mai 2013 à 18:46

Non ?

flattr this!