0

I want to insert only new data into my database. In case, the data with the same primary key is already in the database, I want to ignore it and not raise an exception. However, the default ModelSerializer's create function seems to raise and exception if the value already exists in the table. So, I am trying to solve this problem by overriding the ModelSerializer's create() function.

Here's my code:

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'

and I am calling the seralizer instance's save method using this:

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

The values get saved if I submit new values. However, I get an error if I try to submit values already in the table:

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

The print statements on the overriddent create() don't print anything either. So, I am guessing that the overridden method is not running at all. What am I doing wrong or what would be the proper way to tackle this problem? Thank you.

  • Probably you're trying to create an `UsrPlaceMap` with the same content on `ggl_place_id` of an existing one. That happens because you have `primary_key=True` on that field. The solution wouldn't be to override the `create` method on the serializer but instead drop the `primary_key=True` if that's possible. – Higor Rossato Oct 04 '19 at 14:30
  • You might want to use `logging` help you debug vs `print`. [Here](https://docs.djangoproject.com/en/2.2/topics/logging/) is the documentation – Codebender Oct 04 '19 at 14:36

2 Answers2

0

I think the problem is where you are checking if the queryset is None.

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

So at this place_map = UsrPlaceMap.objects.filter(ggl_plc_id=place_id) you have the variable place_map which is a queryset. You can checkout how to determine that a queryset returned some data or not here.

Codebender
  • 195
  • 1
  • 10
0

The error message you are getting is the result of serializer's validation which is done before the create is called.

You cannot call serializer.save() without calling is_valid ( you'd get error like : You must call .is_valid() before calling .save()).

So your code snippet is not complete.

In your model, you have primary key on the field ggl_plc_id so when you make the post request to create such object, it validates the field value and since it is primary key, it must be unique.

If i understood correctly, you want to insert new record if it does not already exists.

I would suggest to handle it in the view. That means you check if such record exists, if yes, you use the serializer to serializer the existing record, otherwise you use it to create the record.

Enthusiast Martin
  • 3,041
  • 2
  • 12
  • 20
  • Thank you. I'll consider doing it in the view instead. Is it a good idea to overwrite the validators? – Sarthak Adhikari Oct 04 '19 at 16:20
  • @SarthakAdhikari since you want to return existing object, you;d need to implement some logic if you try to go down the "ovverriding vaidator" route - and me personally, i dont like so much. Just handle it in the view. it will be eaiser to understand. – Enthusiast Martin Oct 05 '19 at 05:43