Django ORM LEFT JOIN SQL

Добрый день) Подскажите пожалуйста, в django models в Foreign Key, при создании соединения, создается ячейка в базе _id по которой в последствии выполняются JOIN запросы, подскажите как указать свою ячейку по которой делать JOIN, не могу создать таблицы в уже созданной базе данных


I need a banal simple LEFT JOIN without connection with _id.
Or specify another cell in the database for JOIN instead of _id, for example
CastleModels.id = ClanModels.hasCastle


class ClanInfoModels(models.Model):
    clan_id = models.IntegerField()
    name = models.CharField(max_length=80)

    class Meta:
        db_table = 'clan_subpledges'
        managed = False


class ClanModels(models.Model):
    clan_id = models.IntegerField()
    hasCastle = models.IntegerField(primary_key=True)

    class Meta:
        db_table = 'clan_data'
        managed = False


class CastleModels(models.Model):
    id = models.IntegerField(primary_key=True)
    name = models.CharField(max_length=11)

    class Meta:
        db_table = 'castle'
        managed = False
        ordering = ['id']
need sql query = 

SELECT castle.name, castle.id, clan_subpledges.name as 'name_clan' FROM замок LEFT JOIN clan_data ON clan_data.hasCastle = castle.id LEFT JOIN clan_subpledges ON clan_subpledges.clan_id = clan_data.clan_id

Просто назовите свое поле.

class ClanModels(models.Model):
    clan_id = models.IntegerField()
    hasCastle = models.ForeignField('CastleModels', db_column='hasCastle', on_delete=models.Cascade)

Вы можете использовать Subquery для решения вашей проблемы, но не должны. Я думаю, что проблема вашего кода в том, что модели определены неправильно. Это должно быть так:

class ClanInfo(models.Model):
    clan = models.ForeignKey('Clan')
    name = models.CharField(max_length=80)

    class Meta:
        db_table = 'clan_subpledges'
        managed = False


class Clan(models.Model):
    id = models.IntegerField(primary_key=True)
    hasCastle = models.ForeignKey('Castle')

    class Meta:
        db_table = 'clan_data'
        managed = False


class Castle(models.Model):
    id = models.IntegerField(primary_key=True)
    name = models.CharField(max_length=11)

    class Meta:
        db_table = 'castle'
        managed = False
        ordering = ['id']

Тогда вы можете просто запросить следующим образом:

 Castle.objects.values('name', 'id', 'clan__claninfo__name')

Чтобы узнать, как работает обратный запрос, пожалуйста, прочитайте документацию. FYI: Я удалил Models из каждого имени класса модели, потому что вам не нужно добавлять Models к имени класса, идентифицируя его как модель.

Кроме того, если вы настаиваете на сохранении существующего кода, то следующий код может работать, используя subquery:

from django.db.models import OuterRef, Subquery


outer_query = ClanInfo.objects.filter(clan_id=OuterRef('id'))
CastleModels.objects.annotate(clan_subpledges=Subquery(outer_query.values('name')[:1]).values('id', 'name', 'clan_subpledges')

Используйте преимущества опции db_column в определении модели Django.

db_column: Имя колонки базы данных, которую следует использовать для этого поля.

Ваш SQL можно записать как

from django.db.models import F
from .models import CastleModels

queryset = CastleModels.objects.values('name', 'id', name_clan=F('clanmodels__claninfomodels__name'))

Я не могу полностью вывести дизайн вашей модели, но если

  1. замок может содержать ноль или несколько кланов, а
  2. clan_id фактически является первичным ключом клана.

Тогда модели могут быть определены как:

class CastleModels(models.Model):
    id = models.IntegerField(primary_key=True)
    name = models.CharField(max_length=11)

    class Meta:
        db_table = 'castle'
        managed = False
        ordering = ['id']

class ClanModels(models.Model):
    clan_id = models.IntegerField(primary_key=True) 
    hasCastle = models.ForeignKey(CastleModels, on_delete=models.DO_NOTHING, db_column='hasCastle')

    class Meta:
        db_table = 'clan_data'
        managed = False

class ClanInfoModels(models.Model):
    clan_id = models.OneToOneField(ClanModels, on_delete=models.DO_NOTHING, db_column='clan_id')
    name = models.CharField(max_length=80)

    class Meta:
        db_table = 'clan_subpledges'
        managed = False
Вернуться на верх