winordie
@winordie
Лучшая документация -- исходники

Как отфильтровать по диапазону дат из связаной таблицы?

Задача:

Есть 2 таблицы: Марка автомобиля и Модель автомобиля
class Manufacturer(models.Model):
    title = models.CharField(_("Full name"), max_length=255, blank=True)

class CarModel(models.Model):
    manufacturer = models.ForeignKey(Manufacturer, on_delete=models.PROTECT, related_name="models_car")
    production_start = models.DateField(null=True, blank=True)
    production_end = models.DateField(null=True, blank=True)


Для каждой модели авто есть год начала и окончания выпуска (конец не для всех есть).

От пользователя приходит год.

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

Т.е. по сути необходима функция которая на вход получает число, а на выходе отдает QuerySet из Manufacturer.

***

Пример:
Manufacturer:
    id    title
    ===========
    1     Audi
    2     BMW

Model:
    mfa_id     start      end
    =========================
    1          1932       1960
    1          1980       2001
    2          1977       2014
    2          2004       ----


От пользователя приходит год = 1954.

Нужно вернуть только Audi, тк у BMW нет модели 1954 года выпуска.
  • Вопрос задан
  • 224 просмотра
Решения вопроса 1
@Yahweh
Сделал так:
def get_mfa(year):
    year = date(int(year), 1, 1)
    cm = CarModel.objects.filter(Q(production_end__gte=d) | Q(production_end=None), production_start__lte=d) 

    return Manufacturer.objects.filter(models_car__in=cm).distinct()
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
Shmele
@Shmele
Python developer
Если у вас production_start и production_end это только год, нет необходимости делать их DateField. Если сделать их PositiveIntegerField или вообще PositiveSmallIntegerField можно будет сделать проще и эффективнее:
def get_mfa(year):
    return CarModel.objects.filter(
        Q(production_start__lte=year) | Q(production_start__isnull=True),
        Q(production_end__gte=year) | Q(production_end__isnull=True)
    ).values_list('manufacturer', flat=True).distinct()

Допускает ситуации, когда production_start, production_end или они обе могут отсутствовать.

Если всё же остановитесь на своём варианте, будьте осторожны с .filter(models_car__in=cm). Если список cm разрастётся до сотен или тысяч элементов, представьте каким гигантским станет SQL запрос с его использованием и сколько он скушает памяти.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы