I'm trying to take a single image using Django forms and upload it with resized version under 3 headers. I'm even able to do so with request.POST QueryDict but not with request.FILES MultiValueDict even after it shows filled data for respective field names.
My Views.py
def image_add(request,article_id):
template_name = 'blogs/image_add.html'
articles = Article.objects.get(article_id=article_id)
form = ImageAddForm
if request.method == 'POST':
image = request.FILES["image_1080"]
request.FILES['image_800'] = image
request.FILES['image_350'] = image
print(request.POST)
print(request.FILES)
form = ImageAddForm(request.POST, request.FILES)
if form.is_valid():
new_form = form.save(commit=False)
new_form.dir_id = article_id
new_form.save()
return redirect('/')
context = {'form':form,'articles':articles}
return render(request, template_name,context)
My Models.py
from smartfields import fields
from smartfields.dependencies import FileDependency
from smartfields.processors import ImageProcessor
class Images(models.Model):
dir_id = models.CharField(max_length=10,null=True)
image_1080 = fields.ImageField(upload_to=img_1080_dir_path, name="image_1080", dependencies=[
FileDependency(processor=ImageProcessor(
format='PNG', scale={'max_width': 1080, 'max_height': 1080}))
])
image_800 = fields.ImageField(upload_to=img_800_dir_path, blank=True, name="image_800", dependencies=[
FileDependency(processor=ImageProcessor(
format='PNG', scale={'max_width': 800, 'max_height': 800}))
])
image_350 = fields.ImageField(upload_to=img_350_dir_path, blank=True, name="image_350", dependencies=[
FileDependency(processor=ImageProcessor(
format='PNG', scale={'max_width': 350, 'max_height': 350}))
])
My Forms.py
class ImageAddForm(forms.ModelForm):
class Meta:
model = Images
fields = ('name','alt_text','image_1080')
widgets = {
'name': forms.TextInput(attrs={'class': 'form-control'}),
'alt_text': forms.TextInput(attrs={'class': 'form-control'}),
'image_1080': forms.ClearableFileInput(attrs={'class': 'form-file-input'})
}
This saves only one image - 'image_1080' but not the other two.
Your approach of overwriting POST parameters is more of a hack, because conceptually it means you are ignoring the data that suppose to come in from the user. So this is something I would recommend against in general:
if request.method == 'POST':
image = request.FILES["image_1080"]
request.FILES['image_800'] = image
request.FILES['image_350'] = image
I suspect this approach doesn't work because the same instance of the file is shared among many fields. Correct approach instead would be to simply use one form field as input and let smartfields attach other fields to the model for you. Also, I recommend keeping the original file uploaded, just in case if you ever need to resize and change the format again in the future:
from smartfields import utils
class Images(models.Model):
image = fields.ImageField(
upload_to=utils.UploadTo(generator=True, field_name='image'),
dependencies=[
FileDependency(suffix='1080', processor=ImageProcessor(
format='PNG', scale={'max_width': 1080, 'max_height': 1080}),
FileDependency(suffix='800', processor=ImageProcessor(
format='PNG', scale={'max_width': 800, 'max_height': 800}),
FileDependency(suffix='350', processor=ImageProcessor(
format='PNG', scale={'max_width': 350, 'max_height': 350}))
])
When uploading an image to image
field, smartfields will automatically add extra fields to you Images
model, eg:
> i = Images(my_image)
> i.save()
> print(i.image) # original
> print(i.image_1080) # resized to 1080
> print(i.image_800)