C’est le genre de problème qui arrive très souvent lorsqu’on touche à une base de données, en ajoutant un champ.
Pourquoi ? Parce que par défaut, les champs crées sans paramètres ne doivent pas être vides.
Exemple concret : je veux rajouter pour un modèle, un champ « exemple » :
class Groupe(models.Model):
description = models.CharField(max_length=150)
exemple = models.CharField()
Je fais « makemigration / migrate » et là, horreur : « django.db.utils.IntegrityError: main_groupe__new.exemple may not be NULL »
La solution
Supprimer le dossier « migrations » de l’application concernée
Lancer un migrate --fake-initial qui va « simuler » un migrate, sans essayer de créer les tables
Lancer makemigration nomappli (!! c’est ici que si on oublie le nom de l’appli rien ne se passe !!)
Seconde astuce : supprimer le champ fautif
Lancer migrate : là il va supprimer de la base le champ fautif
Remettre le champ avec blank=True, default=None
Refaire makemigration puis migrate sans préciser le nom de l’appli, comme d’habitude.
Et votre nouveau code sera pris en compte : class Groupe(models.Model):
description = models.CharField(max_length=150)
exemple = models.CharField(max_length=150,
blank=True, default=None)
Oui je sais ça a l’air long, mais en pratique ça prend deux-trois minutes seulement !
Aide ici from django.template import loader
def render_sample(request):
s = loader.get_template(
'alerts/subject.txt'
).render({})
m = loader.get_template(
'alerts/message.txt'
).render({})
SQL
Requête directe
Lancer la console python (Tools » Python console),
puis taper : from django.db import connection
cursor = connection.cursor()
cursor.execute("PRAGMA table_info(langue)")
for c in cursor.fetchall():
print(c)
Autre exemple : from django.db import connection
cursor = connection.cursor()
cursor.execute("delete from app_persongame where person_id=1")
cursor.fetchall()
cursor.execute("update app_persongame set state=1 where person_id=2")
cursor.fetchall()
Sauvegarde / restauration
Lancer via manage.py ([CTRL] + [ALT] + r sous PyCharm) : Sauvegarde :dumpdata -o data.json Restauration :loaddata data.json
Changer un mot de passe
from django.contrib.auth.models import User
u = User.objects.get(username='nomutilisateur')
u.set_password('motdepasse')
u.save()
Multilangue
Créer tous les fichiers en ignorant mes librairies tierces :
makemessages --locale fr --locale en --ignore third_party
Être root. De là, taper : sudo -i -u postgres psql [nom base de donnees] CREATE USER interro WITH PASSWORD 'i';
Très important : lui donner tous les droits sur la base : GRANT ALL PRIVILEGES ON DATABASE "interro" to interro;
Et si l’utilisateur existe déjà : ALTER USER interro WITH PASSWORD 'i';
Changement d’owner des tables
Se connecter à la base. Allez je mets la commande Windows : "\Program Files\PostgreSQL\9.5\bin\psql.exe" -U postgres interro
. De là, taper (j’ai bien mis en gras le nom de l’utilisateur à qui on donne les tables) : SELECT 'ALTER TABLE '|| schemaname || '.' || tablename ||'
OWNER TO interro;' FROM pg_tables
WHERE NOT schemaname IN ('pg_catalog', 'information_schema')
ORDER BY schemaname, tablename;
Et PostgreSQL va sortir une floppée de « ALTER TABLE...« , il suffit juste de les copier/coller dans le prompt pour les appliquer.
Vues Login / logout
– Créer l’URL de login : url(r'^login/$', LoginView.as_view(), name='login'),
– Créer la vue LoginView from django.contrib.auth import views
class LoginView(views.LoginView):
template_name = 'login.html'
def __init__(self):
pass
– Créer l’URL de logout : url(r'^logout/$', LogoutView.as_view(), name='logout'),
– Créer la vue LogoutView from django.contrib.auth import views
class LogoutView(views.LogoutView):
def __init__(self):
self.next_page = '/'
<form action="{% url 'login' %}" method="post" accept-charset="utf-8">
{% csrf_token %}
{% for field in form %}
<label>{{ field.label }}</label>
{% if field.errors %}
{{ field.errors }}
{% endif %}
{{ field }}
{% endfor %}
<input type="hidden" name="next" value="{{ next }}" />
<input class="button small" type="submit" value="Submit"/>
</form>
J’ai eu une discussion avec des fans de Symfony il y a quelques temps. Ils me soutenaient (avec une prétention qui m’a surpris) que Php était de très loin le langage le plus recherché actuellement. Ils se trompaient lourdement. Dire que Php est le langage le plus utilisé, oui. Dire qu’il est le plus demandé, et qu’il le restera, non.
Python est l’avenir
Aucune discussion possible.
Python c’est tout. End of story
Voici le mail que j’ai envoyé récemment à plusieurs de mes clients, et, qui explique la tendance python :
En tapant « most popular development languages » sur google, on voit que :
Enfin je l’ai appris ce matin de la part d’un professeur : deux universités de France retirent Php pour le remplacer par Python cette année (si vous êtes intéressé je vous dirais lesquelles, je n’ai plus en tête les villes de ces universités).
J’imagine les gens de mauvaise foi qui vont aller chercher sur le Web et sortir les deux ou trois sites qui mettent Php devant Python… oui vous allez en trouver, mais en proportion, la plupart des sites expliquent que la tendance d’aujourd’hui c’est Python et JavaScript. Quant à ce dernier, moi qui ai fait quelques sites en NodeJS, je confirme que c’est l’âge de pierre aussi bien côté serveur Web que côté langage JavaScript lui-même… peut être qu’enfin à sa version 6, il fera du scoping normal (lisez ici) déjà rien que ça c’est moisi, sans parler des principes des closures qui empêchent carrément de faire de grosses applications qu’on peut facilement maintenir… là aussi, je ne pourrai jamais convaincre des gens qui ont principalement fait du JavaScript sans avoir essayé aussi intensivement d’autres langages (on ne peut pas comparer dans ce cadre, et toute discussion devient alors impossible)…
Si, comme moi, vous voulez faire des requêtes directement et voir toutes les tables, pour les modifier manuellement, rien de plus simple, il faut juste chercher sur le Web pendant pas mal de temps. Voici la solution pour économiser de précieuses minutes :
Lancer la console python (Tools » Python console)
Taper :
from django.db import connection
cursor = connection.cursor()
cursor.execute("PRAGMA table_info(langue)")
for c in cursor.fetchall():
print(c)
Si vous voulez plus de détail, et que la console a des problèmes avec les accents, voici un code qui remplace les accents par un point d’interrogation :
Taper :
from django.db import connection
cursor = connection.cursor()
cursor.execute("SELECT * FROM langue")
for c in cursor.fetchall():
for d in c:
if type(d) is str:
print(d.encode(
sys.stdout.encoding,
errors='replace'))
else:
print(d)
Et vous obtiendrez un résultat qui pourrait ressembler à : None
b'Russian'
b'ru'
False
b'???????'
False
Dans Facebook il faudra aller dans le coin des développeurs, et créer une application jusqu’à arriver à un écran comme celui-ci :
Même chose pour gmail :
Et enfin la relation dans le code :
Pour terminer : Facebook ne renvoyait pas les emails, lorsqu’on s’authentifiait.
C’est un bogue connu depuis que Facebook a modifié son API très récemment.
La solution est ici : editez votre fichier \authomatic\providers\oauth2.py.
Allez à la classe Facebook.
Copiez-collez ce code, qui ne change presque rien (je vous laisse chercher) sauf l’URL user_info_url qui a été modifiée pour la v2.4 : et voilà, il ne vous reste plus qu’à suivre le tutoriel de authomatic avec Django, qui est assez bien fait, et tout devrait fonctionner !
class Facebook(OAuth2):
"""
Facebook |oauth2| provider.
* Dashboard: https://developers.facebook.com/apps
* Docs: http://developers.facebook.com/docs/howtos/login/server-side-login/
* API reference: http://developers.facebook.com/docs/reference/api/
* API explorer: http://developers.facebook.com/tools/explorer
Supported :class:`.User` properties:
* city
* country
* email
* first_name
* gender
* id
* last_name
* link
* locale
* location
* name
* picture
* timezone
* username
Unsupported :class:`.User` properties:
* birth_date
* nickname
* phone
* postal_code
"""
user_authorization_url = 'https://www.facebook.com/dialog/oauth'
access_token_url = 'https://graph.facebook.com/oauth/access_token'
# Correction merci à miohtama :
# https://github.com/peterhudec/authomatic/issues/112
user_info_url = 'https://graph.facebook.com/me?fields=' \
'id,email,name,first_name,last_name,address,gender,' \
'hometown,link,timezone,verified,website,locale,languages'
user_info_scope = ['email', 'user_about_me', 'user_birthday',
'user_location']
Maintenant avec cet exemple, si vous voulez faire des vecteurs et les dessiner avec la brosse en cours, ainsi qu’avec mon article sur l’automatisation de Gimp, vous devriez arriver à faire beaucoup de choses !
Avez-vous déjà entendu parler de Sokoban, le jeu ?
J’ai eu la formidable idée (c’est de l’humour…) de le coder en Python, et encore mieux (c’est encore de l’humour…) de le coder pour pouvoir y jouer en mode console.
\o/
J’ai commencé à développer pour qu’il soit international, donc les commentaires sont pour la plupart en anglais.
La première chose que je voulais faire c’est pouvoir faire des affichages différents. Donc, selon que votre console le supporte ou pas, vous pourrez changer l’affichage :
Voici l’écran, si on veut changer les graphismes (en cliquant sur « + » ou sur « -« ) :
Voici l’écran, si on veut encore changer les graphismes (en cliquant sur « + » ou sur « -« ) :
Le code orienté objet
Les classes de base
Et ensuite le plus important à mon sens : le code orienté objet. J’ai voulu apprendre l’orienté objet de python. J’ai donc crée des classes qui correspondent aux objets de base (dans l’ordre, classe du Sol sans rien, classe du Sol où il faut ranger une pierre, classe Mur, et classe Joueur) :
# Different drawings:
class Ground(object):
def __init__(self):
super(Ground,self).__init__() # Parent call:
class GroundStoneDest(object):
def __init__(self):
super(GroundStoneDest,self).__init__() # Parent call:
class Wall(object):
def __init__(self):
super(Wall,self).__init__() # Parent call:
class Player(object):
def __init__(self):
super(Player,self).__init__() # Parent call:
Classe Level
Et de la même façon j’ai crée la classe Level qui est la plus complexe, et qui contient les fonctions les plus utilisées :
apply_drawings_set()
Calculer les motifs pour dessiner le tableau (oui, oui c’est plus complexe que ça n’en a l’air) ;
draw()
Dessiner les motifs en cours à l’écran ;
register_player_move()
Se souvenir des mouvements du joueur, soit pour pouvoir faire un « undo » (pas implémenté), soit pour pouvoir les sauver pour les rejouer (pas implémenté non plus) ;
move()
Essai de déplacer un objet situé en (x,y) du décalage (add_x, add_y), sachant que le décalage peut être négatif ;
solved()
Test si toutes les pierres sont bien rangées.
Classe LevelsReader
De la même façon, j’ai crée la classe LevelsReader qui lit un niveau, et l’analyse pour voir s’il est un minimum cohérent. Pas la peine d’entrer dans le détail, les fonctions sont suffisamment explicites je pense.
Bibliothèque curses
Et pour terminer, la fonction de la boucle principale qui concerne l’unité curses : def curses_main(stdscr, code). C’est ici qu’on affiche le menu, qu’on attend qu’on tape sur une touche, etc.
Notez bien : le code n’est pas terminé. C’est un début de code, relativement correctement fait. J’ai passé à peine deux jours dessus pour réussir à faire cela, donc ne m’en voulez pas trop, il n’est pas peaufiné, mais il fonctionne.
Si jamais vous l’améliorez, ce serait gentil de me faire parvenir la nouvelle version 🙂
Le lien que tout le monde attend avec impatience, la bave aux lèvres :
Voilà, je viens de me donner un défi. Je l’expliquerai après.
Top chrono : 16:34 – Fini : 16:43
Voici mon problème : j’ai un fichier « index.htm » qui utilise plein de fichiers images. Seulement, tous ces fichiers « images » sont mélangés dans un seul et même répertoire, avec d’autres fichiers qui ne sont pas présents. Je voulais un listing des fichiers présents, et des fichiers pas présents.
9 minutes en python.
Voici mon script, qui n’est pas fabuleux, mais qui fonctionne bien :
1 #!/usr/bin/python
2 # -*- coding: utf-8 -*-
3
4 import os
5
6 path = './img'
7 f = open('./index.htm', 'r')
8 s = f.read()
9 for nom in os.listdir(path):
10 if s.find(nom)>=0:
11 print "Présent - "+nom
12
13 for nom in os.listdir(path):
14 if s.find(nom)<0:
15 print "Absent - "+nom
Bien sûr, il y aurait possibilité de faire ça en shell / bash, mais en python c'est tellement plus sympa 😉
Si ça peut éventuellement aider la communauté, j'en fais un article.
Ci suit un exemple simple. Supposons que vous venez tout juste d’acheter le domaine « p-bor.com » mais vous avez beau faire un ping, rien ne fonctionne, parce que malgré que vous l’ayez acheté, il n’est toujours pas actif. En pratique, vous devez attendre et revenir de temps à autre essayer de le « pinger » pour voir si, enfin, vous arriver à le voir sur Internet.
J’ai une solution plus amusante : il suffit de faire ce script python, qui essaie de faire la correspondance entre une adresse « nom de domaine » et son adresse IP.
C’est la fonction gethostbyaddr().
Dès que la correspondance est faite, on l’affiche et on quitte. Dit autrement, tant que votre nom de domaine n’est pas validé, il y aura une boucle de test toutes les minutes. Surtout n’hésitez pas à laisser un commentaire pour améliorer la chose !
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import socket, time, random