Полное внешнее соединение в Джанго - PullRequest
8 голосов
/ 31 октября 2008

Как создать запрос на полное внешнее объединение через чип-связь M2M с использованием API QuerySet django?

Если это не поддерживается, приветствуется некоторый намек на создание собственного менеджера для этого.

Отредактировано, чтобы добавить: @ С. Лотт: Спасибо за просветление. Необходимость ВНЕШНЕГО СОЕДИНЕНИЯ исходит из приложения. Он должен сгенерировать отчет, показывающий введенные данные, даже если он еще не завершен. Я не знал о том, что результатом будет новый класс / модель. Ваши подсказки мне очень помогут.

Ответы [ 2 ]

11 голосов
/ 31 октября 2008

Django не поддерживает «соединения» в обычном смысле SQL - он поддерживает навигацию по объектам.

Обратите внимание, что реляционное соединение (внутреннее или внешнее) создает новый "класс" сущностей. Тот, который не имеет определения в Джанго. Так что нет правильного «набора результатов», так как нет определения класса для вещей, которые вы возвращаете. Лучшее, что вы можете сделать, это определить кортеж, который будет упакован с None для пропущенных комбинаций.

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

for obj in Model1.objects.all():
    if obj.model2_set().count() == 0:
        # process (obj, None) -- no Model2 association
    else:
        for obj2 in obj.model2_set.all():
            # process (obj, obj2) -- the "inner join" result

«Полное» внешнее объединение - это объединение оставшихся элементов, которые не имеют отношений.

for obj2 in Model2.objects.all():
    if obj2.model1_set().count() == 0:
        # process (None, obj2) -- no Model1 association

Проблема всегда в том, какую обработку вы выполняете с этой странной коллекцией трех разных подмножеств объектов?

Задача объектной базы данных - сосредоточить обработку на объекте и связанных с ним объектах.

Своеобразный набор, называемый «реляционным объединением», никогда не входит в исходную объектную модель. Это новый класс объектов, созданный из двух (или более) оригинальных объектов.

Хуже того, внешние объединения создают коллекцию с несколькими подклассами (внутреннее соединение, левое внешнее соединение и правое внешнее соединение). Что означает этот набор вещей ?

Подождите, может быть хуже. Если обработка включает проверку отсутствующих атрибутов (например, if someObj.anObj2attribute is None: мы, по сути, ищем Model1 элементов, с которыми не связан Model2 объект. Ммм ... почему мы поместили их во внешнее соединение, только для фильтрации они используют оператор if. Почему бы просто не выполнить отдельные запросы и правильно обработать каждое подмножество?


Редактировать: Когда вы показываете "неполный" статус, это вообще не внешнее соединение. Это намного проще. Вам нужно создать одну (или две) отдельные коллекции в функции просмотра для отображения вашего шаблона.

Во-первых, вы должны использовать коды состояния, а не наличие или отсутствие внешнего ключа. Необязательные внешние ключи не имеют «причин» - они либо есть, либо их нет. Код состояния может предоставлять полезные оттенки значения («неполное», «по ошибке», «сломано», «не применимо», «подлежит удалению» и т. Д.)

errorList1 = Model1.objects.filter( status="Incomplete" )
errorList2 = Model2.objects.filter( status="Incomplete" )

Это две неприсоединяемые части полного внешнего соединения. Затем вы можете отобразить эти два списка ошибок в своем шаблоне с соответствующими заголовками столбцов и кодами состояния и всем прочим.

Вы даже можете поместить их в одну таблицу, чтобы имитировать старый полный отчет о внешнем объединении, который раньше видели люди

<table>
    <tr><th>Model1</th><th>Model2</th></tr>
    {% for e1 in errorList1 %}
    <tr><td>e1</td><td>NULL</td></tr>
    {% endfor %}
    {% for e2 in errorList2 %}
    <tr><td>NULL</td><td>e2</td></tr>
    {% endfor %}
</table>

Выглядит как полный отчет о внешнем соединении. Без полного внешнего соединения.

1 голос
/ 12 марта 2010

Колин, один из тех, с кем я работаю, недавно написал пост о создании пользовательских объединений в Django:

http://www.caktusgroup.com/blog/2009/09/28/custom-joins-with-djangos-queryjoin/

Возможно, вы найдете там что-нибудь полезное!

...