Почему Django Rest Framwork не показывает указанную широту? - PullRequest
1 голос
/ 05 ноября 2019

У меня есть база кода Django, которая использует Django Rest Framework (DRF) для API, который обслуживает содержимое БД для внешнего интерфейса.

Теперь я также хочу пользователейчтобы иметь возможность публиковать новый контент через этот API. У меня есть API для приема POST, но у меня возникли проблемы с gis Pointfield .

В одной из моих моделей у меня есть следующее поле:

from django.contrib.gis.db import models as gis_models

class Device(models.Model):
    geometry = gis_models.PointField(name='geometry', null=True, blank=True)
    # And some other fields

Я позволяю людям размещать геометрию в двух отдельных полях (latitude и longitude), которые я затем хочу записать в поле geometry. У меня есть DeviceSerializer, который выглядит следующим образом:

класс DeviceSerializer (HALSerializer): types = TypeSerializer (many = True) longitude = serializers.SerializerMethodField () latitude = serializers.SerializerMethodField () organization = serializers.SerializerMethodField()

class Meta:
    model = Device
    fields = (
        '_links',
        'id',
        'types',
        'longitude',
        'latitude',
        'organisation'
    )

def get_organisation(self, obj):
    if obj.owner:
        return obj.owner.organisation
    return 'Unknown'

def get_longitude(self, obj):
    if obj.geometry:
        return obj.geometry.x

def get_latitude(self, obj):
    if obj.geometry:
        return obj.geometry.y

def create(self, validated_data):
    print(validated_data)  # IN HERE I DON'T RECEIVE THE POSTED LATITUDE AND LONGITUDE

    types_data = validated_data.pop('types')
    device = Device.objects.create(**validated_data)
    for type_data in types_data:
        Type.objects.create(device=device, **type_data)

    if 'longitude' in validated_data and 'latitude' in validated_data:
        # WE NEVER REACH THIS POINT BECAUSE THE LAT AND LONG ARE NEVER POSTED
        device.geometry = Point(validated_data.pop('longitude'), validated_data.pop('latitude'))

    return device

В моем тесте я делаю следующее:

response = self.client.post(
    url,
    data={'types': [], 'latitude': 1, 'longitude': 1, 'organisation': 'abc'},
    format='json'
)

Но latitude и longitude никогда не отображаются в print(validated_data). Кто-нибудь знает, почему они там отсутствуют?

1 Ответ

1 голос
/ 05 ноября 2019

РЕДАКТИРОВАТЬ

Решение, приведенное ниже, не такое чистое, как многие другие решения, такие как приведенные в этом ответе Как я могу создать PointField с помощью API? . Я бы порекомендовал использовать этот, но при необходимости оставлю мой ниже для других


Проблема в том, что вы отправляете latitude и longitude в данных, но модель имеет только поленазывается геометрией. Я вижу, вы пытаетесь установить это, используя проверенные данные, но проверенные данные - это данные, проверенные по полям модели, поэтому вы не сможете получить их здесь. Одним из способов решения этой проблемы является добавление контекста в представление.

, если ваше представление выглядит примерно так:

class MyView():
    def create(self, request, *args, **kwargs):
        serializer = self.serializer_class(
            data=request.data,
            context={
                "latitude": request.data.get('latitude')
                "longitude": request.data.get('longitude')
            },
        )
        if serializer.is_valid:
            serilazer.save()

Тогда в сериализаторе вы можете переопределить функцию validate с помощью

def validate(self, attrs):
    latitude = self.context.get("latitude")
    longitude = self.context.get("longitude")
    attrs.update(
        {
            "geometry": Point(latitude, longitude)
        }
    )
    return super().validate(attrs)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...