DRF序列化器只能单向工作,输出正常,但输入错误

时间:2017-08-09 10:43:08

标签: django django-rest-framework geodjango

我正在尝试按照此http://www.django-rest-framework.org/api-guide/fields/#custom-fields来序列化GeoDjango中的Point。但只能得到以下例外。无法弄清楚我的错误在哪里。

输出正确,但在插入相同输出时出错。

错误输出:

Got a `TypeError` when calling `Venue.objects.create()`. This may be because you have a writable field on the serializer class that is not a valid argument to `Venue.objects.create()`. You may need to make the field read-only, or override the VenueSerializer.create() method to handle this correctly.
Original exception was:
 Traceback (most recent call last):
  File "/usr/local/lib/python3.5/dist-packages/rest_framework/serializers.py", line 916, in create
    instance = ModelClass.objects.create(**validated_data)
  File "/usr/local/lib/python3.5/dist-packages/django/db/models/manager.py", line 85, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/usr/local/lib/python3.5/dist-packages/django/db/models/query.py", line 394, in create
    obj.save(force_insert=True, using=self.db)
TypeError: save() got an unexpected keyword argument 'force_insert'

来自serializers.py:     来自django.contrib.gis.geos import Point

class LocationField(serializers.Field):
    def to_representation(self, obj):
        return "%s,%s" % (obj.y, obj.x)

    def to_internal_value(self, data):
        lat,lng = [str(col) for col in data.split(',')]
        pnt = Point(float(lat), float(lng), srid=4326)
        return pnt

class VenueSerializer(serializers.ModelSerializer):
    location = LocationField()
    class Meta:
        model = Venue
        fields = ('id', 'name', 'description', 'website', 'location')
        read_only_fields = ('created_at', 'modified_at')

来自models.py:

from __future__ import unicode_literals
from django.contrib.gis.db import models
from django.conf import settings
from django.contrib.auth import get_user_model
from pygeocoder import Geocoder


def get_sentinel_user():
    return get_user_model().objects.get_or_create(username='system')[0]


class Venue(models.Model):
    """
    Model for venues
    """
    name = models.CharField(max_length=254)
    description = models.TextField(max_length=512, blank=True)
    website = models.CharField(max_length=254, blank=True)

    address = models.CharField(max_length=254, blank=True)
    location = models.PointField()

    owner = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.SET(get_sentinel_user),
    )

    created_at = models.DateTimeField(auto_now_add=True)
    modified_at = models.DateTimeField(auto_now=True)

    objects = models.GeoManager()

    def __str__(self):
        return self.name

    class Meta:
        ordering = ('created_at',)

    def save(self):
        if not self.address:
            geo = Geocoder.reverse_geocode(self.location.y, self.location.x)
            self.address = geo.formatted_address
        super(Venue, self).save()

1 个答案:

答案 0 :(得分:0)

models.py中的save()函数缺少**kwargs

更正了以下内容:

def save(self, **kwargs):
    if not self.address:
        geo = Geocoder.reverse_geocode(self.location.y, self.location.x)
        self.address = geo.formatted_address
    super(Venue, self).save()