Reputation: 1191
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
Upvotes: 0
Views: 337
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
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