Как вернуть первый сериализованный объект, а не все в Django? - PullRequest
0 голосов
/ 30 апреля 2019

У меня есть API (использующий django-rest-framework) с двумя моделями (например, Users и Cars).

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

Я пытался включить cars = CarSerializer(many=True) в сериализаторе пользователя, который возвращает все автомобили для этого пользователя.

Я пытался cars = CarSerializer(many=False), который возвращает нужный мне формат, но ни один автомобиль не включается.

код

модель автомобиля

class Car(models.Model):
    name = models.TextField(default='')
    year = models.IntegerField(null=True)
    owner = models.ForeignKey('User', related_name='cars')

автомобильный сериализатор

class CarSerializer(serializers.ModelSerializer):

    class Meta:
        model = Car
        fields = ('id', 'name', 'year', 'owner')

пользовательский сериализатор

class UserSerializer(serializers.ModelSerializer):
    car = CarSerializer(many=True)

    class Meta:
        model = User
        fields = ('id', 'first_name', 'last_name', 'car')

вид из машины

class CarViewSet(viewsets.ReadOnlyModelViewSet):
    queryset = Car.objects.all()
    serializer_class = CarSerializer

вид пользователя

class UserViewSet(viewsets.ReadOnlyModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer

Что я ищу

Учитывая две машины, принадлежащие пользователю с идентификатором 1:

id: 1
owner: 1
name: "kinda okay car"
year: 2012

id: 2
owner: 1
name: "the fastest one"
year: 2020

JSON Результат GET / users / 1

{
  "id": 1,
  "first_name": "Bob",
  "last_name": "McFastCar",
  "car": {
    "name": "the fastest one",
    "year": 2020
  }
}

Что я сейчас получаю

JSON Результат GET / users / 1

{
  "id": 1,
  "first_name": "Bob",
  "last_name": "McFastCar",
  "cars": [
    {
      "id": 2,
      "owner": 1
      "name": "the fastest one",
      "year": 2020
    },
    {
      "id": 1,
      "owner": 1
      "name": "kinda okay car",
      "year": 2012
    }
  ],
}

Спасибо, я надеюсьВы можете помочь мне найти решение.

Ответы [ 3 ]

1 голос
/ 30 апреля 2019

На самом деле вы можете создать @property в вашей User модели, которая возвращает только последний автомобиль:

class User:
    ...

    @property
    def last_car(self):
        return self.cars.last()

И затем в UserSerializer вы можете просто сериализовать это свойство:

class UserSerializer:
    last_car = CarSerializer(read_only=True)

    class Meta:
        model = User
        fields = (..., 'last_car')

Это бы сработало.


PS : Если вы по-прежнему хотите, чтобы ваша последняя запись автомобиля была сериализована как "car": { ... }, но не "last_car": { ... },Вы можете использовать атрибут source на самом CarSerializer:

class UserSerializer:
    car = CarSerializer(source='last_car', read_only=True)
    ...
0 голосов
/ 30 апреля 2019

Вы можете написать UserSerializer как ниже

class UserSerializer(serializers.ModelSerializer):
    cars = serializers.SerializerMethodField()

    class Meta:
        model = User
        fields = ('id', 'first_name', 'last_name', 'cars')

    def get_cars(self, instance):
        cars = instance.cars.all().order_by('-year')
        return CarSerializer([cars[0], ], many=True).data

и вызов GET /users/1 вернет результаты, подобные этому

{
    "id": 2,
    "first_name": "Bob",
    "last_name": "McFastCar",
    "cars": [
        {
            "id": 2,
            "name": "the fastest one",
            "year": 2020,
            "owner": 2,
            "first_name": "Bob"
        }
    ]
}

Нижняя строка выдала мне неизвестную ошибку, поэтому я написал ее со многими = True

return CarSerializer(cars, many=False).data
0 голосов
/ 30 апреля 2019

CarSerializer должен быть связан с набором запросов или объектом, иначе он вернет все объекты

# get the car object with the highest using order_by
car =  Car.objects.all().order_by('-id')[0]
# build a car serializer from the car object
car_serializer = CarSerializer(car, many=False)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...