Django休息框架无法保存外键

时间:2017-06-14 13:58:20

标签: django django-rest-framework

当我将json发送到我的序列化程序时,除了一个具有外键关系的字段外,所有字段都会保存。

我的设置如下:

模型

class Day(models.Model):
  date = models.DateField(auto_now=False, auto_now_add=False)
  price = models.FloatField()
  paymentMethod = models.CharField(max_length = 200)

def __unicode__(self):
    return str(self.date)

class Reservation(models.Model):
  start = models.DateField(verbose_name='Заезд', auto_now=False, auto_now_add=False, blank=False)
  end = models.DateField(verbose_name='Выезд', auto_now=False, auto_now_add=False, blank=False)
  check_in_time = models.TimeField(verbose_name='Время заезда', blank=False)
  check_out_time = models.TimeField(verbose_name='Время выезда', blank=False)
  has_refund = models.BooleanField(verbose_name='Возвратная бронь', default=True)
  payed = models.BooleanField(verbose_name='Оплачено', default=False)
  room = models.ForeignKey('Room', null=True, blank=True, verbose_name='Номер', on_delete=models.CASCADE)
  reserved_days = models.ManyToManyField(Day, blank=False)
  guest_name = models.CharField(verbose_name='Имя гостя', max_length=200, blank=True)
  reservation_number = models.CharField(verbose_name='Номер брони', max_length=200, blank=True)


class Room(models.Model):
  name = models.CharField(max_length = 200, null=True)

def __unicode__(self):
    return self.name

串行器

class DaySerializer(serializers.ModelSerializer):
class Meta:
    model = Day
    fields = [
        'date',
        'price',
        'paymentMethod',
    ]

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

class ReservationSerializer(serializers.ModelSerializer):
    room = RoomSerializer
    reserved_days = DaySerializer(many=True)

    class Meta:
        model = Reservation
        fields = [
            'start',
            'end',
            'check_in_time',
            'check_out_time',
            'reserved_days',
            'room',
            'has_refund',
            'payed',
            'guest_name',
            'reservation_number',
        ]

    def create(self, validated_data):
        day_data = validated_data.pop('reserved_days')
        room = validated_data.pop('room')

        reservation = Reservation.objects.create(**validated_data)
        existing_room = Room.objects.get_or_create(pk=room.pk)
        reservation.room = existing_room

        for day in day_data:
            day, created = Day.objects.get_or_create(date=day['date'], price=day['price'], paymentMethod=day['paymentMethod'])
            reservation.reserved_days.add(day)
        return reservation

我发送的JSON

    {
    "start": "2017-12-12",
    "end": "2017-12-12",
    "has_refund": false,
    "room": 0,
    "reserved_days": [ {
       "date": "2017-12-12",
       "price": "2",
       "paymentMethod": "3"
    },
    {
        "date": "2017-12-13",
        "price": "2",
        "paymentMethod": "3"
    }
    ],
    "check_in_time": "14:00",
    "check_out_time": "12:00",
    "guest_name": "Ivan",
    "payed": false
    }

响应

ValueError at /core/create/
Cannot assign "(<Room: kremlin>, False)": "Reservation.room" must be a "Room" instance.

更新

工作序列化程序

def create(self, validated_data):
    day_data = validated_data.pop('reserved_days')
    room = validated_data.pop('room')

    reservation = Reservation.objects.create(**validated_data)
    existing_room = Room.objects.get(name=room['name'])
    reservation.room = existing_room
    reservation.save()

    for day in day_data:
        day, created = Day.objects.get_or_create(date=day['date'], price=day['price'], paymentMethod=day['paymentMethod'])
        reservation.reserved_days.add(day)
    return reservation

1 个答案:

答案 0 :(得分:1)

get_or_create返回(object,created)元组,以便解释你得到的错误 以下答案正在修改

仔细查看您的代码,我注意到您正在创建Reservation第一个&amp;然后分配房间但从不保存。我已经更改了它,以便首先获得房间并将其添加到经过验证的数据中,以便正确保存。

class ReservationSerializer(serializers.ModelSerializer):
    room = RoomSerializer()

    def create(self, validated_data):
        day_data = validated_data.pop('reserved_days')
        room = validated_data.pop('room')

        if room.pk:
            room_id = room.pk
        else:
            room_id = Room.objects.create(name=room.name).id
        validated_data["room_id"] = room_id

        reservation = Reservation.objects.create(**validated_data)

        for day in day_data:
            day, created = Day.objects.get_or_create(date=day['date'], price=day['price'], paymentMethod=day['paymentMethod'])
            reservation.reserved_days.add(day)
        return reservation

另请注意,get_or_create会出现竞争条件,这会导致多行同时插入相同的参数。