django-rest-framework Переопределение функции создания, не работающей на ModelSerializer

Я хочу вставить в свою базу данных только новые данные. В случае, если данные с тем же первичным ключом уже находятся в базе данных, я хочу проигнорировать их и не вызывать исключение. Однако функция создания по умолчанию ModelSerializer, похоже, вызывает исключение, если значение уже существует в таблице. Итак, я пытаюсь решить эту проблему, переопределив функцию create () ModelSerializer.

Вот мой код:

serializers.py

class UsrPlaceMapSerializer(serializers.ModelSerializer):
    class Meta:
        model = UsrPlaceMap
        fields = '__all__'

    def create(self, validated_data):
        place_id = validated_data.get("ggl_plc_id")
        place_map = UsrPlaceMap.objects.filter(ggl_plc_id=place_id)

        print("USRMAP INIT")

        if place_map is not None:
            print("USRMAP NOT NONE")
            return place_map

        place_map = UsrPlaceMap.objects.create(ggl_plc_id=place_id, state=validated_data.get("state"),
                                               cty_nm=validated_data.get("cty_nm"), cntry=validated_data.get("cntry"))
        print("USRMAP CREATED")

        return place_map

models.py

class UsrPlaceMap(models.Model):
    cty_nm = models.CharField(max_length=500)
    state = models.CharField(max_length=200, blank=True, null=True)
    cntry = models.CharField(max_length=500)
    ggl_plc_id = models.CharField(primary_key=True, max_length=500)

    class Meta:
        managed = False
        db_table = 'usr_place_map'

и я вызываю метод save экземпляра seralizer, используя это:

instance = UsrPlaceMapSerializer(data=data, many=True)
if instance.is_valid():
    instance.save()

Значения сохраняются, если я отправляю новые значения. Однако я получаю сообщение об ошибке, если пытаюсь отправить значения, уже содержащиеся в таблице:

 {
            "ggl_plc_id": [
                "usr place map with this ggl plc id already exists."
            ]
        }
}

Операторы печати в замещающем create () тоже ничего не печатают. Итак, я предполагаю, что переопределенный метод вообще не работает. Что я делаю не так или как лучше всего решить эту проблему? Спасибо.


person Sarthak Adhikari    schedule 04.10.2019    source источник
comment
Вероятно, вы пытаетесь создать UsrPlaceMap с тем же содержимым на ggl_place_id существующем. Это происходит потому, что в этом поле указано primary_key=True. Решением было бы не переопределить метод create в сериализаторе, а вместо этого отказаться от primary_key=True, если это возможно.   -  person Higor Rossato    schedule 04.10.2019
comment
Возможно, вы захотите использовать logging для отладки против print. Вот документация   -  person Codebender    schedule 04.10.2019


Ответы (2)


Сообщение об ошибке, которое вы получаете, является результатом проверки сериализатора, которая выполняется перед вызовом create.

Вы не можете позвонить serializer.save(), не позвонив is_valid (вы получите ошибку типа: You must call .is_valid() before calling .save()).

Итак, ваш фрагмент кода не завершен.

В вашей модели у вас есть первичный ключ в поле ggl_plc_id, поэтому, когда вы делаете почтовый запрос для создания такого объекта, он проверяет значение поля и, поскольку это первичный ключ, он должен быть уникальным.

Если я правильно понял, вы хотите вставить новую запись, если она еще не существует.

Я бы посоветовал разобраться с этим в представлении. Это означает, что вы проверяете, существует ли такая запись, если да, вы используете сериализатор для сериализации существующей записи, в противном случае вы используете его для создания записи.

person Enthusiast Martin    schedule 04.10.2019
comment
Спасибо. Вместо этого я подумаю о том, чтобы сделать это в представлении. Стоит ли перезаписывать валидаторы? - person Sarthak Adhikari; 04.10.2019
comment
@SarthakAdhikari, поскольку вы хотите вернуть существующий объект, вам нужно реализовать некоторую логику, если вы попытаетесь пойти по маршруту оверрайдинга vaidator - и лично мне это не нравится. Просто держите это в поле зрения. будет легче понять. - person Enthusiast Martin; 05.10.2019

Я думаю, проблема в том, где вы проверяете, является ли набор запросов None.

if place_map is not None:
    print("USRMAP NOT NONE")
    return place_map

Итак, в этом place_map = UsrPlaceMap.objects.filter(ggl_plc_id=place_id) у вас есть переменная place_map, которая является queryset. Вы можете узнать, как определить, что queryset вернул некоторые данные или нет, здесь.

person Codebender    schedule 04.10.2019