Глубина DRF только для указанных полей для GET и POST
Итак, я попробовал это Stack Overflow - Django REST Framework Depth Only For Specified Fields для указания поля с глубиной, это работает, но когда я хочу сделать POST для вставки новой записи, это не может, потому что это как будто django считает мое поле как требуемое и устанавливает его в NULL. Вот мой код...
../apps/models.py
class GroupingTypes(models.Model):
grouping_name = models.CharField(max_length=255, unique=True)
description = models.TextField(null=True, blank=True)
class Meta:
db_table = 'grouping_types'
class Templates(models.Model):
id = models.UUIDField(primary_key=True, default=None, editable=False)
...
name = models.CharField(max_length=255, default=None)
grouping = models.ForeignKey(GroupingTypes, on_delete=models.CASCADE)
file = models.FileField(upload_to="templates/")
...
class Meta:
db_table = 'templates'
def delete(self, *args, **kwargs):
if self.file and os.path.isfile(self.file.path):
os.remove(self.file.path)
super().delete(*args, **kwargs)
../apps/serializers.py
class GroupingTypesSerializer(serializers.ModelSerializer):
class Meta:
model = GroupingTypes
fields = "__all__"
class TemplatesSerializer(serializers.ModelSerializer):
# Extra fields that's not defined in models
unix_timestamp_added = serializers.SerializerMethodField()
datetime_added = serializers.SerializerMethodField()
def get_unix_timestamp_added(self, obj: Templates):
return int(obj.timestamp_added.timestamp())
def get_datetime_added(self, obj: Templates):
return obj.timestamp_added.strftime("%Y-%m-%d %H:%M:%S")
grouping = GroupingTypesSerializer(read_only=True)
class Meta:
model = Templates
fields = "__all__"
extra_kwargs = {
'file': {'write_only': True}
}
../apps/views.py
# `../utils/utils.py`
def post(request: HttpRequest, Serializer: serializers.ModelSerializer):
serializer = Serializer(data=request.data)
if serializer.is_valid():
serializer.save()
print(f"\033[92mPOST\033[0m")
return Response(
{
"success": True,
"msg": "added",
"data": None,
},
status=HTTP_201_CREATED
)
print(f"\033[91mPOST\033[0m")
return Response(
{
"success": False,
"msg": serializer.errors,
"data": None,
},
status=HTTP_400_BAD_REQUEST
)
# -------------------------------------------
# views.py
class TemplatesList(APIView):
def get(self, request: HttpRequest):
...
def post(self. request: HttpRequest):
return utils.utils.post(request, Serializer=TemplatesSerializer)
../apps/urls.py
urlpatterns = [
...
path("template/", TemplatesList.as_view()),
path("template/<str:uuid>/", TemplatesDetail.as_view()),
...
]
Я попытался отправить POST в формате JSON, но получил ошибку, которая гласит:
django.db.utils.IntegrityError: null value in column "grouping_id" of relation "templates" violates not-null constraint
DETAIL: Failing row contains (828b0759-0642-4844-abfa-1b5b602a27d2, ..., TEMPLATE-NAME, null, templates/new-template_OQggWfx.xlsx, ...).
Почта тела, которую я отправил, выглядит так. Просто нормально:
{
"id": uuid.uuid4(),
...,
"name": "TEMPLATE-NAME",
"grouping": 2,
"file": InMemoryUploadedFile,
...
}
Все работает нормально для GET & POST Я удаляю эту строку
grouping = GroupingTypesSerializer(read_only=True)
Но для указанной глубины файла он не выводит данные, как ожидалось.
Вложенные сериализаторы DDRF по умолчанию доступны только для чтения, как указано здесь
Чтобы сделать эти поля доступными для записи, необходимо переопределить метод create в сериализаторе следующим образом
class TemplatesSerializer(serializers.ModelSerializer):
# Extra fields that's not defined in models
unix_timestamp_added = serializers.SerializerMethodField()
datetime_added = serializers.SerializerMethodField()
def get_unix_timestamp_added(self, obj: Templates):
return int(obj.timestamp_added.timestamp())
def get_datetime_added(self, obj: Templates):
return obj.timestamp_added.strftime("%Y-%m-%d %H:%M:%S")
grouping = GroupingTypesSerializer()
class Meta:
model = Templates
fields = "__all__"
extra_kwargs = {
'file': {'write_only': True}
}
def create(self, validated_data):
grouping_id = validated_data.get("grouping", None)
if grouping_id:
validated_data["grouping"] = GroupingTypes.objects.get(id=grouping_id)
super().create(validated_data)