0

I'm developing a project using django-rest for my backend and postgreSQL as my database.

I'm using postgreSQL ArrayField in my Recipe model to store multiple images of different instructions.

However when I send a POST request with a list of instructions images (instructions_image_list) I'am getting a weird error.

I would really appreciate if anyone could help me solve it. thanks in advance.

the error

status_code 500
'utf-8' codec can't decode byte 0xff in position 0: invalid start byte

the model

class Recipe(models.Model):
    id = models.UUIDField( 
        primary_key=True,
        default=uuid.uuid4,
        editable=False,
    )
    author = models.ForeignKey(get_user_model() , on_delete=models.CASCADE, null=True, related_name='author') 
    photo_main = models.ImageField(upload_to='media/', blank=True)
    title = models.CharField(max_length=150)
    instructions_text_list = ArrayField(models.CharField(max_length=100, blank=True,null=True),default=list, blank=True ,null=True,size=15,)
    instructions_image_list = ArrayField(models.ImageField(upload_to='media/',blank=True, null=True),default=list,  blank=True ,null=True, size=15,)

the view

class RecipeCreate(CreateAPIView):
    permission_classes = (permissions.IsAuthenticated, )
    queryset = Recipe.objects.all()
    serializer_class = RecipeCreateSerializer

    def perform_create(self, serializer):
        '''save the the current logged in user as the author of the recipe'''
        serializer.save(author=self.request.user)

1 Answer 1

1

It's better if you store recipe images in separate table instead of using ArrayField.

class Recipe(models.Model):
......

class RecipeImage(models.Model):
   recipe = models.ForeignKey(Recipe, on_delete=models.CASCADE)
   image = models.ImageField(upload_to="recipe_images/")

EDIT:

You can handle your multiple recipe images within your RecipeCreateSerializer and RecipeCreateView.

For example:


# serializer

class RecipeCreateSerializer(serializers.ModelSerializer):
      recipe_images = serializers.ListField(
        child=serializers.FileField(allow_empty_file=False, use_url=False)
    )

      class Meta:
        model = Recipe
        fields = [
           #  .. other fields
            "recipe_images",

        ]

      def create(self, validated_data):
         validated_data.pop("recipe_images", None)
         return super().create(validated_data)

# view

from django.db import transaction

class RecipeCreate(CreateAPIView):
    permission_classes = (permissions.IsAuthenticated, )
    queryset = Recipe.objects.all()
    serializer_class = RecipeCreateSerializer
    
    @transaction.atomic
    def perform_create(self, serializer):
        '''save the the current logged in user as the author of the recipe'''
        recipe = serializer.save(author=self.request.user)
        # create recipe images here with each images uploaded
        for img in self.request.data.getlist("recipe_images"):
             RecipeImage.objects.create(image=img, recipe=recipe)
        return super().perform_create(serializer)
Sign up to request clarification or add additional context in comments.

8 Comments

Thanks for the help, I thought about using this method but it's get way more messy than saving the images in ArrayField, is there any way to make my method work?
How's it way more messy it should not be messy as it's the standard way for your requirement.
Cause I will need to create manyToManyField + create different view to create the RecipeImage model + adding permissions + assigning the created models to the Recipe manyToManyField
Why you need many to many relationships? The model i posted in the answer should work and it's not necessary to create another view. You can simply create images within your recipe create view.
1. The manyToManyFiels is because I want to store multiple RecipeImage models in the Recipe model am I wrong? ,2. which field should I send in the post request to assign the images? Thanks in advance
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.