Django-fr

Forum

#1 31-10-2010 09:40:12

christophetd
Membre
Inscription : 30-10-2010
Messages : 8

Ajouter des champs au modèle User

Bonjour,

Est-il possible d'ajouter des champs au modèle préfédini User ? Si oui, comment ? Simplement en modifiant son models.py, ou y a-t-il autre chose à faire ?
Merci. smile

Hors ligne

#2 31-10-2010 09:51:19

Rémy HUBSCHER
Membre
Inscription : 11-08-2010
Messages : 161

Re : Ajouter des champs au modèle User

Bonjour,

Il faut utiliser le profil pour ajouter des champs à un modèle.
http://docs.djangoproject.com/en/dev/topics/auth/#storing-additional-information-about-users

Tu peux ensuite utiliser cette solution pour éditer le profil et le User
avec un seul formulaire.

http://stackoverflow.com/questions/1727564/how-to-create-a-userprofile-form-in-django-with-first-name-last-name-modificatio

N'hésite pas si tu as d'autres question.

Cordialement,

Natim

Hors ligne

#3 31-10-2010 10:53:25

christophetd
Membre
Inscription : 30-10-2010
Messages : 8

Re : Ajouter des champs au modèle User

En gros, je dois créer un modèle « UtilisateurProfil » (par exemple) dans mon /monapp/monmodule/models.py qui ressemblerait au code ci-dessous, puis spécifier dans mon settings.py AUTH_PROFILE_MODULE = 'monmodule.UtilisateurProfil'  ?

class UtilisateurProfil(models.Model):
    info1 = models.CharField()
    # etc.

[Edit] Ah, le django-book explique très bien cela en fait ! http://www.djangobook.com/en/1.0/chapter12/#cn222 Une fois que tout est défini, il faut refaire un syncdb je suppose ?

Dernière modification par christophetd (31-10-2010 10:54:42)

Hors ligne

#4 31-10-2010 11:24:23

Rémy HUBSCHER
Membre
Inscription : 11-08-2010
Messages : 161

Re : Ajouter des champs au modèle User

Oui c'est ça, il te faudra aussi ajouter `monmodule` à ton
INSTALLED_APPS avant de faire le syncdb.

Hors ligne

#5 31-10-2010 11:28:51

christophetd
Membre
Inscription : 30-10-2010
Messages : 8

Re : Ajouter des champs au modèle User

Je vais tester ça, merci bien. smile

Hors ligne

#6 31-10-2010 13:59:21

christophetd
Membre
Inscription : 30-10-2010
Messages : 8

Re : Ajouter des champs au modèle User

Une dernière question : est-il possible de mettre en BDD des éléments tels que des dictionnaires ? Admettons (ce n'est pas mon cas tongue) que je veuille faire quelque chose comme :

u = User.get(pk=1)
u.livres = { 
        'harry potter': 'état neuf', 
        'la peau de chagrin': 'salement abimé'
}
u.save()

Serait-ce possible ? Dans l'exemple, je suppose qu'il faudrait attribuer un champ particulier à mon modèle de profil, mais je ne sais pas lequel ça serait.

Merci beaucoup !

Hors ligne

#7 31-10-2010 15:32:25

Rémy HUBSCHER
Membre
Inscription : 11-08-2010
Messages : 161

Re : Ajouter des champs au modèle User

Ce que tu veux faire ce fait en NoSQL avec des solutions telles que CouchDB.

Si tu veux le faire avec des SGBD, il faut faire une table livre, qui va contenir un champ user de type ForeignKey vers la table User et un related_name `livres` Il y aura aussi un champ titre et un champ état.

Ainsi en faisant

u.livres.all()

tu auras une liste des livres de l'utilisateur.

Hors ligne

#8 31-10-2010 15:35:07

David Thenon
Membre
Inscription : 11-08-2010
Messages : 156
Site Web

Re : Ajouter des champs au modèle User

Salut christophe,

Oui c'est tout à fait possible de stocker ton dictionnaire, seulement il n'y a
pas de type SQL conçus pour cela, tu devras le stocker en tant qu'un champ
text (et pas varchar qui est trop limité en espace). Il y a plusieurs façons
de faire ça :

* Avec pickle qui va sérializer ton contenu lors de la sauvegarde et qui le
déserialisera en un objet python pendant l'accès (c'est ce qu'utilise django
dans les sessions pour stocker les données contextuels à une session cf
"django.contrib.sessions.models.Session")
* Avec JSON ou tu sérialize ton objet python en JSON que tu stockes tel quel
et tu déserialize lors de l'accès en un objet python.

Et d'autres encore, cela dit c'est plutôt de la bidouille, parce que tu perds
beaucoup d'avantages comme la possibilité de faire des recherches sur le
contenu de ce genre de champ.

Pour ton exemple, un champs de type ForeignKey qui relie sur un modèle de
"livres" serait clairement la vrai bonne solution.

> Une dernière question : est-il possible de mettre en BDD des éléments
> tels que des dictionnaires ? Admettons (ce n'est pas mon cas tongue) que je
> veuille faire quelque chose comme :
>
>

u = User.get(pk=1)
> u.livres = {
>         'harry potter': 'état neuf',
>         'la peau de chagrin': 'salement abimé'
> }
> u.save()

>
> Serait-ce possible ? Dans l'exemple, je suppose qu'il faudrait attribuer
> un champ particulier à mon modèle de profil, mais je ne sais pas lequel
> ça serait.
>
> Merci beaucoup !
> _______________________________________________
> django mailing list
> django _AT_ lists.afpy.org
> http://lists.afpy.org/mailman/listinfo/django
> ---------------------------------------------------------------------------
> ------------ Orange vous informe que cet  e-mail a ete controle par
> l'anti-virus mail. Aucun virus connu a ce jour par nos services n'a ete
> detecte.
>
>
>
> ---------------------------------------------------------------------------
> ------------ Orange vous informe que cet  e-mail a ete controle par
> l'anti-virus mail. Aucun virus connu a ce jour par nos services n'a ete
> detecte.

Hors ligne

#9 02-11-2010 09:43:05

Chamal
Membre
Inscription : 11-08-2010
Messages : 17

Re : Ajouter des champs au modèle User

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256


Le 31 oct. 2010 à 15:35, David THENON a écrit :

> Salut christophe,
>
> Oui c'est tout à fait possible de stocker ton dictionnaire, seulement il n'y a
> pas de type SQL conçus pour cela, tu devras le stocker en tant qu'un champ
> text (et pas varchar qui est trop limité en espace). Il y a plusieurs façons
> de faire ça :
>
> * Avec pickle qui va sérializer ton contenu lors de la sauvegarde et qui le
> déserialisera en un objet python pendant l'accès (c'est ce qu'utilise django
> dans les sessions pour stocker les données contextuels à une session cf
> "django.contrib.sessions.models.Session")
> * Avec JSON ou tu sérialize ton objet python en JSON que tu stockes tel quel
> et tu déserialize lors de l'accès en un objet python.
>
> Et d'autres encore, cela dit c'est plutôt de la bidouille, parce que tu perds
> beaucoup d'avantages comme la possibilité de faire des recherches sur le
> contenu de ce genre de champ.
>
> Pour ton exemple, un champs de type ForeignKey qui relie sur un modèle de
> "livres" serait clairement la vrai bonne solution.
>
>> Une dernière question : est-il possible de mettre en BDD des éléments
>> tels que des dictionnaires ? Admettons (ce n'est pas mon cas tongue) que je
>> veuille faire quelque chose comme :
>>
>>

u = User.get(pk=1)
>> u.livres = {
>>        'harry potter': 'état neuf',
>>        'la peau de chagrin': 'salement abimé'
>> }
>> u.save()

>>
>> Serait-ce possible ? Dans l'exemple, je suppose qu'il faudrait attribuer
>> un champ particulier à mon modèle de profil, mais je ne sais pas lequel
>> ça serait.
>>

C'est pas parce que c'est possible que l'on doit le faire ...

Cela s'appelle de la dénormalisation (le contraire du respect des formes normales : http://fr.wikipedia.org/wiki/Forme_normale_(bases_de_donn%C3%A9es_relationnelles) et doit être appliqué que dans des situations bien identifiées et maitrisées, sinon c'est vite la catastrophe (des objets qui deviennent orphelins, du code difficile a maintenir, etc).

Mais oui les outils de nosql s'affranchissant des relations entre objets (le R de RDBMS), autrement que celles exprimées dans la logique du code, sont adaptés par nature a de telles "non normalisation".

Désolé j'ai une tendance lourde a être ayatollah de la forme normale, mais j'ai trop souvent vu en tant que dba des bêtises de modélisation de ce genre et peut garantir que les conséquences sont jamais bénéfiques à moyen terme.

L'ORM de Django permet facilement de se promener dans les modèles "related" :

class Livre (models.Model):
    titre = ....

# Association N-N entre User et Livre avec des propriétés supplémentaires possibles :
#
class UserLivre(models.Model):
    user = models.ForeignKey(User,related='livres')
    livre = models.ForeinKey(Livre, related='users')
    etat = models.CharField(max_length=32)

ensuite on accède aux livres d'un utilisateur (et les propriétés associées) facilement par le related u.livres (attention il faut rajouter .all() pour avoir tous les objets) :

user = User.get(id=<user_id>)

for l in user.livres.all():
    print "%u détient %s en état %s" % (user.name,l.livre.titre,l.etat)

ajouter / supprimer consiste a manipuler les objets de cette liste lié à un utilisateur.

++ Aymeric


-----BEGIN PGP SIGNATURE-----
Version: GnuPG/MacGPG2 v2.0.12 (Darwin)

iF4EAREIAAYFAkzPzyEACgkQk+uq5YLlwVQcRwD+M8iigT/uw+MgzNEEYoWU9QEF
eMUkgE0XGNwWjGJoVfwBALZPBDIVjrm1YII9rVJx8/T6vux8LkBdIaEMx8FVYzqZ
=sioR
-----END PGP SIGNATURE-----

Hors ligne

#10 08-11-2010 12:04:32

Samuel Martin
Membre
Inscription : 11-08-2010
Messages : 30

Re : Ajouter des champs au modèle User

Bonjour,

Pour ajouter des champs au models User il existe effectivement plusieurs
solutions.


   1. La solution officielle : créer une class UserProfile lié avec User
   (comme décrit dans les précédentes réponses)
   2. Les solutions officieuses : add_class / metaclasse sur User


La 1. conviendra dans la majorité des cas, mais niveau perf on a vu mieux.
Si tu ajoutes juste 1 champs supplémentaire l'intérêt est minime, cela
contraint à une requête bdd supplémentaire pour chaque utilisateur (dans le
pire des cas).

La 2. (je n'ai pas encore testé add_class)

Voici des exemples concrets :
*Add_class :

*User.add_to_class('location', models.CharField(max_length=250,blank=True))

Ajoute le champ "location" au models User


*Meta Class / Meta Object:*

A coller dans le fichier __init__.py de UserProfile par ex:

class MetaClass(type):
    def __new__(self, classname, classbases, classdict):
        try:
            frame = inspect.currentframe()
            frame = frame.f_back
            if frame.f_locals.has_key(classname):
                old_class = frame.f_locals.get(classname)
                for name, func in classdict.items():
                    if inspect.isfunction(func):
                        setattr(old_class, name, func)
                return old_class
            return type.__new__(self, classname, classbases, classdict)

        finally:
            del frame

class MetaObject(object):
    __metaclass__ = MetaClass


class User(MetaObject):
.... ici vos nouveaux attributs ...



Cdlt,

--
Samuel Martin

Temesis
Qualité, conformité, et accessibilité des services en ligne

http://www.temesis.com
http://www.opquast.com
http://openweb.eu.org

Mob : +33 614 157 941

Hors ligne

Pied de page des forums