2009-02-07 5 views
19

Je suis en train de coder un site dans Django (parce que vous ne pouvez jamais apprendre trop de frameworks!), Et je me demande s'il existe un moyen d'incrémenter automatiquement un objet par rapport à un objet apparenté. Ainsi, par exemple, dire que j'ai un modèle d'entrée et un modèle EntryVersion:Existe-t-il un moyen d'incrémenter automatiquement un champ Django par rapport à une clé étrangère?

Entrée
- titre
- limaces

EntryVersion
- entrée (clé étrangère)
- numéro_version
- contenu

Je veux incrémenter automatiquement version_number en ce qui concerne la clé étrangère d'entrée (de sorte qu'une entrée puisse avoir plusieurs versions, commençant à une et se déplaçant vers le haut par une). Cependant, il ne s'agira pas d'un véritable auto-incrément, car il ne sera pas unique dans la base de données (il peut y avoir de nombreuses versions d'entrée avec version_number = 1, juste une seule pour une entrée donnée). Je savais que je pouvais lancer mon propre admin et que je le gérais ici, mais je me demandais s'il y avait un moyen pour que l'administrateur de Django augmente automatiquement le numéro de version de 1 quand une nouvelle version est enregistrée.


Edit: code spécifique que je (corrigé numéro de version uniquement mis sur la première sauvegarde)

La réponse de Tiago avait raison, mais dans l'intérêt des futurs utilisateurs stackoverflow avec des dilemmes similaires, voici la code spécifique que je:

def save(self, force_insert=False, force_update=False): 
    # Only modify number if creating for the first time (is default 0) 
    if self.version_number == 0: 
     # Grab the highest current index (if it exists) 
     try: 
      recent = EntryVersion.objects.filter(entry__exact=self.entry).order_by('-version_number')[0] 
      self.version_number = recent.version_number + 1 
     except IndexError: 
      self.version_number = 1 
    # Call the "real" save() method 
    super(EntryVersion, self).save(force_insert, force_update) 

l'astuce order_by w/index est celui que je glanées dans la documentation Django ici:

http://docs.djangoproject.com/en/dev/topics/db/queries/#id4

Notez que vous devez avoir défini default=0 sur votre champ version_number pour que cela fonctionne.

Il peut y avoir un meilleur moyen, mais cela semble fonctionner exactement comme je le voulais; J'espère que d'autres le trouveront utile aussi.

+0

Merci de partager votre solution. – Giacomo

+1

Quelle est la sécurité de cette solution, compte tenu des demandes simultanées à la même entrée? –

+0

Je ne suis pas sûr d'avoir 100% de votre cas d'utilisation. Pourriez-vous le faire dans la méthode de sauvegarde de l'entrée? –

Répondre

8

Vous pouvez le faire:

def save(self, force_insert=False, force_update=False): 
    #if self.id is None: 
    self.version_number += 1 

    super(EntryVersion, self).save(force_insert, force_update) # Call the "real" save() method. 

qui vient directement d'ici:

http://docs.djangoproject.com/en/dev/topics/db/models/#overriding-predefined-model-methods

+0

Merci! Évidemment, j'aurai besoin d'ajouter un peu plus de logique que d'incrémenter le numéro de version (puisqu'il ne sera probablement pas utilisé par défaut avec le dernier numéro de version), mais je pense que c'est certainement la direction que je dois prendre; merci aussi pour le lien, je n'ai pas remarqué que dans les docs. –

+0

J'ai fait quelque chose comme ça dans un projet, mais j'ai fini par mettre la logique dans la vue, car c'était plus simple et il n'y avait qu'une seule méthode qui pouvait créer mon objet. – Tiago

+0

Je pourrais finir par migrer vers la vue, mais je voulais spécifiquement pouvoir avoir Just Work dans l'admin dès maintenant (puisque je suis dans les toutes premières phases de test et que je n'ai pas encore de configuration d'affichage). Merci encore! –

Questions connexes