Как создать объект с вложенными объектами в Django Rest Framework - PullRequest
1 голос
/ 23 мая 2019

Создание моего первого приложения Django, когда-либо здесь.У меня проблема с вставкой моего Route объекта.Вот мое models.py:

class Location(models.Model):
    location_id = models.AutoField(primary_key=True)
    location_name = models.CharField(max_length=50)
    location_lat = models.FloatField()
    location_log = models.FloatField() 

    def __str__(self):
        return self.location_name

class Route(models.Model):
    route_id = models.AutoField(primary_key=True)
    route_code = models.CharField(max_length=50)
    origin_location = models.OneToOneField(Location, related_name="origin", on_delete=models.PROTECT)
    destination_location = models.OneToOneField(Location, related_name="destination", on_delete=models.PROTECT)
    waypoint1_location = models.OneToOneField(Location, related_name="waypoint1", on_delete=models.PROTECT, blank=True, null=True)
    waypoint2_location = models.OneToOneField(Location, related_name="waypoint2", on_delete=models.PROTECT, blank=True, null=True)
    route_duration = models.DurationField(blank=True, null=True)

    def __str__(self):
        return self.route_code

Что я в основном хочу, так это иметь Route, с origin и destination в качестве обязательных и путевых точек необязательными.

Во-первых, у меня есть страница формы, где пользователь создает объекты Location независимо.

Затем у меня есть другая страница формы, где пользователь создает маршруты.Он выбирает в виде Location объекты - один для источника , один для пункта назначения и, опционально, waypoint1 и waypoint2

Итак, в этом Route создании я явно не хочу создавать новый Location.Это уже там.Я только хочу связать новый объект route с уже существующими объектами location.

My serializers.py:

class LocationSerializer(serializers.ModelSerializer):
    class Meta:
        model = Location
        fields = '__all__'

class RouteSerializer(serializers.ModelSerializer):
    origin_location = LocationSerializer(many=False, required=True)
    destination_location = LocationSerializer(many=False, required=True)
    waypoint1_location = LocationSerializer(many=False, required=False, read_only=True)
    waypoint2_location = LocationSerializer(many=False, required=False, read_only=True)

    class Meta:
        model = Route
        fields = '__all__'

Вставляемый JSON route:

{"route_code": "213123", "origin_location": {"location_id": 3, "location_name": "Tumut", "location_lat": - 35.31158, "location_log": 148.21159}, "destination_location": {"location_id": 3, "location_name": "Tumut", "location_lat": - 35.31158, "location_log": 148.21159}}

Я получаю следующую ошибку:

AssertionError at / api / route / \ nМетод .create() по умолчанию не поддерживает записи вложенных полей. \ NНаписать явный метод .create() для сериализатора planner.serializers.RouteSerializer или установить read_only=Trueдля вложенных полей сериализатора. \ n \ nRequest Метод: POST \ nRequest URL: http://localhost:8000/api/route/\n

Похоже, мне нужно написать функцию create() для моего RouteSerializer, но я не уверен, как подойтиЭто.Любая помощь приветствуется.

1 Ответ

1 голос
/ 23 мая 2019

Хорошо, я получил это на работу.Вот мои изменения:

serializers.py:

class LocationSerializer(serializers.ModelSerializer):
    class Meta:
        model = Location
        fields = '__all__'

class RouteSerializer(serializers.ModelSerializer):
    class Meta:
        model = Route
        fields = '__all__'

class RouteReadSerializer(RouteSerializer):
    origin_location = LocationSerializer(read_only=True)
    destination_location = LocationSerializer(read_only=True)
    waypoint1_location = LocationSerializer(read_only=True)
    waypoint2_location = LocationSerializer(read_only=True)

viewsets.py

class RouteViewSet(viewsets.ModelViewSet):
    queryset = Route.objects.all()
    serializer_class = RouteSerializer

    def get_serializer_class(self):
         # Define your HTTP method-to-serializer mapping freely.
         # This also works with CoreAPI and Swagger documentation,
         # which produces clean and readable API documentation,
         # so I have chosen to believe this is the way the
         # Django REST Framework author intended things to work:
         if self.request.method in ['GET']:
             # Since the ReadSerializer does nested lookups
             # in multiple tables, only use it when necessary
             return RouteReadSerializer
         return RouteSerializer

class LocationViewSet(viewsets.ModelViewSet):
    queryset = Location.objects.all()
    serializer_class = LocationSerializer

models.py

class Route(models.Model):
    route_id = models.AutoField(primary_key=True)
    route_code = models.CharField(max_length=50, unique=True)
    origin_location = models.ForeignKey(Location, related_name="origin", on_delete=models.CASCADE)
    destination_location = models.ForeignKey(Location, related_name="destination", on_delete=models.PROTECT)
    waypoint1_location = models.ForeignKey(Location, related_name="waypoint1", on_delete=models.PROTECT, blank=True, null=True)
    waypoint2_location = models.ForeignKey(Location, related_name="waypoint2", on_delete=models.PROTECT, blank=True, null=True)
    route_duration = models.DurationField(blank=True, null=True)

    def __str__(self):
        return self.route_code

Я изменилOneToOneField до ForeignKey.Это на самом деле имеет больше смысла.

Спасибо

...