0

I'm trying to .save() my data in database. But I get an error {'Hero_id':[ErrorDetail<string='Hero with this Hero_id already exists.',='unique'>]}. Models.py:

class Hero(models.Model):
    Hero_id = models.IntegerField(auto_created=True, primary_key=True, serialize=False, verbose_name='Hero_id')
    race = models.CharField(max_length=50, blank=True)
    age = models.IntegerField(blank=True)
    class_= models.CharField(max_length=50, blank=True)

Views.py:

class HeroSerializer(serializers.ModelSerializer):
    class Meta:
        model = Hero
        fields = ['Hero_id', 'race', 'age', 'class_']
        extra_kwargs = {
                'race': {
                    'required': False,
                    'allow_null':True
                 },
                'age': {
                    'required': False,
                    'allow_null':True
                 },
                'class_': {
                    'required': False,
                    'allow_null':True
                 }
            }

def PATCH(request):
if request.method == "PATCH":
      stream = io.BytesIO(request.body)
      data = JSONParser().parse(stream)
      serializer = HeroSerializer(data=data["json"],partial=True)
      if serializer.is_valid():
            serializer.save()
            return JsonResponse(data,save=False)
      return JsonResponse(serializer.errors)

My incoming data is always containing Hero_id. Example: {"json":{"Hero_id":"4", "race":"orc"}} or {"json":{"Hero_id":"4", "race":"Human", "age":"34", "class_":"archer"}} Questions: 1)How to patch specific row in database depending on Hero_id? 2)How can I pass a request.data? I always get an error 'WSGIRequest' object has no attribute 'data'. 3)Is there any difference between JSONParser().parse(io.BytesIO(request.body)) and request.data in my case?

Denzel
  • 359
  • 4
  • 12

1 Answers1

2

You need to pass updating instance to serializer. Without it, djnago will try to create new object:

@api_view 
def PATCH(request):
  instance = Hero.objects.get(Hero_id=request.data["json"]["Hero_id"])
  serializer = HeroSerializer(instance, data=data["json"], partial=True)
  if serializer.is_valid():
        serializer.save()
        return JsonResponse(data)
  return JsonResponse(serializer.errors)

BTW you can use api_view decorator to enable Django rest framework request. In this case you don't need to parse request body manually.

neverwalkaloner
  • 46,181
  • 7
  • 92
  • 100
  • Hmm... Now when I try JsonResponse(data) it returns [{"model": "testing.Hero", "pk": 7, "fields": {"race": "Human", "age": 7, "class": "swordsman"}}, {"model": "testing.Hero", "pk": 8, "fields": {"race": "Elf", "year": 360, "class": "archer"}}]. Why "model" and "pk" is in Json? What is more "pk" replaced Hero_id. Even when i try to GET/POST database return this type of Json. How can i return back to [{{ "Hero_id": 7, "race": "Human", "age": 7, "class": "swordsman"}, { "Hero_id": 8, "race": "Elf", "year": 360, "class": "archer"}}]? – Denzel Jan 03 '20 at 16:39
  • 1
    @Denzel I think iy should be `return JsonResponse(serializer.data)`. – neverwalkaloner Jan 03 '20 at 16:44
  • Well it works. But how can i use this to return all data in my database? I tried `h=Hero.objects.all() serializer= HeroSerializer(h) return JsonResponse(serializer.data)` but it returns an error – Denzel Jan 03 '20 at 17:21
  • Got AttributeError when attempting to get a value for field `Hero_id` on serializer `HeroSerializer`. The serializer field might be named incorrectly and not match any attribute or key on the `str` instance. Original exception text was: 'str' object has no attribute 'Hero_id'. – Denzel Jan 03 '20 at 17:34