Как я могу сериализовать список с отношением объектов, созданным из набора запросов TruncYear в Django 1.11 - PullRequest
1 голос
/ 03 ноября 2019

Мне удается получить данные временных рядов с помощью TruncYear / TruncMonth / TruncDay / и т. Д., Как показано ниже из таблицы отслеживания. Однако данные для места просто производят venue_id. Я хотел бы, чтобы это сериализовалось так, чтобы оно возвращало «имя» из таблицы отношений.

Я использую Django 1.11 и postgres 9.4

Вот мой код временного ряда:

tracking_in_timeseries_data = Tracking.objects.annotate(
                                          year=TruncYear('created_at')).values('year', 'venue_id').annotate(
                                            count=Count('employee_id',
                                                        distinct = True)).order_by('year')   


return Response(tracking_in_timeseries_data, status=status.HTTP_200_OK)    

в настоящее время выводится так:

[
    {
      "venue_id": 4,
      "year": "2017-01-01T00:00:00Z",
      "count": 1
    },
    {
      "venue_id": 2,
      "year": "2018-01-01T00:00:00Z",
      "count": 2
    },
    {
      "venue_id": 6,
      "year": "2019-01-01T00:00:00Z",
      "count": 1
    }
  ]

Я хочу разбить данные о месте проведения, чтобы вернуть идентификатор и имя следующим образом:

  [
    {
      "venue": {
                id: 4,
                name: "room A"
                },
      "year": "2017-01-01T00:00:00Z",
      "count": 1
    },
    {
      "venue": {
                id: 2,
                name: "room B"
                },
      "year": "2018-01-01T00:00:00Z",
      "count": 2
    },
    {
      "venue": {
                id: 6,
                name: "room C"
                },
      "year": "2019-01-01T00:00:00Z",
      "count": 1
    }
  ]

Как взорвать"место", чтобы вернуть идентификатор и имя? Имя полезно для целей презентации.

ОБНОВЛЕНИЕ (вот некоторые попытки, которые потерпели неудачу):

это только отображает счет, но накапливает (https://gist.github.com/axilaris/0cd86cec0edf675d654eadb3aff5b066). что-то странное и не знаю почему.

class TimeseriesSerializer(serializers.ModelSerializer):

    venue = VenueNameSerializer(source="venue_id",many=False, read_only=True)
    year = serializers.TimeField(read_only=True)
    count = serializers.IntegerField(read_only=True)

    class Meta:
        model = Tracking
        fields = ("venue",
                  "year",
                  "count")


class TimeseriesSerializer(serializers.Serializer): <-- here is another try but doesnt work serializers.Serializer

    venue_id = VenueNameSerializer(many=False, read_only=True)
    year = serializers.TimeField(read_only=True)
    count = serializers.IntegerField(read_only=True)

Я думаю, что ответ довольно близок к этому: django rest framework сериализует словарь без создания модели

К вашему сведению, это мой настоящий код (должентакже поместите это здесь) для теста, имена могут немного отличаться, но все намерения те же. https://gist.github.com/axilaris/919d1a20d3e799101a8cf6aeb4d120b5

1 Ответ

2 голосов
/ 07 ноября 2019

Вам нужно создать сериализатор для Venue, который отображает поля id и name и использовать его как поле в TrackingSerializer.

В вашем случае есть что-то ещерассмотреть: поскольку вы используете values для группировки, то, что вы получаете из набора запросов, не является объектом Tracking, поэтому ваш venue_id не может быть преобразован в объект Venue с помощью DRF.

Чтобы это исправить, вам нужно переопределить метод to_representation для VenueSerializer, чтобы получить объект Venue из его первичного ключа.

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

Модели

class Employee(models.Model):
    first_name = models.CharField(max_length=128)
    last_name = models.CharField(max_length=128)


class Venue(models.Model):
    name = models.CharField(max_length=128)


class Tracking(models.Model):
    venue = models.ForeignKey(Venue)
    employee = models.ForeignKey(Employee)
    created_at = models.DateTimeField(auto_now_add=True)

Представления

class TrackingViewSet(viewsets.ModelViewSet):
    queryset = (
        Tracking.objects
        .annotate(
            year=ExtractYear('created_at'),
        )
        .values('year', 'venue')
        .annotate(
            count=Count('employee_id', distinct=True),
        )
        .order_by('year')
    )
    serializer_class = TrackingSerializer

Сериализаторы

class VenueSerializer(serializers.ModelSerializer):
    class Meta:
        model = Venue
        fields = ['id', 'name']

    def to_representation(self, value):
        value = Venue.objects.get(pk=value)
        return super(VenueSerializer, self).to_representation(value)


class TrackingSerializer(serializers.ModelSerializer):
    venue = VenueSerializer(read_only=True)
    year = serializers.IntegerField(read_only=True)
    count = serializers.IntegerField(read_only=True)

    class Meta:
        model = Tracking
        fields = ['venue', 'year', 'count']

Обратите внимание, что я заменил ваш TruncYear на ExtractYear, разница между ними заключается в том, что первый возвращает datetime, а последний int, что, как я думаю, вам нужно.

Если вы предпочитаете использовать TruncYear вам придется заменить:

year = serializers.IntegerField(read_only=True)

на:

year = serializers.DateTimeField(read_only=True)

в TrackingSerializer.

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