Question

Est-il possible de réécrire cette requête à l'aide de l'objet Django QuerySet:

SELECT b.created_on, SUM(a.vote)
FROM votes a JOIN votes b ON a.created_on <= b.created_on
WHERE a.object_id = 1
GROUP BY 1

Où votes est une table, object_id est un entier qui apparaît plusieurs fois (clé étrangère - bien que cela ne soit pas important ici), et created_on qui correspond à une date / heure.

FWIW, cette requête permet d’obtenir un score à tout moment dans le passé en faisant la somme de tous les votes précédents sur cet object_id.

Était-ce utile?

La solution

Je suis presque sûr que cette requête ne peut pas être créée avec l'ORM de Django. Le nouveau code d'agrégation de Django est assez flexible, mais je ne pense pas qu'il puisse faire exactement ce que vous voulez.

Êtes-vous sûr que la requête fonctionne? Vous semblez manquer une vérification que b.object_id est 1.

Ce code devrait fonctionner, mais c'est plus d'une ligne et pas très efficace.

from django.db.models import Sum

v_list = votes.objects.filter(object__id=1)

for v in v_list:
    v.previous_score = votes.objects.filter(object__id=1, created_on__lte=v.created_on).aggregate(Sum('vote'))["vote__sum"]

L’agrégation n’est disponible que dans le coffre, vous devrez peut-être mettre à jour votre installation de Django avant de pouvoir le faire.

Autres conseils

L’agrégation n’est pas le problème; le problème ici est que l'ORM de Django ne fait tout simplement pas de jointure sur tout ce qui n'est pas une ForeignKey, autant que je sache.

C'est ce que j'utilise maintenant. Ironiquement, le sql est cassé, mais voici l'essentiel:

    def get_score_over_time(self, obj):
    """
    Get a dictionary containing the score and number of votes 
    at all times historically
    """
    import pdb; pdb.set_trace();
    ctype = ContentType.objects.get_for_model(obj)
    try:
        query = """SELECT b.created_on, SUM(a.vote)
                        FROM %s a JOIN %s b 
                        ON a.created_on <= b.created_on
                        WHERE a.object_id = %s
                        AND a.content_type_id = %s
                        GROUP BY 1""" % (
            connection.ops.quote_name(self.model._meta.db_table),
            connection.ops.quote_name(self.model._meta.db_table),
            1,
            ctype.id,
            )
        cursor = connection.cursor()
        cursor.execute(query)
        result_list = []
        for row in cursor.fetchall():
            result_list.append(row)
    except models.ObjectDoesNotExist:
        result_list = None
    return result_list
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top