Question

J'ai un joli modèle d'article générique, avec une relation m2m avec le modèle Tag. Je veux garder le compte de chaque utilisation de balise, je pense que le meilleur moyen serait de dénormaliser le champ de comptage sur le modèle de balise et de le mettre à jour chaque fois que l'article sera enregistré. Comment puis-je accomplir cela, ou peut-être y a-t-il un meilleur moyen?

Était-ce utile?

La solution

Vous pouvez le faire en créant un modèle intermédiaire pour la relation M2M et l’utilisez comme crochet pour les signaux post_save et post_delete afin de mettre à jour la colonne dénormalisée dans le Article table.

Par exemple, je le fais pour les questions favorites dans soclone , où les utilisateurs ont une relation M2M avec Question s:

from django.contrib.auth.models import User
from django.db import connection, models, transaction
from django.db.models.signals import post_delete, post_save

class Question(models.Model):
    # ...
    favourite_count = models.PositiveIntegerField(default=0)

class FavouriteQuestion(models.Model):
    question = models.ForeignKey(Question)
    user     = models.ForeignKey(User)

def update_question_favourite_count(instance, **kwargs):
    """
    Updates the favourite count for the Question related to the given
    FavouriteQuestion.
    """
    if kwargs.get('raw', False):
        return
    cursor = connection.cursor()
    cursor.execute(
        'UPDATE soclone_question SET favourite_count = ('
            'SELECT COUNT(*) from soclone_favouritequestion '
            'WHERE soclone_favouritequestion.question_id = soclone_question.id'
        ') '
        'WHERE id = %s', [instance.question_id])
    transaction.commit_unless_managed()

post_save.connect(update_question_favourite_count, sender=FavouriteQuestion)
post_delete.connect(update_question_favourite_count, sender=FavouriteQuestion)

# Very, very naughty
User.add_to_class('favourite_questions',
                  models.ManyToManyField(Question, through=FavouriteQuestion,
                                         related_name='favourited_by'))

Il y a eu quelques discussions sur la liste de diffusion django-developers sur la mise en œuvre d'un moyen de déclaration déclarative des dénormalisations afin d'éviter d'avoir à écrire du code comme ci-dessus:

Autres conseils

Ceci est une nouvelle fonctionnalité de Django 1.2: http://docs.djangoproject.com/en/dev/ref / signaux / # m2m-modifié

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top