Как присоединиться к кверисету

У меня есть некоторые проблемы с QuerySet в Django python. У меня есть 2 таблицы/модели

class PP(models.Model):
    imei = models.BigIntegerField(primary_key=True)
    name = models.CharField(max_length = 50)
    val2 = models.IntegerField(default = 0)

    def __str__(self):
        return self.name

class Mea(models.Model):
    imei = models.ForeignKey(PP, on_delete=models.CASCADE)
    v1 = models.IntegerField(default = 0)
    v2 = models.IntegerField(default = 0)
    v3 = models.IntegerField(default = 0)
    dates = models.DateField(default=datetime.date.today)

    def __str__(self):
        return self.imei
PP
    +----+--------+------+
    |imei|  name  | val2 |
    +----+--------+------+
    |  1 | john   |   12 |
    |  2 | adam   |    5 |
    |  3 | alfred |    3 |
    +----+--------+------+



Mea
+----+----+----+-----+---------------------+
|imei| v1 | v2 | v3  |        date         |
+----+----+----+-----+---------------------+
|  1 |  4 | 15 |  18 | 2020-10-16 11:15:53 |
|  1 |  2 | 12 |  17 | 2020-10-16 11:22:53 |
|  1 |  3 | 13 |  16 | 2020-10-16 11:32:53 |
|  2 |  1 | 16 |  15 | 2020-10-16 13:22:53 |
|  2 |  3 | 13 |  25 | 2020-10-16 13:42:53 |
|  2 |  4 | 12 |  35 | 2020-10-16 14:12:53 |
|  3 |  1 | 21 | 12  | 2020-10-16 14:12:53 |
|  3 |  2 | 28 | 42  | 2020-10-16 15:12:53 |
|  3 |  4 | 30 | 72  | 2020-10-16 16:12:53 |
+----+----+----+-----+---------------------+

Мне нужно получить в одной таблице ID, NAME, v1,v2,v3, дату для новой даты для всех объектов из первой таблицы. что-то вроде этого:

RESULT
+----+--------+----+----+-----+---------------------+
|imei|  name  | v1 | v2 | v3  |        date         |
+----+--------+----+----+-----+---------------------+
|  1 | john   |  3 | 13 |  16 | 2020-10-16 11:32:53 |
|  2 | adam   |  4 | 12 |  35 | 2020-10-16 14:12:53 |
|  3 | alfred |  4 | 30 | 72  | 2020-10-16 16:12:53 |
+----+--------+----+----+-----+---------------------+

Мне нужна самая новая запись из ВТОРОЙ ТАБЛИЦЫ для всех людей из первой таблицы.

Возможно ли это сделать с помощью queryset ?

Добавьте новое свойство к вашей модели PP следующим образом:

class PP(models.Model):
    imei = models.BigIntegerField(primary_key=True)
    name = models.CharField(max_length = 50)
    val2 = models.IntegerField(default = 0)
    @property
    def last_mea(self):
        return self.mea_set.order_by('date','id').last()
    def __str__(self):
        return self.name

class Mea(models.Model):
    imei = models.ForeignKey(PP, on_delete=models.CASCADE)
    v1 = models.IntegerField(default = 0)
    v2 = models.IntegerField(default = 0)
    v3 = models.IntegerField(default = 0)
    dates = models.DateField(default=datetime.date.today)

    def __str__(self):
        return self.imei

С помощью этого нового свойства вы можете получить доступ к last_mea doing:

pp.last_mea

Итак, в ваших шаблонах, предполагая кверисет объектов PP:

{% for q in queryset %}
    <tr>
        <td>{{q.imei}}</td>
        <td>{{q.name}}</td>
        <td>{{q.last_mea.v1}}</td>
        <td>{{q.last_mea.v2}}</td>
        <td>{{q.last_mea.v3}}</td>
        <td>{{q.last_mea.dates | date:'Y-m-d'}}</td>
    </tr>
{% endfor %}

РЕДАКТИРОВАНИЕ:

Вы не можете показать время в таком формате: "2020-10-16 11:15:53", потому что вы храните только дату без времени. Тип поля "даты" - это "DateField", а не "DateTimeField". Если вам нужно время, измените DateField на DateTimeField и значение по умолчанию (today --> now).

При условии, что все PP имеют одну или более связанных mea (т.е. без нулей), тогда, я думаю, вы можете фильтровать таблицу mea для исключения дубликатов, и вы не пропустите ни одной строки PP без одной или более связанных строк Mea.

qs = Mea.objects.order_by('-dates'      # descending, so newest first
   ).distinct( 'imei'                   # first row only for each imei 
   ).order_by( 'imei'                   # re-order if required. 
   ).select_related('imei'              # for efficiency
   )

for mea_instance in qs:
    ...

Доступ к данным из pp осуществляется через mea_instance.imei.name и т.д. .select_related('imei') должен кэшировать другой объект, чтобы не было N дальнейших запросов к БД.

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