when i am saving the modelform with blank image field, then it shows error, And this error is due to the custom form validation of image field in the modelform. And also the if statement is not working in custom form validation method.
" 'unicode' object has no attribute '_size' ".
models.py
class ImageUpload(models.Model):
image = models.ImageField(upload_to='uploads')
name = models.CharField(max_length='128')
class Meta:
db_table = 'image_upload'
formy.py
class ImageUploadForm(forms.ModelForm):
class Meta:
model = ImageUpload
def clean_image(self):
image = self.cleaned_data.get('image',None)
if image: # this is not working, if image field is blank
if image._size:
if image:
if image._size > 1*1024*1024:
raise ValidationError("Image file too large ( > 4mb )")
return image
else:
raise ValidationError("Couldn't read uploaded image")
else:
raise ValidationError("image format should be .png %s"%(image_format))
views.py
def add_image(request):
response_data = {}
if request.method == 'POST':
form = ImageUploadForm(request.POST,request.FILES)
context = {
'form':form
}
if form.is_valid():
form.save()
response_data['status'] = 'true'
response_data['message'] = 'successfully added'
return HttpResponse(json.dumps(response_data),content_type='application/javascript')
else:
response_data['message'] = form.errors
#return HttpResponse(response_data)
return HttpResponse(json.dumps(response_data),content_type='application/javascript')
else:
form = ImageUploadForm()
context = {
'form':form
}
return render(request,'users/add_image.html',context)
The error is on the form
image = self.cleaned_data.get('image',None)
you should get the image like
if 'image' in request.FILES:
image = request.FILES['image']
Related
I have the following clean method by which I reduce an image if it is too large:
class CompanyForm(forms.ModelForm):
class Meta:
model = Company
exclude = ('limited')
def clean_image(self):
image_field = self.cleaned_data.get('image')
if image_field:
reduced_image = reduce_image(image_field, 550)
return reduced_image
else:
raise forms.ValidationError('You must upload a square logo image')
return image_field
My reduce image looks like the following:
def reduce_image(image_field, height_max):
if image_field:
try:
image_file2 = BytesIO(image_field.read())
image = Image.open(image_file2).convert('RGB')
print(image)
except:
#raise ValidationError('There was a problem with the image, please try another.')
print('returning from image errror')
return image_field
w, h = image.size
print('image width:'+str(w))
print('image height:'+str(h))
if h > height_max:
print('height toolarge')
ratio = h/float(w)
new_height = ratio * height_max
image = image.resize((int(height_max), int(new_height)), Image.ANTIALIAS)
image_file = BytesIO()
image.save(image_file, 'JPEG', quality=90)
image_field.file = image_file
print(image_file)
return image_field
The first time I save, it saves no problem. When I save a second time to update the model, it removes the image.
Why might this be happening?
In the post method of your update view pass the following arguments to your form
get_object it's a custom method that I use to return the concerned object
If you're using CBV
def post(self, request, *args, **kwargs):
self.form_class(request.POST, request.FILES, instance=self.get_object())
....
For function based views
if request.method == 'POST':
form = CompanyForm(request.POST, request.FILES, instance=get_object())
if form.is_valid():
....
class ProductImageForm(forms.ModelForm):
class Meta:
model = ProductImage
fields = ['product', 'original', 'caption']
# use ImageInput widget to create HTML displaying the
# actual uploaded image and providing the upload dialog
# when clicking on the actual image.
widgets = {
'original': ImageInput(),
}
def save(self, *args, **kwargs):
# We infer the display order of the image based on the order of the
# image fields within the formset.
kwargs['commit'] = False
obj = super(ProductImageForm, self).save(*args, **kwargs)
obj.display_order = self.get_display_order()
obj.save()
return obj
def get_display_order(self):
if self.prefix:
return self.prefix.split('-').pop()
else:
return 1
I am using django modelformset_factory to insert images into database and also update the images.The problem now is that image is inserted into database instead of updation while using modelformset_factory.Following below are the my code.Please help me to update other than saving
ImageFormSet = modelformset_factory(ProductImage,
form=ProductImageForm, extra=0, can_delete=True)
formset = ImageFormSet(self.request.POST or None, self.request.FILES or None, data)
if formset.is_valid():
try:
instances = formset.save(commit=False)
for instance in instances:
instance.save()
except Exception as e:
pass
else:
err = formset.errors
raise error_message(err)
I am trying to save an instance of a model but to no avail.
Below is my model;
class AudioFile(models.Model):
name = models.CharField(max_length=100,default='')
audio_file = models.FileField()
uploader = models.ForeignKey(User,default='')
def __unicode__(self):
return self.name
I have the below form;
class AudioFileForm(forms.ModelForm):
class Meta:
model = AudioFile
fields = ['name', 'audio_file']
def clean_audio_file(self):
audio = self.cleaned_data['audio_file']
if audio:
if audio._size > 5*1024*1024:
raise ValidationError("File too large ( > 5mb )")
if os.path.splitext(audio.name)[1] != ".mp3":
raise ValidationError("We only support mp3!")
return audio
else:
raise validationError("Couldn't read uploaded file")
And I have the below view to handle the submitted form;
form = AudioFileForm(request.POST, request.FILES)
if form.is_valid():
form.cleaned_data['uploader'] = request.user //view requires login
form.save()
return HttpResponseRedirect(
reverse('home_audio',kwargs={'pk':audio_file.pk})
)
else:
return HttpResponse(form.errors)
But on submission I get the error; IntegrityError at /uploadaudio
NOT NULL constraint failed: stationrunner_audiofile.uploader_id /uploadaudio is the URL correspoding to the view and stationrunner is my app's name.
Someone please help out.
Try changing the view:
form = AudioFileForm(request.POST, request.FILES)
if form.is_valid():
audio_file = form.save(commit=False) // This will not hit the database, and no IntegrityError will be raised
audio_file.uploader = request.user // Tack on the user,
audio_file.save()
return HttpResponseRedirect(
reverse_lazy('home_audio',kwargs={'pk':audio_file.pk}) // Use reverse lazy to prevent circular import issues.
)
else:
return HttpResponse(form.errors)
Also you could fix some issues with the model:
from django.conf import settings
from django.db import models
class AudioFile(models.Model):
name = models.CharField(max_length=100) // If the field is not allowed to be blank, the default blank does not make sense.
audio_file = models.FileField(upload_to="audio_files") // Without this parameter file field does not work.
uploader = models.ForeignKey(settings.AUTH_USER_MODEL) // This should reference the user model declared in your settings file.
def __unicode__(self):
return self.name
I have a ModelForm containing a field: image = models.ImageField:
class InstanceForm(ModelForm):
class Meta:
model = Instance
exclude = ('created_at','author',)
And my view is:
def add_instance(request):
if request.user.is_authenticated():
if request.POST:
form=InstanceForm(request.POST,request.FILES)
if form.is_valid():
new_instance=form.save(commit=False)
new_instance.author=request.user.username
new_instance.save()
locals().update(csrf(request))
return render_to_response(...)
else:
return render_to_response(...)
else:
form=InstanceForm()
return render_to_response(...)
else: return HttpResponse(...)
When my form is not valid it shows not only errors, but field 'image' without path to image. It's working in this way, even if I have chosen image at first using Browse.
I use a custom function to upload a file splitting it in chunks, as documented here.
My problem is that calling save() after handle_uploaded_file() uploads my file twice, one into "MEDIA_URL/my_path" dir and one into "MEDIA_URL".
But I would like to have only one upload, the one with chunks.
It is possible to force save() to make 'chunked' upload?
Or should I use different approaches?
Thank you.
models.py
class ShapeFile(models.Model):
name = models.CharField(max_length=100)
srid = models.ForeignKey(SpatialRefSys)
user = models.ForeignKey(User)
color_table = models.ForeignKey(ColorTable)
file = models.FileField(upload_to="my_path")
class Meta:
unique_together = ('name', 'user')
forms.py
class UploadForm(ModelForm):
class Meta:
model = ShapeFile
fields = ('name','user','srid','file','color_table')
widgets = {'srid': TextInput(),
'user': HiddenInput()
views.py
def handle_uploaded_file(fileName, filePath):
with open(filePath, 'wb+') as destination:
for chunk in fileName.chunks():
destination.write(chunk)
#login_required
def shapeIng(request):
if request.method == 'POST':
form = UploadForm(request.POST, request.FILES)
if form.is_valid():
req = request.POST
# Split uploaded file into chunks
fileName = request.FILES['file']
filePath = ShapeFile(file=fileName).file.path
handle_uploaded_file(fileName, filePath)
form.save()
messages.success(request, 'Shapefile upload succesful!')
return redirect('shapeCreated')
else:
messages.error(request, 'Something went wrong uploading Shapefile.')
else: # request.method == 'GET'
form = UploadForm(initial={'user': request.user})
return render_to_response('my_app/base_shapeIngestion.html',
{'form': form},
context_instance=RequestContext(request))
change your view function to this:
def testupload2(request):
if request.method == 'POST':
file_name=request.FILES['file']
form = SomeForm(request.POST, request.FILES)
if form.is_valid():
dest_file = open('C:/prototype/upload/'+ str(file_name), 'wb+')
path = 'C:/prototype/upload/'+ str(file_name)
for chunk in request.FILES['file'].chunks():
dest_file.write(chunk)
dest_file.close()
t = get_template("testupload2.html")
lst = os.listdir('C:/downloads/prototype/prototype/upload/')
html = t.render(Context({'MEDIA_URL':'http://127.0.0.1:8000/site_media/'}))
return HttpResponse(html)