обратный запрос django - PullRequest
2 голосов
/ 13 апреля 2011

Я пытаюсь выполнить запрос от родителя к потомку, и с помощью одного запроса можно получить дочерний результат в родительском.В моем примере я пытаюсь установить связь между таблицами i18n, в которую я хочу включить строку из дочерней таблицы в один запрос.

models.py

class main(models.Model):
    slug       = models.SlugField()
    is_active  = models.BooleanField(default=True)
    site       = models.ForeignKey(Site)

    def __unicode__(self):
        return self.slug

class main_i18n(models.Model):
    main        = models.ForeignKey(main)
    language    = models.CharField(max_length=2, choices=LANGUAGES)
    title       = models.CharField(max_length=50)
    class Meta:
        unique_together = (("language", "main"))
    def __unicode__(self):
        return self.title

Я попробовал следующее, чтобы запросить

a=main.objects.filter(is_active=True, main_i18n__language='en')

, и связь была выполнена отлично, вот что я видел, когда пытался напечататьquery

>>> a.query.__str__()
'SELECT `category_main`.`id`, `category_main`.`slug`, `category_main`.`is_active`, `category_main`.`site_id` FROM `category_main` INNER JOIN `category_main_i18n` ON (`category_main`.`id` = `category_main_i18n`.`main_id`) WHERE (`category_main_i18n`.`language` = en  AND `category_main`.`is_active` = True )'

Как видно из запроса, соединение выполняется правильно, но имена столбцов не включены в оператор выбора.Я не могу получить доступ к данным main_i18n при попытке сделать цикл for.

извините за мой паршивый английский и надеюсь, что я могу найти помощь,

С наилучшими пожеланиями,

---- EDIT:

ниже приведен шаблон, который в настоящее время используется, в конечном итоге я действительно хотел бы создать один запрос и выполнить перегруппировку на основе списка данных в моем представлении.

    <table class="homepage-listing">
        <tr>
            <td>
{#                {% regroup list by main as rg_main %}#}
                {% for obj in main %}
{#                    {% if obj.grouper != None %}#}
                    <div class="listing-block">
                            <a href="#" ><h3>{{ obj }}</h3></a>
                            <ul>
                                {% for s in obj.list %}
                                    <li>{{ s.list_i18n_set.get }} </li>
                                {% endfor %}
                            </ul>
                    </div>
{#                    {% endif %}#}
                {% endfor %}
            </td>
        </tr>
    </table>

--- EDIT:

Мне пришлось использовать дополнительные функции для создания одного запроса для этой цели.Я начал с этого, но немного усложняюсь, стараюсь убедиться, что столбцы не жестко закодированы в запросах и соединения верны.Может кто-нибудь сказать мне, если есть лучший способ написать запрос?

    dict = Main.objects.extra(
    select=
    {
        'main_title' : '%s.%s' % (MainI18n._meta.db_table, MainI18n._meta.get_field('title').verbose_name),
        'list_title' : '%s.%s' % (ListI18n._meta.db_table, ListI18n._meta.get_field('title').verbose_name),
    },
    tables=[
            '%s' % (MainI18n._meta.db_table),
            '%s' % (List._meta.db_table),
            '%s' % (ListI18n._meta.db_table),
    ],
    where=[
            '%s.%s=%s.%s' % (MainI18n._meta.db_table, 'main_id', Main._meta.db_table, 'id'),
            '%s.main_id=%s.id' % (List._meta.db_table, Main._meta.db_table),
            '%s.list_id=%s.id' % (ListI18n._meta.db_table, List._meta.db_table),
            'category_listi18n.language="%s"' % (request.LANGUAGE_CODE)
    ]).select_related().filter(maini18n__language=request.LANGUAGE_CODE )

Ответы [ 2 ]

2 голосов
/ 13 апреля 2011

Когда вы используете внешний ключ, вам необходимо получить доступ к этим данным через RelatedManager.В вашем случае вы должны получить доступ к данным в main_i18n из основного, например:

>>> a=main.objects.get(id=1)
>>> i18n = a.main_i18n_set.get()
>>> i18n.language
u'en'

или если вам нужно работать с несколькими объектами:

a = main.objects.filter(is_active=True, main_i18n__language='en')
for obj in a:
  i18n = obj.main_i18n_set.get()
  print i18n.language

, что, конечно, будет напечатано 'en'для каждого объекта, возвращаемого фильтром.

1 голос
/ 13 апреля 2011

Вместо этого вы можете запросить MainI18N:

MainI18N.objects.filter(main__is_active=True, language='en').select_related('main')

РЕДАКТИРОВАТЬ: Вы можете заключить это в метод пользовательского набора запросов.Быстрое решение (которое не позволяет вам далее фильтровать QuerySet) будет выглядеть примерно так:

class MainQuerySet(QuerySet):
    def translate(self, lang):
       for obj in MainI18N.filter(language=lang, main__in=self).select_related('main'):
           main = obj.main
           main.i18n = obj
           yield main
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...