Можно ли вручную изменить значение ID первичного ключа в Django Model через сериализаторы?

Можно ли как-то вручную изменить значение ID в AutoField (первичный ключ) через сериализатор?
Я нашел это в документации Django: https://docs.djangoproject.com/en/4.0/ref/models/instances/#auto-incrementing-primary-keys, но я понятия не имею, как это сделать, включая сериализаторы.

Моя задача такова: Если пост с заданным ID не существует, получить пост из внешнего API и сохранить его.

Модель:

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)

Мой сериализатор:

from rest_framework import serializers
from .models import Post


class PostSerializer(serializers.ModelSerializer):
    class Meta:
        model = Post
        fields = ['id', 'user_id', 'title', 'body']

Мое мнение:

@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

Структура должности:

 {
    "user_id": 1,
    "id": 1,
    "title": "Blabla",
    "body": "Lorem Ipsum"
  },

Эта реализация получает пост с заданным ID из API, затем сохраняет его, но уже с другим ID. Есть ли лучшие способы сделать это? Дайте мне знать ниже!

пробовали ли вы PostSerializer(data=found_post, id = id)?

Функция AutoField для построения пк требует уникальный идентификатор, и он не может/не должен быть изменен в БД (насколько я знаю).

Я бы сосредоточился на том, чтобы решить эту задачу другим способом. Вы можете использовать try/except для проверки существования объекта:

try:
    ObjectName.objects.get(id=self.kwargs['id'])  # insert correct syntax for your use case
except ObjectName.DoesNotExist:
    # Make external call here

сначала: Вам не нужно создавать автоключ. Django сделает это автоматически.

class Post(models.Model):
    user_id = models.IntegerField(default=1)
    title = models.CharField(max_length=200)
    body = models.CharField(max_length=500)

во второй: Вы сохраняете модель на GET, это плохая десигнация:

  • GET для чтения.
  • POST для записи.

Наконец, попробуйте использовать представления и наборы представлений из DRF, это проще:

class CreatePostAPIView(CreatePostAPIView):
    model=Post

Вы можете вызывать это DRF-представление везде:

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)

Мое мнение, где-то нарушена бизнес-логика в post_detail_id.

Если вы используете serializers.ModelSerializer, как в приведенном выше примере class CarSerializer(serializers.ModelSerializer):. Вы можете установить дополнительные свойства при сохранении.

serializer = CarSerializer(data=car)
if serializer.is_valid():
    serializer.save(id=id)

Вы можете добавлять другие свойства, если они есть в модели. Я не могу найти другого решения, чтобы сделать это.

Я нашел этот способ здесь Solution. Надеюсь, это поможет

Вернуться на верх