How to upload an image and store its link in database - django

I read some documents in Django site such as: Basic file uploads and FileField.storage. However, I still don't understand how to upload a file (or an image) to server and store its link in database. I would like to write the files to the following directory such as: 'image/%Y/%m/%d'
Please give me a sample code. Thank you so much.
My code follows as:
#models.py
class Image(models.Model):
imageid = models.AutoField()
title = models.CharField(max_length=100)
imagepath = models.ImageField(upload_to='images/%Y/%m/%d/')
#forms.py
class UploadFileForm(forms.Form):
title = forms.CharField(max_length=100)
image = forms.FileField()
#views.py
def upload_file(request):
if request.method == 'POST':
form = UploadFileForm(request.POST, request.FILES)
if form.is_valid():
# How to upload file to folder named 'images/%Y/%m/%d/'
# How to save the link above to database
return HttpResponseRedirect('/success/url/')
else:
form = UploadFileForm()
return render_to_response('upload.html', {'form': form})

I believe if you create the upload form as a model form and then just save it in the view, it will have the effect of saving the file to the filesystem and the path to the model. This is a basic example, but I think it should work.
# forms.py
class UploadFileForm(forms.ModelForm):
class Meta:
model = models.Image
# views.py
...
form = UploadFileForm(request.POST, request.FILES)
if form.is_valid():
form.save()
return HttpResponseRedirect('/success/url/')

Related

Get the real name of saved file (Model) after upload - Django

I'm trying to get the real name of the uploaded file in Django. It turns out that if a file name already exists inside the Model, the Django will create another name aleatory.
For example, if 'abc.xls' is inside the Model database and I try to upload 'abc.xls' again, Django will create a file called 'abc_123456.xls'. That's not the problem!
My question is: how can I get this name ('abc_123456.xls') inside my view.py?
def index(request):
if 'GET' == request.method:
form = DocumentForm()
return render(request, 'auditoria_app/index.html', {'form': form})
else:
form = DocumentForm(request.POST, request.FILES)
if form.is_valid():
form.save()
# I'd like to get the correct file name here!
mediaFolder = settings.MEDIA_ROOT
fileName = f"{mediaFolder}/SAE/{form.cleaned_data['file'].get_alternative_name}" # .xlsm (Excel file)
splitFileName = fileName.split('.')
zipFileName = f"{splitFileName[0]}.zip" # .zip
My model:
from django.db import models
from django.core.validators import FileExtensionValidator
class Document(models.Model):
file = models.FileField(upload_to='SAE/')
uploaded_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return str(self.file)
You can retrieve it from file with name attribute. Bu it gives you file name with joined MEDIA_ROOT. You can extract MEDIA_ROOT from that attribute. Also you can retrieve object when form.save(commit=False) Try this:
def index(request):
if 'GET' == request.method:
form = DocumentForm()
return render(request, 'auditoria_app/index.html', {'form': form})
else:
form = DocumentForm(request.POST, request.FILES)
if form.is_valid():
document = form.save(commit=False)
document.save()
# you can get file_name like this
file_name = document.file.name.split('/')[-1]

django adding multiple model image instances using form

I want to save 400 picture to my Image model using one single file field and i dont know how tp get each image from the form and create an instance on the Image model
here is my model function:
class Image(models.Model):
image = models.ImageField(null=True, blank=True)
and here is my form:
class AddImageForm(forms.ModelForm):
image = forms.FileField(widget=forms.FileInput(attrs={'class':'form-control','multiple':'true'}))
class Meta:
model = Image
fields = ['image']
and here is my view which i know is wrong just to make sure i share everything:
def imagesform(request):
form = AddImageForm()
if request.method == 'POST':
if form.is_valid():
for i in form['image']:
Image.objects.create(image=i)
context = {'form':form}
return render(request, 'members/imagesform.html', context)
Multiple file uploads can be a pain to implement, but you're almost there! From what I see, the only thing that's missing is that you should instantiate your form with the request.POST and request.FILES arguments:
def imagesform(request):
if request.method == 'POST':
form = AddImageForm(request.POST, request.FILES)
if form.is_valid():
for i in form['image']:
Image(image=i).save()
form = AddImageForm()
context = {'form':form}
return render(request, 'members/imagesform.html', context)
Also, make you sure you add the attribute enctype="multipart/form-data" to your <form> tag.

Image is not uploaded via django form

My Views
def apost(request):
if request.method =='POST':
form = APostForm(request.POST, request.FILES)
if form.is_valid():
form = form.save(commit=False)
form.slug = slugify(form.title)
form.save()
return redirect('apost')
else:
form = APostForm()
template_name = 'dadmin/form.html'
items = Post.objects.all()
context = {'title':'Add Post','form':form,'items':items}
return render (request, template_name, context)
My Form
class APostForm(forms.ModelForm):
class Meta:
model = Post
fields = {'title','photo','content'}
Models
photo = models.ImageField(upload_to='images')
No Image uploaded is Accepted Photo is selected but when Click save. It shows this field is required error. I had searched through the questions here but request.FILES solves others problems but not mines. Whats wrong?
you should use in template where you are uploading form:
<form class="form-horizontal form_middle" enctype='multipart/form-data' method="POST">
#apply logic for media upload
</form>
in views.y, the form you are saving should also have request.FILES
studentProfileForm = StudentRegisterForm(request.POST, request.FILES)
if studentProfileForm.is_valid():
user = studentProfileForm.save()
File upload is a bit weird in model forms in django.
Change your forms.py to -
class APostForm(forms.ModelForm):
photo=forms.FileField(label='Upload image') # or image field
class Meta:
model = Post
fields = {'title','content'}
form.save() will automatically save the field.

Uploading Profile Image using Django ModelForm

I've looked around at related questions, but none of the answers seem to work. I'm trying to upload a profile image for a user and have it replace (overwrite) the current image. Upon saving the image I want to change the filename to the user id. In it's current form the image will upload, but it won't replace the existing image (e.g. it'll be saved as 2_1.png).
class PhotoForm(forms.ModelForm):
def save(self):
content_type = self.cleaned_data['photo'].content_type.split('/')[-1]
filename = '%d.%s' % (self.instance.user.id, content_type)
instance = super(PhotoForm, self).save(commit=False)
instance.photo = SimpleUploadedFile(filename, self.cleaned_data['photo'].read(), content_type)
instance.save()
return instance
class Meta:
model = UserProfile
fields = ('photo',)
def photo_form(request):
if request.method == 'POST':
form = PhotoForm(data=request.POST, file=request.FILES, instance=request.user.get_profile())
if form.is_valid():
form.save()
else:
form = PhotoForm()
return render(request, 'photo_form.html', {'form': form})
def photo_form(request):
if request.method == 'POST':
form = PhotoForm(data=request.POST, file=request.FILES, instance=request.user.get_profile())
if form.is_valid():
handle_uploaded_file(request.FILES['<name of the FileField in models.py>'])
def handle_uploaded_file(f):
dest = open('/path/to/file', 'wb') # write should overwrite the file
for chunk in f.chunks():
dest.write(chunk)
dest.close()
check here: https://docs.djangoproject.com/en/dev/topics/http/file-uploads/
If that doesn't work, I suppose you could just use os.system to delete the file if the form is accepted. That probably wouldn't be that great of a solution, but it should work.

How to override FileField and automatically delete previous file in Django?

im django beginner (django 1.2.5)
I have that model:
class Document(models.Model):
file = models.FileField(upload_to='documents/%Y/%m/%d', null=True, blank=True)
title = models.CharField(max_length=30)
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
author = models.ForeignKey(User)
#other fields
#other fields
and model form to this:
class DocumentForm(ModelForm):
file = forms.FileField(required=True, error_messages={'required' : 'required!','empty': "empty!"})
title = forms.CharField(widget = forms.TextInput(attrs={'size': 93,}), error_messages={'required': 'required!'})
#other fields
#other fields
class Meta:
model = Document
exclude = ('author',)
def save(self, author, commit=True):
document=ModelForm.save(self,commit=False)
document.author = author
if commit:
document.save()
return document
I uploading new documents in using DocumentForm above and it works pretty but when i trying edit some document i cannot put new file in place previous. I may change every field except FileField.
def document_edit(request, document_id):
doc = get_object_or_404(Document, id=document_id)
form = DocumentForm(instance=doc)
if doc.author == request.user:
if request.method == "POST":
form = DocumentForm(request.POST, request.FILES, instance=doc)
if form.is_valid():
if request.POST.get('cancel'):
return HttpResponseRedirect('/')
elif request.POST.get('delete'):
document = Document.objects.get(id=document_id)
document.file.delete()
document.delete()
return HttpResponseRedirect('/')
else:
form.save(author=request.user)
return HttpResponseRedirect('/')
else:
# return again form with errors
else:
# return form with doc instance
else:
# return "you can't edit this doc!"
I research django documentation and i only know i should write some custom save method in some class but i completely have no idea how can i do this. It should be save() method in Document() or in DocumentForm()?
Generally i want this: When i put path to new file in form i want override this new file in his place and automatically delete previous file.
Can you help me? Thanks in advance!
You are on the right track, you just want to use the instance keyword, so your form reflects the object being edited. Simplified version:
def edit_upload(request, document_id):
doc = get_object_or_404(Document, id=document_id)
if request.method == 'POST': # If the form has been submitted...
form = DocumentForm(request.POST, request.FILES, instance=doc)
if form.is_valid(): # All validation rules pass
if doc.file: # If document has file already...
doc.file.delete() # delete it
form.save() # Saves object, uses new uploaded file
return redirect('/thanks/') # Redirect after success
else:
form = DocumentForm(instance=doc) # Show form to edit
return render(request, 'edit.html', {
'form': form,
})