Samir Tendulkar
Samir Tendulkar

Reputation: 1191

Post create with multiple images using FBV

Hi everyone I am new to Django and I am going bald pulling my hair. Can someone help me with this.

I'm trying to add multiple images to my post and I am having issues. I have 2 models. One post model and One image model. My post model already has 1 imagefield. Then I have another related model which allows multiple images. Below is how my models look like

class Post(models.Model):
    user = models.ForeignKey(User, related_name='posts')
    title = models.CharField(max_length=250, unique=True)  
    slug = models.SlugField(allow_unicode=True, unique=True)  
    message = models.TextField()  
    post_image = models.ImageField()

class Image (models.Model): #(Images)
    post = models.ForeignKey(Post, on_delete=models.CASCADE)
    image = models.ImageField(upload_to='images/', blank=True, null=True)
    image_title = models.CharField(max_length=100)
    image_description = models.CharField(max_length=250)

    def __str__(self):
        return self.post.title + " Image"

Below is how my views look like. When the form loads. It has the multiple image fields. Its just not saving those images when my post is created. I get a post that completely ignores the formsets and multiple images. It only shows the Post model aspects and 1 image of the Post model. Even in the Admin there are no multiple images.

Can someone point me to what is the error in my code?

VIEWS.py 1st try

@login_required
def post_create(request):
    ImageFormset = modelformset_factory(Image, fields=('image', 'image_title', 'image_description'), extra=7)
    if request.method == 'POST':
        form = PostForm(request.POST, request.FILES)
        formset = ImageFormset(request.POST or None, request.FILES or None)
        if form.is_valid() and formset.is_valid():
            post = form.save(commit=False)
            post.user = request.user
            post.save() ## It seems as if my code just plays till here and then disconnects
            for f in formset:
                try:
                    photo = Image(post=post, image=f.cleaned_data['image', 'image_title', 'image_description'])
                    photo.save()
                    return redirect('posts:single', username=request.user.username, slug=post.slug)
                except Exception as e:
                    break
    else: ## This part works too as it shows the correct empty form
        form = PostForm()
        formset = ImageFormset(queryset=Image.objects.none())
    context = {'form': form, 'formset': formset}
    return render(request, 'posts/post_form.html', context)

below is my forms.py

class PostForm(forms.ModelForm):
    class Meta:
        model = Post
        fields = ('title', 'message', 'post_image' )

Changed the views like user3054319 suggested see below. It works fine but saves only 1 image in the image folder. Is everything correct my indents

VIEWS.py 2nd try

@login_required
def post_create(request):
    ImageFormset = modelformset_factory(Prep, fields=('image', 'image_title', 'image_description'), extra=7)
    if request.method == 'POST':
        form = PostForm(request.POST, request.FILES)
        formset = ImageFormset(request.POST or None, request.FILES or None)
        if form.is_valid() and formset.is_valid():
            post = form.save(commit=False)
            post.user = request.user
            post.save()
            for f in formset:
                try:
                    photo = Prep(post=post, image=f.cleaned_data['image'], image_title=f.cleaned_data['image_title'],
                                 image_description=f.cleaned_data'image_description'])
                    photo.save()
                    return redirect('posts:single', username=request.user.username, slug=post.slug)
                except Exception as e:
                    break 

Then I tried removing the try and except statement and getting the redirect outside the loop It saves all 7 images but in the end gives a error (see error image attached below)

VIEWS.py 3rd try

@login_required
def post_create(request):
    ImageFormset = modelformset_factory(Prep, fields=('image', 'image_title', 'image_description'), extra=7)
    if request.method == 'POST':
        form = PostForm(request.POST, request.FILES)
        formset = ImageFormset(request.POST or None, request.FILES or None)
        if form.is_valid() and formset.is_valid():
            post = form.save(commit=False)
            post.user = request.user
            post.save()
            for f in formset:
                    photo = Prep(post=post, image=f.cleaned_data['image'], image_title=f.cleaned_data['image_title'], image_description=f.cleaned_data['image_description'])                                 
                    photo.save()
                return redirect('posts:single', username=request.user.username, slug=post.slug)

error image below If this can be achieved by CBV I can add a video of me dancing like I won a lottery. but I won't get too greedy even a solution to this can save some hair on my head Error I get on 3rd try

Upvotes: 0

Views: 337

Answers (2)

Samir Tendulkar
Samir Tendulkar

Reputation: 1191

Below are the correct Views.py thanks to user3054319

def post_create(request):
    ImageFormSet = modelformset_factory(Images, fields=('image','image_title', 'image_description'), extra=7)
    if request.method == "POST":
        form = PostCreateForm(request.POST or None)
        formset = ImageFormSet(request.POST or None, request.FILES or None)
        if form.is_valid() and formset.is_valid():
            instance = form.save(commit=False)
            instance.author = request.user
            instance.save()
            print(formset.cleaned_data)
            for f in formset.cleaned_data:
                try:
                    photo = Images(post=instance, image=f['image'], image_title=f['image_title'], image_description=f['image_description'])
                    photo.save()
                except Exception as e:
                    break
            return redirect('posts:single', username=instance.user.username, slug=instance.slug)
    else:
        form = PostCreateForm()
        formset = ImageFormSet(queryset=Images.objects.none())
    context = {
        'form': form,
        'formset': formset,
    }
    return render(request, 'blog/post_create.html', context)

Upvotes: 0

user3054319
user3054319

Reputation: 85

I went through your post create view and found that you are trying to access multiple keys of a dictionary with one call which is f.cleaned_data[‘image’, ‘image_title’] which is syntactically wrong

If you print(f.cleaned_data) it will give dictionary and you should know how to access dictionary.

You must use

photo = Image(post=post, image=f.cleaned_data['image'], image_title=f.cleaned_data['image_title'])

Upvotes: 1

Related Questions