Извлечь умный список из набора запросов, содержащего поля ManyToMany, используя значения в Django - PullRequest
2 голосов
/ 08 декабря 2011

У меня в основном есть эта модель:

class MyModel(models.Model):
    uid = models.CharField()
    m2m = models.ManyToManyField(AnotherModel)

class AnotherModel(models.Model):
    name = models.CharField()
    lang = models.CharField()

, и я хотел бы получить список таких диктовок (конечно, возможно, с фильтрацией, но это прекрасно работает):

[{
    'uid': uid,
    'm2m': [m2m.name, m2m.name, ...]
}]

Если я делаю:

MyModel.objects.select_related('m2m').filter().values('uid', 'm2m__name')

Я получаю следующее:

[{
    'uid': name_1,
    'm2m__name': m2m_1.name
},{
    'uid': name_1,
    'm2m__name': m2m_2.name
}]

, где у меня две проблемы :

  1. Iполучить отдельный элемент списка за каждый м2м!Я хотел бы только один на UID, с именами m2m в списке
  2. Я получаю "m2m__name", где я хотел бы только "name" или, возможно, "m2m"

(если яне задавайте явно m2m__name и используйте только m2m Я не получаю Unicode , но идентификатор)

Есть ли способ решить эти проблемы прямо в набор запросов без прохожденияцикл питона?Какой самый эффективный способ?

РЕДАКТИРОВАТЬ

... возможно, с использованием .raw () или .extra (), и некоторый самодельный SQL может хотя бы решить вопрос2.?

Ответы [ 2 ]

1 голос
/ 15 декабря 2011

Мне кажется странным, что никто не заинтересован в этом вопросе, но я закончил циклически перебирать результаты, чтобы построить свой собственный желаемый список:

my_list = {}
for item in items:
    _uid = item['uid']
    _name = item['m2m__name']
    list_item = my_list.get(, {'uid': _uid, 'name': set([_name])})
    list_item['name'].add(_name)

это приведет к чему-то вроде:

my_list = { 'uid': {
    'uid': uid,
    'm2m': [m2m.name, m2m.name, ...]
}}

какие именно элементы необходимы в вопросе.

Мне бы хотелось решить хотя бы одну из проблем на уровне QuerySet ...

0 голосов
/ 16 января 2019

У меня был именно этот вопрос, и мне пришлось собрать несколько кусочков информации, чтобы получить ответ.Для других вот что я нашел.Это работает, только если вы используете Postgres> = 9,4 и Django> = 9,0 .

Вы можете сделать следующее:

MyModel.objects.filter( ... ).values('uid', names=ArrayAgg('m2m__name'))

Будет давать следующее:

<MyModelQuerySet [{'uid': 'id_1', 'names': ['name_1', 'name_2', ...]}]>
...