Django: Referencing the pk in a multi form view - django

I have a view with two forms. I am trying to reference the uploaded image's pk in the same form. How do i do that?
form1 = ImageForm(request.FILES, request.POST)
form2= SongForm(request.POST or None)
if form2.is_valid() and form1.is_valid():
image = form1.save(commit=False)
image.save()
save_file(request.FILES['image'])
song = form2.save(commit=False)
song.image = the uploaded image's pk???
song.save()
Thanks,

Once you call image.save() image should get a pk, and therefore, you should be able to reference it with image.pk.

Related

For loop on form not functing properly

I have a feature that allows users to upload multiple images to their blog but it is not working correctly. When a user uploads multiple images only one of them is uploaded to the postgres db.
view
def DetailPostView(request, pk):
model = Post
post = Post.objects.get(pk=pk)
if request.method == 'POST':
test = PostImagesForm(request.POST, request.FILES)
files = request.FILES.getlist('images')
if test.is_valid():
for f in files:
instance = test.save(commit=False)
instance.post = Post.objects.get(pk=pk)
instance.save()
else:
print(instance.errors)
postgallery = PostImages.objects.filter(post_id=post)
context = {
'post':post, 'PostImagesForm':PostImagesForm, 'postgallery':postgallery
}
return render(request, 'blog/post_detail.html', context)
form
class PostImagesForm(ModelForm):
class Meta:
model = PostImages
fields = ('images',)
widgets = {
'images': forms.ClearableFileInput(attrs={'multiple': True}),
}
you can see i am getting the list of files via the files = request.FILES.getlist('images') then running a for loop on the contents.
If I break the code in the stack trace I can see that the two files are in the list so i am very confused on why it is not properly iterating though the list and uploading each file to the db.
Update
Took a look into the docs and found a section on multi image upload and the docs are doing it the same way I am. Still very confused.
I believe the issue was the because I was not passing the current image into the model so it only uploaded the first image.
Solution
if request.method == 'POST':
for f in request.FILES.getlist('images'):
test = PostImagesForm(request.POST, request.FILES)
if test.is_valid():
instance = test.save(commit=False)
instance.post = Post.objects.get(pk=pk)
instance.images = f
instance.save()

How to get image data from Django form which returns False for is_valid()

How to save image in Django form that is not validated. I could able to save data of Charfield using
title = form_name["title"].data
Other data that are passed are getting saved but image is not getting saved. How to fix it.
form = forms.FormName()
if request.method == "POST":
form_name = FormName(data = request.POST)
title = form_name["title"].data
thumbnail = form_name["thumbnail"].data
content = form_name["content"].data
tags = form_name["tags"].data
instance = htmlpage(title=title, thumbnail=thumbnail, content= content, tags=tags, by=request.user)
instance.save()

Formset populated by wrong data - Django 1.8

Basic problem: I have a list of products, and when I go to edit a single product, the image upload formset is populated with all images in the folder, but it should only be populated by related images (see left hand side of picture below).
When I try to make any changes - to the product or to the images - it is unsuccessful, and the input boxes which were populated by unrelated images now display 'this field is required' (see right hand side of picture below)
Obviously, I need to successfully edit the product object, and I want this page to be populated only by images related to that product.
The View
def EditProduct(request, pk):
instance = get_object_or_404(Product, id=pk)
ImageFormSet = modelformset_factory(ProductImage,
form=ImageForm, extra=4)
if request.method == 'POST':
product_form = AddEditProductForm(request.POST, request.FILES, instance=instance)
formset = ImageFormSet(request.POST, request.FILES,
queryset=ProductImage.objects.none())
if product_form.is_valid() and formset.is_valid():
product = product_form.save()
images = formset.save(commit=False)
for image in images:
image.product = product
image.save()
return HttpResponseRedirect('/product/')
else:
print (product_form.errors, formset.errors)
else:
product_form = AddEditProductForm(instance=instance)
formset = ImageFormSet(queryset=ProductImage.objects.all()) # possible wrong queryset
return render(request, 'product/edit.html',
{'product_form': product_form, 'formset': formset},
context_instance=RequestContext(request))
So this code is somehow returning ALL of my uploaded images - including unrelated images - to the editing form for a single product - how do I make it so only those images which are related to the instance are displayed in the form?
On a related note - how do you access an individual image in the formset - for example if i wanted to remove one, what kind of modifications am I looking at?
This depends on your model.
formset = ImageFormSet(queryset=ProductImage.objects.all()) # possible wrong queryset
This is indeed the wrong queryset. You should do something like:
queryset=ProductImage.objects.filter(product_id = pk)
if you gave the product_image field a related_name than you could do
queryset=instance.related_product_images
https://docs.djangoproject.com/en/1.8/ref/models/fields/#django.db.models.ForeignKey.related_name

Uploading images from two formsets - Django

I have a page where you can add a product, add a thumbnail, and add images for the product.
I am using to formsets, seen below. The problem is that images uploaded to the image formset are uploaded correctly, but images uploaded to the thumbnail formset are not uploading at all... what might I be doing wrong?
def AddProduct(request):
ImageFormSet = modelformset_factory(ProductImage,
form=ImageForm, extra=4)
ThumbnailFormSet = modelformset_factory(ProductvThumbnail,
form=ThumbnailForm)
if request.method == 'POST':
product_form = AddEditProductForm(request.POST)
image_formset = ImageFormSet(request.POST, request.FILES, prefix='images',
queryset=roductImage.objects.none())
thumbnail_formset = ThumbnailFormSet(request.POST, request.FILES, prefix='thumbnail',
queryset=ProductThumbnail.objects.none())
if product_form.is_valid() and image_formset.is_valid() and thumbnail_formset.is_valid():
product = product_form.save()
thumbnails = thumbnail_formset.save(commit=False)
for thumbnail in thumbnails:
thumbnail.product = product
thumbnail.save()
images = image_formset.save(commit=False)
for image in images:
image.product = product
image.save()
return HttpResponseRedirect('/product/')
else:
print (product_form.errors, image_formset.errors, thumbnail_formset.errors)
else:
product_form = AddEditProductForm()
image_formset = ImageFormSet(queryset=ProductImage.objects.none(), prefix='images')
thumbnail_formset = ThumbnailFormSet(queryset=ProductThumbnail.objects.none(), prefix='thumbnail')
return render(request, 'product/add.html',
{'product_form': product_form, 'image_formset': image_formset,
'thumbnail_formset': thumbnail_formset},
context_instance=RequestContext(request))
I have found a solution - my formsets seem to be fine, the issue was in my models.py. The ImageField in the ProductThumbnail model was called 'image = models.ImageField...' but it should have been called thumbnail - that is why no thumbnails were being uploaded - my for loop was not finding anything.

form instance of a model gives id=None Django

I'm misunderstanding something! If my model is not saved, it does not have an id associated with it. So if I have something like this:
views.py (inserting or editing existing info uses the same modelform)
def insert_or_modify(request, id=None):
if id is not None:
book = BookModel.objects.get(pk=id)
else:
book = BookModel()
if request.method == 'POST':
form = BookInfoForm(request.POST, request.FILES, instance=book)
if form.is_valid():
form.save()
....
return render_to_response(...)
I also have an image and use upload_to for the imagefield. There are two problems: id is None and I'm not sure how to manipulate/save the instance=book so that I would actually get an id. The second problem is the location I save my data to is way off. Even though the template tag book.img.url has the desired location of the book at http:127.0.0.1:8000/folder1/media/id/, the actual location is somewhere else:
Where I want to save my image to:
/project/folder1/media/id/
where id is the book id.
What I actually get:
/project/id/
(But 'id' becomes 'None' since it doesn't exist!)
My previous code worked. It would save to the correct location, but with this current code, it doesn't work. So the saving issue doesn't seem like it's due to settings.py since it worked previously.
EDIT: removed non-code from code formatting area
EDIT: I found out why I wasn't saving to the correct location. As it turned out, I forgot to uncomment something when I last modified settings.py. Saving to the location works now! Sorry guys!
EDIT: I think the id=None problem is caused by form.save(). If I avoid doing that and just save to the model directly, I don't have this problem.
Id assigns only on saving objects when you use autoincrement id field (default).
You can save item before handling image, and then save image.
May be you can not worry about image name - becouse django file storages dont have troubles with same image names. So if you just save file "image.png", and then save another file with name "image.png" - then it will be saved as "image_1.png"
def add_or_create(request, item_id=None):
item = get_object_or_404(BookModel, id=item_id) if item_id else None
form = BookInfoForm(request.POST or None, request.FILES or None, instance=book) # assume it is ModelForm
if form.is_valid():
book = form.save()
For the first part:
def insert_or_modify(request, id=None):
if id:
book = BookModel.objects.get(pk=id)
if request.method == 'POST':
form = BookInfoForm(request.POST, request.FILES, instance=book)
if form.is_valid():
save_book = form.save()
# use save_book as your instance of BookModel
....
else:
if request.method == 'POST':
form = BookInfoForm(request.POST, request.FILES)
if form.is_valid():
save_book = form.save()
# use save_book as your instance of BookModel
....
save_book = form.save() allows you to then use save_book as your saved instance of BookModel, and save_book.id is its id.
def create_id(instance,some_id=None):
if some_id is None:
obj=Post.objects.first()
new_id=obj.id
new_id+=1
return new_id
else:
return some_id
def pre_save_post_receiver(sender, instance, *args, **kwargs):
if not instance.id:
instance.id = create_id(instance)
pre_save.connect(pre_save_post_receiver, sender=Post)