Is it somehow possible to manually change ID value in AutoField (primary key) through serializer?
I found this in documentation of Django: https://docs.djangoproject.com/en/4.0/ref/models/instances/#auto-incrementing-primary-keys, but I have no idea how to do this including serializers.
My task is: If post with given ID does not exists, fetch post from external API and save it.
Model:
from django.db import models
class Post(models.Model):
id = models.AutoField(primary_key=True)
user_id = models.IntegerField(default=1)
title = models.CharField(max_length=200)
body = models.CharField(max_length=500)
My serializer:
from rest_framework import serializers
from .models import Post
class PostSerializer(serializers.ModelSerializer):
class Meta:
model = Post
fields = ['id', 'user_id', 'title', 'body']
My view:
@api_view(['GET', 'PUT', 'DELETE'])
def post_detail_id(request, id):
try:
post = Post.objects.get(pk=id)
except Post.DoesNotExist:
#-----------------------------------------------------------#
found_post = search_post(id) #fetch post from external API
if request.method == "GET" and found_post is not None:
serializer = PostSerializer(data=found_post)
if serializer.is_valid():
serializer.save()
return Response(status=status.HTTP_201_CREATED)
#-----------------------------------------------------------#
return Response(status=status.HTTP_404_NOT_FOUND)
return post_detail(request, "id", post) #method to handle CRUD
Post structure:
{
"user_id": 1,
"id": 1,
"title": "Blabla",
"body": "Lorem Ipsum"
},
This implementation fetch post with given ID from API, then saves it, but with different ID. Are there any better ways to do this? Let me know below!
CodePudding user response:
have you tried PostSerializer(data=found_post, id = id)
?
CodePudding user response:
The AutoField function to build a pk requires a unique identifier and it cannot/should not be changed in the DB (as far as I am aware).
I would focus on accomplishing the use-case another way. You could use try/except to check if the object exists:
try:
ObjectName.objects.get(id=self.kwargs['id']) # insert correct syntax for your use case
except ObjectName.DoesNotExist:
# Make external call here
CodePudding user response:
at first: You are dont need to create autokey. Django do it automatically.
class Post(models.Model):
user_id = models.IntegerField(default=1)
title = models.CharField(max_length=200)
body = models.CharField(max_length=500)
at second: You are save model on GET, it's bad desigion:
- GET for read.
- POST for write.
At last, try to use view and viewsets from DRF, it is easier:
class CreatePostAPIView(CreatePostAPIView):
model=Post
You can call this DRF-view everythere:
def post_detail_id(request, id):
....
except Post.DoesNotExist:
#-----------------------------------------------------------#
request.data = request.method == "GET" and search_post(id) #fetch
if request.data:
return CreatePostAPIView().post(request, *args, **kwargs)
#-----------------------------------------------------------#
return Response(status=status.HTTP_404_NOT_FOUND)
My opinion, somewhere business-logic in post_detail_id is broken.