O
O
Oscar Django2015-09-16 12:03:04
Django
Oscar Django, 2015-09-16 12:03:04

How to filter by date range from related table?

Task:
There are 2 tables: Car Make and Car Model

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)

For each car model, there is a year of start and end of production (the end is not for everyone).
The year comes from the user.
It is necessary to return car brands for which there is at least one model with the year of manufacture received from the user.
***
I.e. as a matter of fact function which on an input receives number is necessary, and on an output gives QuerySet from Manufacturer.
***
Example:
Manufacturer:
    id    title
    ===========
    1     Audi
    2     BMW

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

Year = 1954 comes from the user . Only Audi
needs to be returned , since BMW does not have a 1954 model.

Answer the question

In order to leave comments, you need to log in

2 answer(s)
Y
Yahweh, 2015-09-16
@winordie

Did it like this:

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()

S
Shmele, 2015-09-18
@shmele

If you have production_startand production_endit's only a year, there's no need to do them DateField. If you make them PositiveIntegerField, or at all PositiveSmallIntegerField, it will be possible to make them simpler and more efficient:

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()

Allows situations where production_start, production_endor both may be absent.
If you still stop at your option, be careful with .filter(models_car__in=cm). If the list cmgrows to hundreds or thousands of elements, imagine how gigantic the SQL query will become using it and how much memory it eats up.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question