manage.py – Sam & Max http://sametmax.com Du code, du cul Wed, 23 Dec 2020 13:35:02 +0000 en-US hourly 1 https://wordpress.org/?v=4.9.7 32490438 Ecrire une commande Django http://sametmax.com/ecrire-une-commande-django/ http://sametmax.com/ecrire-une-commande-django/#comments Wed, 04 Dec 2013 07:01:44 +0000 http://sametmax.com/?p=7729 manage.py : c'est portable d'un projet à l'autre et ça permet d'utiliser l'ORM et les templates sans réglage puisqu'on a accès à tous les settings, automatiquement.]]> Quand vous avez à faire un script pour un projet Django, il est pratique de l’avoir sous forme de sous-commande de manage.py : c’est portable d’un projet à l’autre et ça permet d’utiliser l’ORM et les templates sans réglage puisqu’on a accès à tous les settings, automatiquement.

Malheureusement le wrapper de Django destiné à cela date un peu, il est plutôt lourd, pas très souple et utilise des pratiques qui ne sont plus au goût du jour depuis quelques années. Rien de rédhibitoire, mais tout de même.

D’abord, il faut placer sa commande dans un fichier portant le nom de la commande, et dans un package management.commands d’une de vos apps.

Par exemple, si vous voulez faire une commande “nettoyer_godmichets” dans l’application “sex_shop”, il faudra la mettre bien profondément dans le tréfonds de votre projet :

racine
│   ├── sex_shop
│   │   ├── management
│   │   │   ├── commands
│   │   │   │   ├── nettoyer_godmichets.py
│   │   │   │   ├── __init__.py
│   │   │   │   └── __init__.pyc
│   │   │   ├── __init__.py

Notez les fichiers __init__.py, indispendables sinon votre commande ne sera pas trouvée. Oh, et ‘sex_shop’ doit être dans INSTALLED_APPS.

Ensuite, votre commande doit être une classe héritant de BaseCommand. Sa méthode handle() sera appelée automatiquement au lancement de la commande.

from django.core.management.base import BaseCommand
from sex_shop.models import Godmichet

class Command(BaseCommand):

    def handle(self, *args, **options):
        for god in Godmichet.objects.all():
            god.clean()

Et vous pouvez lancer la commande :

./manage.py nettoyer_godmichets

Néanmoins généralement on voudra avoir un peu de décorum.


from optparse import make_option

from django.core.management.base import BaseCommand
from sex_shop.models import Godmichet, Marque


class Command(BaseCommand):

    # ici on peut mettre un message d'aide
    help = 'Fait briller dard dard les dards'

    # optionellement une aide pour les arguments
    args = 'marque1, [marque2], marque3'

    # On peut ajouter des options passables à la commande
    option_list = BaseCommand.option_list + (
        make_option('--dry-run',
            action='store_true',
            dest='dry_run',
            default=False,
            help='Affichage uniquement, aucune action réelle'),
        )

    def handle(self, *args, **options):

        # on retrouve dans args les arguments positionnels de la commande

        if not args:
            for god in Godmichet.objects.all():
                # Plutôt que print(), on peut utiliser ce wrapper
                # pour ecrire sur le terminal. Cela permet de bénéficier
                # automatiquement de l'option --verbosity
                self.stdout.write('Processing %s' % god.name)

                # La valeur des options est passée via kwargs.
                if not options['dry_run']:
                    god.clean()
        else:
            # l'utilisateur a passé des marques ? On nettoie que les gods
            # de ces marques...
            for marque in args:
                try:
                    gods = Marque.objects.get(name=marque).gods.all()
                    for god in gods:
                        self.stdout.write('Processing %s' % god.name)

                        if not options['dry_run']:
                            god.clean()

                except Marque.DoesNotExist:
                    # si la marque n'existe pas, on fait une erreur
                    # ceci arrête le script, retourne un code d'erreur 1
                    # et met le texte en rouge
                    raise CommandError('La marque %s n'existe pas' %s marque)

Et voilà, votre commande accepte maintenant optionnellement qu’on lui passe une liste de marques et/ou une option --dry-run:

./manage.py nettoyer_godmichet devilmaycry choucroutebestfriend --dry-run

En plus de ça, la commande accepte automatiquement :

  • --help
  • --verbosity
  • --settings
  • --pythonpath

Qui ont le même effet que sur toutes les commandes django officielles.

]]>
http://sametmax.com/ecrire-une-commande-django/feed/ 5 7729
Changer le mot de passe du super utilisateur django en ligne de commande http://sametmax.com/changer-le-mot-de-passe-du-super-utilisateur-django-en-ligne-de-commande/ Sun, 01 Dec 2013 00:20:18 +0000 http://sametmax.com/?p=8020 Vous avez oublié ce maudit mot de passe ? Impossible de se connecter à l’admin ?

./manage.py changepassword username

Pas besoin d’être root.

Souvenez-vous aussi que vous pouvez quasiment tout faire depuis un shell en faisant :

./manage.py shell

Ce qui vous permet d’importer les modèles de vos apps et faire toutes les querys que vous voulez.

]]>
8020
Créer un super utilisateur Django sans prompt http://sametmax.com/creer-un-super-utilisateur-django-sans-prompt/ http://sametmax.com/creer-un-super-utilisateur-django-sans-prompt/#comments Wed, 20 Nov 2013 09:23:12 +0000 http://sametmax.com/?p=7981 syncdb sans prompt, et donc pas de création de superutilisateur...]]> Automatiser le déploiement d’un projet Django passe par un syncdb sans prompt, et donc pas de création de superutilisateur :

./manage.py syncdb --noinput

Vous pouvez bien entendu toujours en créer un plus tard, avec :

./manage.py createsuperuser --username=vous --email=votre_mail

Mais il va vous prompter pour saisir le mot de passe ou alors mettre un mot de passe inutilisable automatiquement, ça ne résout pas votre problème. Une astuce consiste à le créer avec un code Python et à piper ce code dans un shell :

echo "from django.contrib.auth.models import User; User.objects.filter(username='vous').count() or User.objects.create_superuser('vous', votre_email', 'mot_de_passe')" | ./manage.py shell

Personnellement je colle ça dans une tache fabric. Parfois on peut même générer le mot de passe aléatoirement avec un uuid qui est printé localement.

]]>
http://sametmax.com/creer-un-super-utilisateur-django-sans-prompt/feed/ 5 7981