Как построить Django QuerySet для проверки условий на двух полях manyToMany

У меня есть следующие модели (упрощенно):

class Resource(models.Model):
    name = models.CharField(max_length=64, unique=True)  

class ResourceFlow(models.Model):
    resource = models.ForeignKey(Resource, related_name="flow")
    amount = models.IntegerField()

class Workflow(models.Model):    
    inputs = models.ManyToManyField(ResourceFlow, related_name="workflow")

class Stock(models):
    resource = models.ForeignKey(Resource, related_name="stock")
    amount = models.IntegerField()    

class Producer(models.Model):   
    workflow = models.ForeignKey(Workflow, related_name="location")
    stocks = models.ManyToManyField(Stock, related_name="location")

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

Производство может начаться, если у меня достаточно запасов: для рабочего процесса Производителя, все входы ResourcesFlow amount должны присутствовать в запасах Производителя

Так что набор запросов может быть одним из таких результатов:

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

Возможно ли это сделать в Django? И если да, то как это сделать?

Не уверен, что вы нашли ответ, но в любом случае, надеюсь, я правильно понял ваш вопрос.

Предположим, что у нас есть следующие ресурсы:

head = Resource.objects.create(name="head")
neck = Resource.objects.create(name="neck")
body = Resource.objects.create(name="body")
arm = Resource.objects.create(name="arm")
leg = Resource.objects.create(name="leg")

У нас есть build_a_robot рабочий процесс:

build_a_robot = Workflow.objects.create()
build_a_robot.inputs.add(ResourceFlow.objects.create(resource=head, amount=1))
build_a_robot.inputs.add(ResourceFlow.objects.create(resource=neck, amount=1))
build_a_robot.inputs.add(ResourceFlow.objects.create(resource=body, amount=1))
build_a_robot.inputs.add(ResourceFlow.objects.create(resource=arm, amount=2))
build_a_robot.inputs.add(ResourceFlow.objects.create(resource=leg, amount=2))

Наконец, у нас есть producer:

producer = Producer.objects.create(workflow=build_a_robot)
producer.stocks.add(Stock.objects.create(resource=head, amount=0))
producer.stocks.add(Stock.objects.create(resource=neck, amount=3))
producer.stocks.add(Stock.objects.create(resource=body, amount=1))
producer.stocks.add(Stock.objects.create(resource=arm, amount=10))
producer.stocks.add(Stock.objects.create(resource=leg, amount=1))

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

Я думаю, что вот один из способов сделать это:

from django.db.models import OuterRef, Subquery

required_resources = ResourceFlow.objects.filter(pk__in=producer.workflow.inputs.values("pk")).values("resource")
required_amount = producer.workflow.inputs.filter(resource=OuterRef("resource")).values("amount")[:1]
missing_stocks = Stock.objects.filter(resource_id__in=required_resources).filter(amount__lt=required_amount)

В данном примере missing_stocks будет равно:

<QuerySet [<Stock: Stock [Resource [head], 0]>, <Stock: Stock [Resource [leg], 1]>]>

Итак, нам нужны еще голова и ноги, чтобы построить робота.

Вернуться на верх