Django-fr

Forum

#1 10-09-2010 12:04:12

naoy.teruh
Membre
Inscription : 10-09-2010
Messages : 4

Django - Multiple columns primary key

Hello,

I would like to implement multicolumns primary keys in django.

I've tried to implement an AutoSlugField() which concatenate my columns values(foreignkey/dates) ...

models.py :

class ProductProduction(models.Model): enterprise = models.ForeignKey('Enterprise') product = models.ForeignKey('Product') date = models.DateTimeField() count = models.IntegerField() slug = AutoSlugField(populate_from=lambda instance: instance.enterprise.username + '-' + instance.product.name + '-' + str(instance.date))

When I pass the following parameters : - 'Megacorp','robot','09/10/2010',5 => slug = 'Megacorp-robot-09/10/2010' ... the next time in pass the triplet, a new value has been inserted : - 'Megacorp','robot','09/10/2010',10 => slug = 'Megacorp-robot-09/10/2010' => same slug value => insert ????

I tried to add primary_key=True parameter to the slug... but it creates new instance with a "-1" "-2" ... and NO update is made at all...

Did I miss something ?

Thanks,

Yoan

Hors ligne

#2 10-09-2010 12:10:56

Cyril B.
Administrateur
Inscription : 11-08-2010
Messages : 45

Re : Django - Multiple columns primary key

Hello,

You must have missed this forum is only in French smile You should ask your question on the Django users group instead (or here, but in French).

Hors ligne

#3 10-09-2010 12:25:44

naoy.teruh
Membre
Inscription : 10-09-2010
Messages : 4

Re : Django - Multiple columns primary key

Bonjour,

Je souhaite implémenter dans mon code une clé primaire composite.

J'ai essayé d'utiliser le AutoSlugField() qui concatène des valeurs liés à mes champs (clés étrangères / dates) ...

models.py :

class ProductProduction(models.Model): 
enterprise = models.ForeignKey('Enterprise') 
product = models.ForeignKey('Product') 
date = models.DateTimeField() 
count = models.IntegerField() 
slug = AutoSlugField(populate_from=lambda instance: instance.enterprise.username + '-' + instance.product.name + '-' + str(instance.date))

Lorsque je passe :
- 'Megacorp','robot','09/10/2010',5 => slug = 'Megacorp-robot-09/10/2010' ...
Puis que je repasse le meme triplet, il me refait un INSERT par dessus :
- 'Megacorp','robot','09/10/2010',10 => slug = 'Megacorp-robot-09/10/2010' => slug identique => insert ????

J'essayé de coller le paramètre primary_key=True parameter à mon slug... mais cela crée de nouvelle instances avec "-1" "-2" ...

Komenkonfè ?

Merci aux esprit éclairés,

Yoan

Hors ligne

#4 10-09-2010 12:37:31

werefr0g
Membre
Inscription : 09-09-2010
Messages : 23

Re : Django - Multiple columns primary key

Bonjour,

L'option Meta "unique_together" pourrait t'aider ?

Le 10/09/2010 13:25, HURET Yoan a écrit :
> Bonjour,
>
> Je souhaite implémenter dans mon code une clé primaire composite.
>
> J'ai essayé d'utiliser le AutoSlugField() qui concatène des valeurs
> liés à mes champs (clés étrangères / dates) ...
>
> models.py :
>

> class ProductProduction(models.Model):
> enterprise = models.ForeignKey('Enterprise')
> product = models.ForeignKey('Product')
> date = models.DateTimeField()
> count = models.IntegerField()
> slug = AutoSlugField(populate_from=lambda instance:
> instance.enterprise.username + '-' + instance.product.name + '-' +
> str(instance.date))
>

>
> Lorsque je passe :
> - 'Megacorp','robot','09/10/2010',5 =>  slug = 'Megacorp-robot-09/10/2010'
> ...
> Puis que je repasse le meme triplet, il me refait un INSERT par dessus :
> - 'Megacorp','robot','09/10/2010',10 =>  slug = 'Megacorp-robot-09/10/2010'
> =>  slug identique =>  insert ????
>
> J'essayé de coller le paramètre primary_key=True parameter à mon
> slug... mais cela crée de nouvelle instances avec "-1" "-2" ...
>
> Komenkonfè ?
>
> Merci aux esprit éclairés,
>
> Yoan
> _______________________________________________
> django mailing list
> django _AT_ lists.afpy.org
> http://lists.afpy.org/mailman/listinfo/django
>

Hors ligne

#5 10-09-2010 23:50:01

naoy.teruh
Membre
Inscription : 10-09-2010
Messages : 4

Re : Django - Multiple columns primary key

Bonsoir,

Certes, mais sauf erreur, cette fonction ne gère pas le débranchement Update / Insert, elle lève une exception en cas de doublon, rien de plus.
J'aimerais trouver un moyen de pouvoir gérer cela au niveau du modèle, j'ai essayé la surcharge de save...

def save(self, *args, **kwargs):
      product_production = ProductProduction.objects.get(slug=self.slug)
      if product_production == None:
        super(ProductProduction, self, force_insert=True)
      else:
        self.pk = product_production.pk
        super(ProductProduction, self, force_update=True)

... mais sans succès :
ProductProduction matching query does not exist.
sur :
product_production = ProductProduction.objects.get(slug=self.slug)

Ce n'est pas simple...

Bonne nuit

Yoan

Hors ligne

#6 12-09-2010 03:23:45

werefr0g
Membre
Inscription : 09-09-2010
Messages : 23

Re : Django - Multiple columns primary key

Yoan,

Désolé, j'étais focalisé sur les nouvelles instances crées malgré la clé
primaire, d'où le blocage par unique_together.

Sinon, c'est plutôt dangereux d'utiliser un get sans gérer les
exceptions. Tu peux "à la rigueur" faire l'impasse en recourant à filter
ou count. Voilà ce que je te propose :

>>> from django.core.exceptions import ObjectDoesNotExist

>>>   def save(self, *args, **kwargs):
>>>     try:
>>> product_production = ProductProduction.objects.get(slug=self.slug)
>>>     except ObjectDoesNotExist:
>>> super(CartDetail, self).save(*args, **kwargs)
>>> else:
>>> self.pk = product_production.pk
>>> super(CartDetail, self).save(force_update=True, *args, **kwargs)

Hors ligne

#7 12-09-2010 03:28:41

werefr0g
Membre
Inscription : 09-09-2010
Messages : 23

Re : Django - Multiple columns primary key

Re,

Désolé pour le post précédent, je commence tout juste à m'imbiber de
café... voilà donc une version avec ta classe ProductProduction et non
celle issue de mon bac à sable :

>>> from django.core.exceptions import ObjectDoesNotExist

>>>   def save(self, *args, **kwargs):
>>>     try:
>>> product_production = ProductProduction.objects.get(slug=self.slug)
>>>     except ObjectDoesNotExist:
>>> super(ProductProduction, self).save(*args, **kwargs)
>>> else:
>>> self.pk = product_production.pk
>>> super(ProductProduction, self).save(force_update=True, *args, **kwargs)

Hors ligne

#8 12-09-2010 06:46:02

werefr0g
Membre
Inscription : 09-09-2010
Messages : 23

Re : Django - Multiple columns primary key

Purée... et une v3... il faut bien entendu placer le dernier save dans
la clause else... désolé.

>>> from django.core.exceptions import ObjectDoesNotExist

>>>   def save(self, *args, **kwargs):
>>>     try:
>>> product_production = ProductProduction.objects.get(slug=self.slug)
>>>     except ObjectDoesNotExist:
>>> super(ProductProduction, self).save(*args, **kwargs)
>>> else:
>>> self.pk = product_production.pk
>>> super(ProductProduction, self).save(force_update=True, *args, **kwargs)

Hors ligne

#9 12-09-2010 18:49:10

werefr0g
Membre
Inscription : 09-09-2010
Messages : 23

Re : Django - Multiple columns primary key

Yoan,

Tu vas me trouver lourd, mais ça m'a travaillé toute la journée : je
trouve l'alliance de unique_together et de get_or_create efficace et
elle permet, à mon sens, plus de contrôle selon les contextes.
> _______________________________________________
> django mailing list
> django _AT_ lists.afpy.org
> http://lists.afpy.org/mailman/listinfo/django

Hors ligne

#10 12-09-2010 23:25:38

naoy.teruh
Membre
Inscription : 10-09-2010
Messages : 4

Re : Django - Multiple columns primary key

Bonsoir wereFrog,

Tu n'es pas lourd du tout :-)
J'ai suivi ton conseil, voici le code résultant (c'est bien ca ?):

class Meta:
     unique_together = ("enterprise", "product", "mois")
     
    def save(self, *args, **kwargs):
      try:
        print super(ProductProduction, self).save(*args, **kwargs)
      except IntegrityError:
        self.pk = ProductProduction.objects.get(enterprise=self.enterprise,product=self.product,mois=self.mois).pk
        super(ProductProduction, self).save(force_update=True, *args, **kwargs)

J'aurais bien aimé avoir un meta qui fasse tout le boulot (ca n'existe pas ?)
N'hésite pas s'il y a des choses qui ne vont pas dans mon code.

Merci beaucoup,

Yoan,

Hors ligne

#11 13-09-2010 14:56:19

werefr0g
Membre
Inscription : 09-09-2010
Messages : 23

Re : Django - Multiple columns primary key

Yoan,

Le problème ici est que s'il y a lieu de lever IntegrityError, save ne
la propagera pas mais lèvera ObjectDoesNotExist. Du coup, j'irai plutôt
du côté de :

class Meta:
       unique_together = ('entreprise', 'product', 'mois')

     def save(self, *args, **kwargs):
       try:
         super(ProductProduction, self).save(*args, **kwargs)
       except IntegrityError, e:
         try:
           self.pk = 
ProductProduction.object.get(entreprise=self.entreprise, \
             product=self.product, mois=self.mois)
         except ObjectDoesNotExist:
           raise IntegrityError, e
         super(ProductProduction, self).save(*args, **kwargs)

C'est un peu moins lisible que la proposition précédente. Ton idée de
tenter l'appel à save en premier lieu et l'affectation directe d'une
valeur à self.pk le cas échéant donne peut-être une exécution plus
rapide et moins gourmande.

Sinon, le Django est tellement cohérent qu'on perd l'habitude de gérer
ce type de cas particulier. Je n'ose même pas évoquer la modification
dans django de la méthode save pour tester au préalable l'existence d'un
unique_together significatif dans la classe Meta du modèle pour tester
ce type de situation pour chacun des cas inclus xD.

Hors ligne

#12 20-06-2013 17:33:34

SaifJ
Membre
Inscription : 20-06-2013
Messages : 1

Re : Django - Multiple columns primary key

Bonjour,
Je souhaite implémenter dans mon code une clé primaire composé du User et un model Societe que j'ai implemente, pour dire qu'un nom d'utilisateur peut être servi pour differente Societe
voici mn code

class Societe(models.Model):
    
    name = models.CharField(max_length=250)
    provider = models.ForeignKey(Provider)
    
    def __unicode__(self):
        return '%s -- %s' % (self.name, self.provider.name)
    
class UserPro(models.Model):
    
    user = models.OneToOneField(User,primary_key=True)
    adress = models.CharField(max_length=250)
    telephone = models.CharField(max_length=250)
    societe = models.ForeignKey(Societe,primary_key=True)
    def __unicode__(self):
        return '%s' % (self.user.first_name)

Quand j'ajoute primary_key je reçois une erreur de "has more than one primary key"

Dernière modification par SaifJ (20-06-2013 17:34:42)

Hors ligne

#13 22-06-2013 11:51:50

Xavier Ordoquy
Administrateur
Lieu : Puteaux, France
Inscription : 12-10-2011
Messages : 312
Site Web

Re : Django - Multiple columns primary key

Bonjour,

avec le post précédent, nous somme bien dans un cadre différent du post initial.
Pour la gestion de "vraies" clefs composites, il existe une application qui gère ça plutôt bien.
Voir le projet à l'adresse suivante:
https://github.com/simone/django-compositekey

Hors ligne

Pied de page des forums