Как создать сложный набор запросов объединения с несколькими моделями с помощью Django ORM

#django #orm

#django #orm

Вопрос:

Я хочу создать набор запросов с несколькими таблицами. Я не могу найти ни одного ресурса, который помог бы, кроме нескольких небольших примеров объединения в 2 таблицы, я не могу найти ни одного ресурса, который был бы полезен для этого, ни в stackoverflow, ни в документах Django, ни даже в кулинарной книге ORM. Ниже приведен, во-первых, SQL, который я хочу воссоздать, за которым следуют классы моделей, упрощенные для целей этого вопроса. На самом деле у них НАМНОГО больше полей.

 SELECT  doc_uid, 
         docd_filename, 
         doct_name, 
         docd_media_url
  FROM   vugd_detail,
         vug_virtual_user_group,
         vugdoc_vug_docs,
         doc_documents,
         docd_detail,
         doct_type
  WHERE  vugd_vug_uid = vug_uid
  AND    vugdoc_vug_uid = vug_uid
  AND    vugdoc_doc_uid = doc_uid
  AND    docd_doc_uid = doc_uid
  AND    doct_uid = doc_doct_uid
  AND    vugd_status = 1
  AND    docd_status = 1
  AND    NOW() BETWEEN vugd_start_date AND vugd_end_date
  AND    NOW() BETWEEN docd_start_date AND docd_end_date
  AND    vug_uid = {{Some ID}}; 
  

class VugVirtualUserGroup(models.Model):
    objects = None
    vug_uid = models.AutoField(primary_key=True)
    vug_name = models.CharField(unique=True, max_length=30)
    vug_short_code = models.CharField(max_length=6)
    vug_created_on = models.DateTimeField()
    vug_created_by = models.CharField(max_length=30)

    class Meta:
        managed = False
        db_table = 'vug_virtual_user_group'
        app_label = 'main'
        
class VugdDetail(models.Model):
    objects = None
    vugd_uid = models.AutoField(primary_key=True)
    vugd_vug_uid = models.ForeignKey(VugVirtualUserGroup, models.DO_NOTHING, db_column='vugd_vug_uid')
    vugd_long_name = models.CharField(max_length=50)
    vugd_status = models.IntegerField()
    vugd_start_date = models.DateTimeField()
    vugd_end_date = models.DateTimeField()

    class Meta:
        managed = False
        db_table = 'vugd_detail'
        app_label = 'main'


class VugdocVugDocs(models.Model):
    onjects = None
    vugdoc_uid = models.AutoField(primary_key=True)
    vugdoc_vug_uid = models.ForeignKey(VugVirtualUserGroup, models.DO_NOTHING, db_column='vugdoc_vug_uid')
    vugdoc_doc_uid = models.ForeignKey(DocDocuments, models.DO_NOTHING, db_column='vugdoc_doc_uid')

    class Meta:
        managed = False
        db_table = 'vugdoc_vug_docs'
        app_label = 'main'


class DocdDetail(models.Model):
    objects = None
    docd_uid = models.AutoField(primary_key=True)
    docd_doc_uid = models.ForeignKey(DocDocuments, models.DO_NOTHING, db_column='docd_doc_uid')
    docd_filename = models.CharField(max_length=200)
    docd_media_url = models.CharField(max_length=300)
    docd_status = models.IntegerField()
    docd_start_date = models.DateTimeField()
    docd_end_date = models.DateTimeField()

    class Meta:
        managed = False
        db_table = 'docd_detail'
        app_label = 'main'

     
class DoctType(models.Model):
    objects = None
    doct_uid = models.AutoField(primary_key=True)
    doct_vug_uid = models.ForeignKey('VugVirtualUserGroup', models.DO_NOTHING, db_column='doct_vug_uid')
    doct_name = models.CharField(max_length=30)
    doct_start_date = models.DateTimeField()
    doct_end_date = models.DateTimeField()

    class Meta:
        managed = False
        db_table = 'doct_type'
        app_label = 'main'         


class DocDocuments(models.Model):
    object = None
    doc_uid = models.AutoField(primary_key=True)
    doc_doct_uid = models.ForeignKey('DoctType', models.DO_NOTHING, db_column='doc_doct_uid')

    class Meta:
        managed = False
        db_table = 'doc_documents'
        app_label = 'main'  
 

Как можно видеть, фактический запрос не такой сложный.
Цель здесь — просто получить список допустимых (активных, не удаленных) файлов, доступных для определенного VUG (простой группы пользователей), если группа имеет допустимый статус.
Итак, если есть какие-либо эксперты по Django ORM, которые могут помочь с тем, что на самом деле является распространенным типом SQL, который должен быть возможно преобразовать в скрипт Django ORM, ваша помощь будет искренне оценена.

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

1. Что делает objects = None на всех моделях?

2. Ничего. Его можно удалить.

3. @MichaelLindsay: обычно идея состоит в том, чтобы удалить .objects менеджера.

4. Доступ к менеджеру ORM Django по умолчанию осуществляется, хотя MODELNAME.objects это objects = None приведет к удалению доступа к нему.

5. Я тестировал его с objects = None и без objects = None, и он работает в обоих направлениях. Возможно, у вас есть совет по моему вопросу выше?

Ответ №1:

Способ Django запрашивать несколько связанных таблиц — это связать их в цепочку с использованием точечной нотации.

Пример кода sudo может помочь указать вам правильное направление.

 vug_virtual_user_group = VugVirtualUserGroup.objects.get(vug_uid="Some ID")
print(f'vug_virtual_user_group {vug_virtual_user_group}')
 

Поиск с использованием внешнего ключа для получения всех связанных объектов

 vugdoc_vugdocs = vug_virtual_user_group.vugdocvugdocs_set.all()
print(f'vugdoc_vugdocs {vugdoc_vugdocs}')
 

В этом примере предполагается, что modelmanger по умолчанию objects не переопределяется objects = None .