Модель запроса Django A и исключить некоторые элементы из связанной модели B - PullRequest
1 голос
/ 22 октября 2019

Я новичок в Django, и у меня возник вопрос, на который я не ответил на Stackoverflow. По сути, у меня есть 2 модели: Клиент и Заказ, определенные ниже:

class Client(models.Model):
  name = models.CharField(max_length=200)
  registration_date = models.DateTimeField(default=timezone.now)
  # ..


class Order(models.Model):
  Client = models.ForeignKey(ModelA, on_delete=models.CASCADE, related_name='orders')
  is_delivered = models.BooleanField(default=False)
  order_date = models.DateTimeField(default=timezone.now)
  # ..        

Я бы хотел, чтобы мой QuerySet clients_results выполнил 2 следующих условия:

  • Заполнение клиентских объектовнекоторые условия (например, их имя начинается с «d», и они зарегистрированы в 2019 году, но это может быть более сложным)
  • Упорядочить объекты, к которым я могу получить доступ, используя отношение orders, определенное в «related_name»:только те, которые удовлетворяют другим условиям;например, заказ не был доставлен и был выполнен за последние 6 недель.

Я мог бы сделать это непосредственно в шаблоне, но мне кажется, что это неправильный способ сделать это. Кроме того, я прочитал в doc , что Base Manager из Order не должен использоваться для этой цели. Наконец, я нашел вопрос относительно близкий к моему, используя Q и F, но в конце я получил бы order_id, в то время как, в идеале, я хотел бы получить весь объект.

Не могли бы вы посоветовать мне лучший способ решить эту проблему?

Большое спасибо за вашу помощь!

1 Ответ

0 голосов
/ 22 октября 2019

Вам, вероятно, следует использовать Prefetch(..) объект [Django-doc] здесь, чтобы получить связанные недоставленные Order s для каждого Client и сохранить ихв Client с, но затем в другом атрибуте, поскольку в противном случае это может вызвать путаницу.

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

from django.db.models import Prefetch
from django.utils.timezone import now
from datetime import timedelta

last_six_weeks = now() - timedelta(days=42)

clients_results = Client.objects.filter(
    <b>name__startswith='d'</b>
).prefetch_related(
    Prefetch(
        'orders',
        Order.objects.filter(<b>is_delivered=False, order_date__gte=last_six_weeks</b>),
        to_attr='nondelivered_orders'
    )
)

Это будет содержать все Client s, где имя начинается с 'd', и каждый объект Client, возникающий из этого набора запросов, будет иметь атрибут nondelivered_orders, который содержит список Order s, которые не были доставлены и упорядочены за последние 42 дня. .

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