Django: Как объединить таблицы на основе значения таблиц подстановки - PullRequest
0 голосов
/ 15 ноября 2018

Я пытаюсь сделать то, что можно считать продвинутым SQL-запросом, и хотел бы знать, возможно ли это в Django, не прибегая к raw-SQL (я сделаю это, если это необходимо).

Я хочу объединить 1 или другую таблицу на основе значения, расположенного в таблице поиска в таблице, и хотел бы сделать это полностью в python / django.

Ниже приведены приблизительные примеры моделей, которые я использую:

class SpecificProduct(models.Model):
    specific_product_id = models.AutoField(primary_key=True)
    a_field = models.TextField()
    something_specific_to_this_model = models.CharField()


class GeneralProduct(models.Model):
    other_product_id = models.AutoField(primary_key=True)
    text = models.TextField()

TABLE_CATEGORIES = {
    1 : SpecificProduct,
    2 : GeneralProduct,
}

class ProductCategory(models.Model):
    category_id = models.AutoField(primary_key=True)
    table_category = models.IntegerField()  # Technically represents a table.
    category_text = models.CharField(max_length=20)


class Inventory(models.Model):
    inventory_id = models.AutoField(primary_key=True)
    product_category = models.ForeignKey(ProductCategory, on_delete=models.CASCADE)
    product_pk = models.IntegerField()  # Technically foreign key to a product table.
    quantity = models.IntegerField()

Мне нужен такой метод:

def get_product(category_id, product_pk):
    # SQL query  magic
    return one_object_of_a_specific_product_type

Этот метод должен уметь делать такие вещи, как ...

  • Дайте мне продукт (модель), где product_category = 1 и product_pk = 1. (возвращает модель SpecificProduct)
  • Дайте мне продукт, где product_category = 2 и product_pk = 50 (возвращает модель GeneralProduct)

Как вы выполняете этот запрос в Django и возможно ли это вообще?

Edit: Основываясь на ответе Кириети К, я создал модели, которые выглядят следующим образом:

from django.db import models
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes.fields import GenericForeignKey


class SpecificProduct(models.Model):
    specific_product_id = models.AutoField(primary_key=True)
    specific_text = models.TextField()

class GeneralProduct(models.Model):
    general_product_id = models.AutoField(primary_key=True)
    text = models.TextField()

class ProductCategoryLookup(models.Model):
    category_id = models.ForeignKey(ContentType, on_delete=models.CASCADE, primary_key=True)
    category_text = models.CharField(max_length=20)


class Inventory(models.Model):
    inventory_id = models.AutoField(primary_key=True)
    product_category = models.ForeignKey(ContentType, on_delete=models.CASCADE)
    product_id = models.PositiveIntegerField()
    product = GenericForeignKey('product_category', 'product_id')
    quantity = models.IntegerField()


def get_product(category_id, product_pk):
    content_type = ContentType.objects.get(id=category_id)
    inventory = Inventory.objects.get(product_category=content_type, product_id=product_pk).first()
    return inventory.product

1 Ответ

0 голосов
/ 17 ноября 2018

Вы можете использовать универсальный внешний ключ, чтобы динамически получить связь внешнего ключа с любой моделью, читайте об этом здесь. https://docs.djangoproject.com/en/2.1/ref/contrib/contenttypes/#generic-relations

Если вы переписываете свои модели, используя generic-foreign-key, то это выглядит примерно так:

class ProductCategory(models.Model):
    category_id = models.AutoField(primary_key=True)
    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
    object_id = models.PositiveIntegerField()
    table_category = models. GenericForeignKey()  # Technically represents a table.
    category_text = models.CharField(max_length=20)


class Inventory(models.Model):
    inventory_id = models.AutoField(primary_key=True)
    product_category = models.ForeignKey(ProductCategory, 
                       on_delete=models.CASCADE)
    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
    object_id = models.PositiveIntegerField()
    product = models. GenericForeignKey()  # Technically foreign key to a product table.
    quantity = models.IntegerField()

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

def get_product(model=None, category_id, product_pk):
    model = "specificproduct" if model else "generalproduct"
    content_type = ContentType.objects.get(model=model)
    inventory = Inventory.objects.get(product_category_id=category_id, object_id=product_pk, content_type=content_type)

    return inventory.product
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...