django-voting сортировка по рейтингу

    Думаю, многие знакомы с этим расширением, но всё же:
    django-voting позволяет ввести оценку любой сущности по digg-принципу (+1/-1) максимум за 30 минут (с учётом включения асинхронных запросов JS).
    Сайт проекта: django-voting.googlecode.com
    Но есть одна плохая особенность: отсутствие возможности сортировать сущности по рейтингу стандартными средствами ORM. Далее опишу как это реализовал я.
    На самом деле, рейтинг извлекается запросом:
    SELECT SUM(vote) FROM votes WHERE content_type_id=? AND object_id=?
    Где следует указать id типа (contenttype framework) и id объекта.
    Конечно, можно пойти в лоб и сделать что-то типа:
    Article.objects.extra(select={'score': 'SELECT SUM(vote) FROM votes WHERE content_type_id=? AND object_id=?'})
    Но это, ИМХО, длинновато, особенно если нужно это делать много раз.
    «Много раз» символизирует необходимость использовать менеджеры… Скажем, Article.objects это и есть менеджер. Зная это, можно написать своё. Вопрос только в том, как определить id типа? Это задача contenttype фреймворка. Думаю, проще привести код менеджера:
    class ScoreOrderManager(models.Manager):
        def select_score(self):
            """ Выбрать результаты голосования по объекту """
            from django.contrib.contenttypes.models import ContentType
            model_type = ContentType.objects.get_for_model(self.model)
            table_name = self.model._meta.db_table
            return self.extra(select={'score': 'SELECT SUM(vote) FROM votes WHERE content_type_id=%i AND object_id=%s.id' % (int(model_type.id), table_name)})
    Далее подключаем менеджер к объекту, просто добавив свойство (можно переопределить objects) со значением = экземпляру менеджера.
    class Article:
        title = models.CharField(max_length=200)
        ...
        mymanager = ScoreOrderManager()
    Далее, всё работает по принципу:
    Article.mymanager.select_score().order_by('-score')
    Единственная проблема, select_score нужно вызывать непосредственно у менеджера. У QuerySet такого свойства нет. (готов выслушать предложения на этот счёт)

    Оригинал: "django-voting сортировка по рейтингу"

    P.S> Вообще, на google code есть достаточно количество django-* проектов. Очень советую их посмотреть, сбережёте много сил. Это я к тому, что для себя открыл их относительно недавно.

    Похожие публикации

    Средняя зарплата в IT

    113 000 ₽/мес.
    Средняя зарплата по всем IT-специализациям на основании 5 444 анкет, за 2-ое пол. 2020 года Узнать свою зарплату
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама

    Комментарии 15

      0
      Спасибо
        +1
        Наши ряды ширятся :)
          0
          The requested URL /2007/11/prosto-fork.html was not found on this server.
            0
            Опс) Глюк MT. Поправил, спасибо! :)
              0
              В случае же, когда нужно распараллелить выполнение задач, картина такая:
              Допустим, веб-сервер получает запрос на подключение.

              Впринципе, это просто. Но то как объясняется в большинстве источников, мягко говоря, показывает это со сложной стороны. Надеюсь, эта заметка кому-то поможет.


              Я так понимаю, самое интересное потеряно? :)
                0
                Весело получилось)
                Обычно пишу статьи спонтанно и в темпе поросёнка, ибо времени не хватает, так что полно таких нелепостей) Перескакиваю с мысли на мысль
          0
          Спасибо. У вас там в оригинале строки режутся по ширине и не видно конца SQL.
            0
            Поправил маленько
            0
            Потрясающе, вы просто читаете мои мысли.
            Я как раз думал над этим.
              0
              > Единственная проблема, select_score нужно вызывать непосредственно у менеджера. У QuerySet
              > такого свойства нет. (готов выслушать предложения на этот счёт)
              >
              предложение:
              class ScoreOrderManager(models.Manager):

              def get_query_set(self):

              """ Выбрать результаты голосования по объекту """

              from django.contrib.contenttypes.models import ContentType

              model_type = ContentType.objects.get_for_model(self.model)

              table_name = self.model._meta.db_table

              return super(ScoreOrderManager, self).get_query_set().extra(select={'score': 'SELECT SUM(vote) FROM votes WHERE content_type_id=%i AND object_id=%s.id' % (int(model_type.id), table_name)})

              .... определяем менеджер...

              Теперь:
              Article.mymanager.order_by('-score')
                0
                Как вариант пойдёт, но тогда эти результаты будут грузиться постоянно. Не всегда такое подойдёт. (кстати, первый вариант был именно таким, но по выше изложенным причинам от него отказался)
                  0
                  Тогда непонятен смысл добавления mymanager в класс Article. Достаточно создать свой менеджер, в нем метод select_score и перегрузить Article.objects своим менеджером. Дальше вызывать Article.objects.select_score(). Это сделает код более консистентным и понятным на мой взгляд.
                    0
                    >просто добавив свойство (можно переопределить objects)
                    Что, впринципе, я и делаю. Пример такой лишь для того, чтобы новички поняли, что это не обязательно должен быть objects
                0
                кто-нибудь ещё тут пробовал django-votinng? какие отзывы?
                  0
                  Проще попробовать чем описывать

                Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                Самое читаемое