Leçons du jour, et des jours précédents
Vous lirez ici des petites notes personnelles prises au gré de mes recherches répétées sur mon moteur de recherche préféré, pour justement me répéter moins.
-
Créer des index uniques sur plusieurs colonnes nullables
Par défaut, PostgreSQL suppose que deux valeurs NULL sont distinctes. Ça pose problème quand on veut des contraintes d’unicité sur plusieurs colonnes dont certaines sont nullables.
Donc par exemple, si j’ai une contrainte d’unicité sur les colonnes a, b, c, d, ceci fonctionne :
insert into machin values ("a","b","c", null), ("a","b","c", null);
Mais moi c’est pas ça que je veux et ça fait au moins deux fois que je veux pas ça.
On peut lui dire que deux valeurs
NULL
sont identiques avec la clauseNULLS NOT DISTINCT
à partir de PostgreSQL 15.On peut dire à Django de dire à PG que les
NULL
sont identiques avec le kwargnulls_distinct=False
dans la création de contrainte unique :class Meta: constraints = ( models.UniqueConstraint( name="unicity_by_perimeter_and_type", fields=( "perimetre_region", # nullable "perimetre_departement", # nullable "perimetre_arrondissement", # nullable "annee", "type", ), nulls_distinct=False, # !!!! OHHHHH SO CLEVEER ), )
La doc Django sur
UniqueConstraint
qui mentionne bien le kwargnulls_distinct
-
Liste des icônes Wagtail
-
Routes vers l’admin Django
Comment faire des liens vers des listes ou des formulaires dans l’admin Django ? Je suis allée voir dans le code source.
"admin:%s_%s_add" % (opts.app_label, opts.model_name) "admin:%s_%s_changelist" % (self.opts.app_label, self.opts.model_name),
-
Faire un dump et l´importer proprement en PostgreSQL
Faire un dump sans les infos de propriétaire et de privilèges :
pg_dump --format=custom --no-owner --no-privileges lenomdemabase > lenomdemabase.pgdump
Restaurer le dump :
pg_restore --format=custom --no-owner --no-privileges --dbname lenomdemabase --username lenomdemonuser lenomdemabase.pgdump
Dans le
pg_restore
la partie--username lenomdemonuser
est TRÈS importante.Sinon le user propriétaire des tables sera
postgres
et ça va poser des problèmes. -
Manipuler des adresses IP en Python
La lib standard Python contient un module permettant de manipuler des adresses IP.
-
Valeur intelligible d’un champ de modèle à choix multiples dans Django
Pour avoir la valeur “jolie” d’un champ de modèle de type “liste déroulante”, avec un paramètre
choices=
: il existe la méthode magiqueinstance.get_TRUC_display()
.Dans un template :
{{ mon_instance.get_status_display }}
-
Capture d’écran vidéo sous OSX
Cmd + maj + 5
(Capture d’écran classique : Cmd + maj + 4)
-
Numéros de téléphone réservés au cinéma
Des numéros non attribuables sont réservés par l’ARCEP afin de les utiliser dans des films ou des séries.
Les portables et chaque région ont une plage allouée :
- 01 99 00 .. ..
- 02 61 91 .. ..
- 03 53 01 .. ..
- 04 65 71 .. ..
- 05 36 49 .. ..
- 06 39 98 .. ..
-
str.title() marche aussi si les mots sont séparés par des underscore
"oh_my_snake_case".title() = "Oh_My_Snake_Case"
C’est utile si on veut convertir du snake_case en CamelCase. Après il ne reste plus qu’à supprimer les
_
. -
Justify-self n'a pas d'effet sur un élément flexbox
Je vais bien finir par m’en souvenir.
Si je veux un effet de ce type :
A B C D
Je dois donner
margin-left: auto
à D. -
Git reset mais garder les modifs non commitées
git reset --keep
May your uncommited changes never go missing.
-
Ce domaine reçoit-il des e-mails ?
dig mx ledomaine.net
-
pip-compile échoue et ne me dit pas pourquoi
Parfois
pip-compile
se prend les pieds dans le tapis avec une erreur toute nulle :failed to parse pyproject.toml
Pour avoir une erreur claire :
pip install -e .
Aujourd’hui, le problème, c’était le répertoire du projet Django à côté de deux répertoires qui cassaient l’autodiscovery.
Pour résoudre, deux possibilités de modif du package.toml :
[tools.setuptools] py-modules=[]
ou bien :
packages = ["mon package"]
-
Réparer un arbre wagtail
Souvent j’ai cette erreur quand je manipule “programmatiquement” des pages Wagtail :
NoneType object has no attribute _inc_path
Pour ça :
mana fixtree --full
(NB.
mana
est un alias pourpython manage.py
🧙) -
Django ORM - filter prefetch_related
from django.db.models import Prefetch Person.objects.filter(...) .prefetch_related( Prefetch( "order_set", queryset=Order.objects.filter(...), to_attr="orders_filtered" ) )
-
Décimaux en Python
Decimal(48.33) # non Decimal("48.33") # oui
-
Attraper une ou plusieurs exceptions en Python
try: # ... except ZeroDivisionError as e: print(e) raise # re raise that exception except ValueError: print("Write a number") finally: cleanup()
-
Ligne parfaite
Théoriquement, 66 caractères, soit environ 33 em.
Paraît-il.
-
Numéros de spam
Ne pas répondre :
- 01 62
-
01 63
- 02 70
-
02 71
- 03 77
-
03 78
- 04 24
-
04 25
- 05 68
-
05 69
- 09 48
- 09 49
-
Empêcher le push sur main
git config branch.main.pushRemote nope
-
Trouver un élément x qui remplit une condition dans l'itérable `trucs`
next(x for x in trucs if condition)
-
Sécurité des iframes
Option historique :
X-frame-options
.- Accepte DENY : impossible d’inclure le site dans une iframe ;
- ou SAMEORIGIN : seulement possible d’iframer le site depuis lui-même.
Option actuelle : CSP frame-ancestors
Utiliser cette option de CSP en combinaison avec
X-frame-options: DENY
.Compatible chrome, firefox, safari 10+, Edge 15+, mais incompatible IE.
Interroger les usagers/logs pour connaître les navigateurs. -
Pip freeze
pip freeze
affiche toutes les dépendances pip installées dans le venv. -
Hit me up
hit me up = contactez-moi
-
Docker-compose build . - qu'est-ce que ça fait donc ?
Dans un fichier docker-compose :
build . image: truc
Build l’image à partir du Dockerfile, et la tague “truc” pour économiser le temps de build.
-
Docker for mac — parler à l’hôte depuis le conteneur docker
host.docker.internal
-
CORS - cross origin resource sharing
Par défaut, les requêtes CORS n’envoient pas les cookies.
Pour envoyer les cookies :
xhr.withCredentials = true
.Mais ça ne marchera pas si
Access-Control-Allow-Origin
vaut*
.Aussi : dans l’en-tête
Access-Control-Allow-Origin
, il faut inclure le scheme. -
Raccourcis clavier de navigation
Passer d’un onglet à l’autre : ctrl + tab
Passer d’une fenêtre à l’autre dans la même app : cmd + `
-
Git push force with lease
git push --force-with-lease
Évite d’écraser le travail des autres quand on fait un
git push --force
.Plus exactement,
--force-with-lease
n’écrase pas un historique qui n’aurait pas été récupéré au préalable depuis le distant.On combine avec
--force-if-includes
pour en outre vérifier que l’état du dépôt distant a été appliqué à notre historique local.Je viens d’ajouter un alias :
git config --global alias.pfl "push --force-with-lease --force-if-includes"
(MAJ 14 novembre 24 :
- ajout –force-if-includes
- ajout explications )
-
PostgreSQL en ligne de commande
\dt
liste les tables (SHOW TABLES
)- \d <table> <=> DESC <table>
- \x eXpanded display ~ \G de MySQL
- \list <=> show databases
-
Centrer horizontalement et verticalement
.parent { display: flex; justify-content: center; align-items: center; }
-
Faire un point médian sur Mac
Alt + Maj + F
-
Annuler le dernier commit git
git reset HEAD^
- On rembobine le curseur d’un cran.
- Si en plus on veut supprimer les modifications : ajouter
--hard
.
-
Afficher la liste des branches et leur dernière modification
for k in `git branch | perl -pe s/^..//`; do echo -e `git show --pretty=format:"%Cgreen%ci %Cblue%cr%Creset" $k -- | head -n 1`\\t$k; done | sort -r
-
Pour déplacer des fichiers plus vite
cp app/services/metadata/elasticsearch{,_images}_synchronizer.rb
-
Changer le mot de passe root MySQL
Ou le mot de passe de n’importe qui en fait.
mysqladmin -u root password NEWPASSWORD
-
Magento - fusion des CSS cassée
Magento introduit des erreurs de syntaxe si les CSS à concaténer contiennent des url() avec des quotes.
Pas bien :
background: #eee url( '../images/default/grid/loading.gif' ) no-repeat 5px 5px;
Ça donne ceci :
background: #eee url('https://my-domain.com/js/extjs/resources/images/default/grid/loading.gif'') no-repeat 5px 5px;
Certains navigateurs s’emmêlent les pinceaux avec les deux guillemets finaux.
Il faut veiller à déclarer les URL relatives sans apostrophes :
background: #eee url(../images/default/grid/loading.gif) no-repeat 5px 5px;
-
Active Record - faire des jointures imbriquées avec conditions
Try to change your where clause :
Publication .joins( :publication_contributors => :contributor ) .where( :publication_contributors => {:contributor_type => "Author"}, :contributors => {:name => params[:authors]} )
ActiveRecord api is not extremely consistent here: the arguments for
where
do not work exactly as those forjoins
. This is because the arguments forjoins
do not reflect the underlying SQL, whereas the arguments for where do.where
accepts an hash whose keys are table names, and values are hashes (that themselves have column names as keys). It just prevents ambiguity when targetting a column that has the same name in two tables. -
Dnsmasq sous Homebrew - mais où sont les logs ?
Les logs de dnsmasq sont dans
/var/log/system.log
. Donc pour voir ce que dnsmasq a logué :grep dnsmasq /var/log/system.log
Souvent, chez moi, les erreurs sont assez claires :
dnsmasq[52895]: error at line 1 of /etc/dnsmasq.d/tea-solr dnsmasq[52895]: FAILED to start up
-
Développer en parallèle sur une gem et sur un projet qui utilise cette gem
Pour travailler sur la gem locale :
bundle config local.GEM_NAME /path/to/local/git/repository
Pour lister les configs de gemmes locales :
bundle config
Pour supprimer une config de gemme locale :
bundle config --delete local.GEM_NAME
-
Zsh - erreur "no matches found"
Mentionné dans ce billet : quand je veux invoquer une tâche rake avec des arguments, comme ceci :
rake my:task:name[my_arguments]
J’obtiens une erreur “zsh: no matches found”, et c’est chiant. Je suis obligée d’écrire ça :
rake "my:task:name[my_arguments]"
La solution est de modifier le fichier
.zshrc
pour dire à zsh de ne pas partir en erreur s’il ne trouve pas de match…Dans le
.zshrc
:unsetopt nomatch
-
Restaurer un fichier supprimé
Trouver le commit qui a servi à supprimer le fichier :
git rev-list -n 1 HEAD --
Restaurer le fichier :
git checkout ^ --
-
Sauvegarder les résultats de request.sql dans result.txt
mysql -ublabla -h le-host -p --batch lenomdeladb < request.sql > result.txt
Juste pour me souvenir que ça marche, et que ce n’est pas la peine de re-googler à chaque fois.
-
Rechercher et remplacer avec sed dans plusieurs dossiers
find ./prefixe-du-dossier-* -type f -exec sed -ibak -e 's#search#replace#g' {} \;
-
Vim - astuces de l’estimé collègue deudtens
Au-delà du i pour insérer
i
: insérer là où est le curseur (insert)A
: insérer en fin de ligne (APPEND PUTAIN !)a
: pas intéressant (comme i, mais un caractère plus loin)o
: insertion sur une nouvelle ligneJe copie-colle et c’est ma joie
Copier la ligne :
yy
Couper la ligne :
dd
Coller :
p
-
Git rebase onto
git rebase --onto master oldbase mabranchenow
@tut_tuuut faut la lire à l’envers git rebase —onto A B C je veux appliquer les commits de C jusqu’au branchement avec B au dessus de A
— Yves Brissaud (@crev) 5 novembre 2014
-
Retourner au dossier précédent
Retourner au dossier où on était juste avant :
cd -
Retourner sur la branche précédemment active :
git co -
Rebase sur la branche précédemment active :
git rebase -
-
Commit de fixup
git ci --fixup hashducommit
Pour faire un “amend” à distance lors du prochain
git rebase -i
. -
Git add amélioré
Pour ajouter au prochain commit tous les fichier supprimés du système de fichiers :
git add -u
(
-u
pour update) -
Utiliser zgrep
zgrep -c 9791027900015 *.gz
Compte le nombre d’occurrences de zgrep 9791027900015 dans tous les fichiers .gz du répertoire.
-
Savoir quel .gitignore a .gitignoré un fichier
git check-ignore mon-fichier.sql --verbose
Ne marche que pour git ≥ 1.8.3 sorti en mars 2013.
-
Faire le ménage dans un dépôt git
Supprimer toutes les branches déjà mergées dans la branche courante :
git branch --merged | grep -v "\*" | xargs -n 1 git branch -d
Supprimer toutes les branches déjà mergées dans le master du remote :
git branch -r --merged | grep -v master | sed 's/origin\//:/' | xargs -n 1 git push origin
Supprimer les branches qui existent en local mais pointent sur une branche supprimée du remote :
git fetch -p
(
-p
comme « prune ».) -
Grep sur phpinfo() en ligne de commande
php -r 'phpinfo();' | grep php.ini
-
Éviter d'entrer son mot de passe quand Vagrant démarre avec un montage NFS
Méthode sale si vagrant est le seul programme qui modifie les exports NFS :
sudo chown `whoami`:staff /etc/exports
Il y a une méthode plus « propre » qui consiste à autoriser sans mot de passe certaines commandes normalement réservées au
sudo
. Le seul problème c’est que je n’ai pas trop compris ce qu’il faut faire… -
Ouvrir le dossier courant dans le finder
open .
-
Chercher le mot « bétonnière » dans le dossier courant et les sous-dossiers
grep -r betonniere .
-
Trier une liste de fichiers par taille
du . --max-depth=1 -h | sort -h
ls -Slr
-
Supprimer une branche distante
git push origin :newfeature
-
Renommer une branche
git branch -m oldname newname
Syntaxe simplifiée pour renommer la branche courante :
git branch -m newname
-
Installer une vieille formule avec Homebrew
-
Déployer une branche avec Capistrano
OK :
./bin/cap deploy -s branch=dev/thisismybranch ./bin/cap deploy -S revision=358e81487e467a982d8e85bada99260211b336f8
Risky :
./bin/cap deploy -S revision=devel/thisismybranch
If your local branch is not at the same stage as on origin, you will deploy origin/devel/thisismybranch, but you will tag your local commit devel/thisismybranch.
-
Trouver les fichiers qui contiennent une chaîne donnée
grep -lr 9782848998299 .
Explications :
-l
pour afficher le nom du fichier et pas toute la ligne ;-r
pour chercher dans le dossier courant et dans les sous-dossiers.
Attention à ne pas oublier le
.
à la fin de la commande. -
Requêtes en MongoDB
« where distribution is not null » :
db.ebooks.findOne({distribution: {$ne: null}})
« where distribution is null » :
db.ebooks.count({distribution:null})
Avec des embedded documents ça marche aussi :
db.ebooks.count({"distribution.global":{$ne : null}})
-
Le patch suhoshin et les fichiers .phar
Exécuter le script de vérification :
curl http://getcomposer.org/installer | php
Il y a des chances pour qu’il demande d’ajouter ceci dans un php.ini quelque part :
suhosin.executor.include.whitelist = phar
-
Mettre à jour tous mes submodules git
Oui parce que
git submodule update
ben ça ne marche pas du tout.Ce que je veux faire, en vrai, c’est
git submodule foreach git pull origin master
. -
Oups j'ai oublié de créer ma branche de feature
If you have
...-*-*-*-X-*-*-*-*-A
On branch A and X is the commit where you meant to create a new branch B starting at X you can simply
git checkout A git branch B git reset --hard X
or simply
git branch -m A B git branch -f A X
If, on the other hand, you wanted to start B from a different commit Y, you will need to rebase:
git branch B A git branch -f A X git rebase --onto Y A B
After backing up, of course ;)
-
Trouver un fichier dans un dossier ou sous-dossier d'après un bout de son nom
find -iname *ton-morceau-de-nom*
-
Checkout sur une branche distante
git checkout -t origin/haml
-t
pour « track ». Permet de faire un checkout sur une nouvelle branche nommée « haml », configurée pour suivre la branche « origin/haml ». -
Git rebase ça fait quoi déjà ?
git rebase master
Rebase la branche courante (ici « feature ») sur « master ».
git rebase master feature
Rebase la branche « feature » sur la branche « master ».
(Oui pasque je ne me souviens jamais de l’ordre des arguments…)
-
Supprimer des branches
Pour supprimer une branche locale :
git branch -d the_local_branch
Pour supprimer une branche distante :
git push origin :the_remote_branch
Si quelqu’un a déjà supprimé la branche distante :
git fetch -p
-
Lancer une commande CasperJS
Commande de base :
casperjs --includes=config/config-.coffee,config/client/.coffee test create-new-pn-client.coffee
La variable
test
est un hack qui permet d’inclure plusieurs fichiers de configuration.Pour ignorer les erreurs de certificats HTTPS, ajouter l’option
--ignore-ssl-errors=yes
.