ФорумПрограммированиеPythonDjango → Django и Mysql: DISTINCT ON fields is not supported by this database backend

Django и Mysql: DISTINCT ON fields is not supported by this database backend

  • adw0rd

    Сообщения: 22905 Репутация: N Группа: в ухо

    Spritz 25 июня 2012 г. 14:32

    Кто пытался решить эту проблему? Хочется:
    queryset.distinct(field1, field2)


    В PostgreSQL решается так:
    SELECT DISTINCT ON (field1, field2) * FROM `table`;


    В MySQL это можно заменить таким выражением, но в sql.compiler Django это всовывать не хочется…
    SELECT * FROM `table` GROUP BY field1, field2 ORDER BY NULL;
    adw/0
  • adw0rd

    Сообщения: 22905 Репутация: N Группа: в ухо

    Spritz 25 июня 2012 г. 15:23, спустя 50 минут 38 секунд

    Вообщем я всетаки пофиксил для Django 1.5.0-alpha
    Теперь это выглядит так:


    In [1]: from users.models import User

    In [2]: print User.objects.distinct('username').query
    SELECT `auth_user`.`id`, `auth_user`.`username`, `auth_user`.`first_name`, `auth_user`.`last_name`, `auth_user`.`email`, `auth_user`.`password`, `auth_user`.`is_staff`, `auth_user`.`is_active`, `auth_user`.`is_superuser`, `auth_user`.`last_login`, `auth_user`.`date_joined` FROM `auth_user` GROUP BY `auth_user`.`username` ORDER BY NULL

    In [3]: print User.objects.distinct('username', 'email').query
    SELECT `auth_user`.`id`, `auth_user`.`username`, `auth_user`.`first_name`, `auth_user`.`last_name`, `auth_user`.`email`, `auth_user`.`password`, `auth_user`.`is_staff`, `auth_user`.`is_active`, `auth_user`.`is_superuser`, `auth_user`.`last_login`, `auth_user`.`date_joined` FROM `auth_user` GROUP BY `auth_user`.`username`, `auth_user`.`email` ORDER BY NULL

    In [4]: print User.objects.distinct().query
    SELECT DISTINCT `auth_user`.`id`, `auth_user`.`username`, `auth_user`.`first_name`, `auth_user`.`last_name`, `auth_user`.`email`, `auth_user`.`password`, `auth_user`.`is_staff`, `auth_user`.`is_active`, `auth_user`.`is_superuser`, `auth_user`.`last_login`, `auth_user`.`date_joined` FROM `auth_user`


    Поддерживаются и lookups: filter(something__test__id=1)

    In [6]: print CommentPlus.objects.filter(user=User.objects.get(pk=42), followup=True).distinct('object_pk', 'content_type__id').order_by().query
    SELECT `django_comments`.`id`, `django_comments`.`content_type_id`, `django_comments`.`object_pk`, `django_comments`.`site_id`, `django_comments`.`user_id`, `django_comments`.`user_name`, `django_comments`.`user_email`, `django_comments`.`user_url`, `django_comments`.`comment`, `django_comments`.`submit_date`, `django_comments`.`ip_address`, `django_comments`.`is_public`, `django_comments`.`is_removed`, `comments_plus_commentplus`.`comment_ptr_id`, `comments_plus_commentplus`.`followup`, `comments_plus_commentplus`.`is_review`, `comments_plus_commentplus`.`review_type`, `comments_plus_commentplus`.`review_title` FROM `comments_plus_commentplus` INNER JOIN `django_comments` ON (`comments_plus_commentplus`.`comment_ptr_id` = `django_comments`.`id`) INNER JOIN `django_content_type` ON (`django_comments`.`content_type_id` = `django_content_type`.`id`) WHERE (`comments_plus_commentplus`.`followup` = True  AND `django_comments`.`user_id` = 42 ) GROUP BY `django_comments`.`object_pk`, `django_comments`.`content_type_id` ORDER BY NULL
    adw/0
  • adw0rd

    Сообщения: 22905 Репутация: N Группа: в ухо

    Spritz 25 июня 2012 г. 18:50, спустя 3 часа 27 минут 31 секунду

    Взять прямо сейчас можно тут https://github.com/adw0rd/django
    Pull-request в django: https://github.com/django/django/pull/175
    adw/0
  • adw0rd

    Сообщения: 22905 Репутация: N Группа: в ухо

    Spritz 27 июня 2012 г. 8:43, спустя 1 день 13 часов 52 минуты

    Вообщем сделал манкипатчинг текущей версии (Django 1.4), так как на проекте пока использую онную:
    pip install pyjack


    И в "project_root/__init__.py":

    import pyjack
    from django.db.backends.mysql.compiler import SQLCompiler


    class MySQLCompiler(SQLCompiler):
    distinct_via_group_by = []

    def __init__(self, *a, **kw):
    a = a[1:]
    super(MySQLCompiler, self).__init__(*a, **kw)

    def get_distinct(self):
    distinct_fields = super(MySQLCompiler, self).get_distinct()
    self.distinct_via_group_by = []
    for field in distinct_fields:
    self.distinct_via_group_by.append(field)
    return [] if self.query.distinct_fields else None

    def get_grouping(self, *args):
    grouping, gb_params = super(MySQLCompiler, self).get_grouping(*args)
    if self.distinct_via_group_by:
    grouping = self.distinct_via_group_by + grouping
    return grouping, gb_params


    pyjack.connect(SQLCompiler, MySQLCompiler)

    adw/0
  • phpdude

    Сообщения: 26624 Репутация: N Группа: в ухо

    Spritz 25 июня 2012 г. 19:03, спустя 10 часов 20 минут 28 секунд

    КРУТ!
    Сапожник без сапог
  • adw0rd

    Сообщения: 22905 Репутация: N Группа: в ухо

    Spritz 27 июня 2012 г. 7:11, спустя 1 день 12 часов 7 минут

    ps. Была проблема с select_related(), сейчас пофиксил
    adw/0

Пожалуйста, авторизуйтесь, чтобы написать комментарий!