Jquery File Upload plugin in django - django

I am trying to use jQuery file upload plugin to upload files
I am having a form containing text field and other inputs as well as the fileupload plugin specified file input as below
<form method="post" action="{% url 'compose' %}" id="fileupload" enctype="multipart/form-data">
{% csrf_token %}
<input type="text" name="t1"/>
<input data-bfi-disabled='' multiple='' name='files[]' type='file'>
<input type="submit">
</form>
Then in Django view I am trying to access the files uploaded with the following
attachment = request.FILES.getlist("files[]")
But on submit clicking I am getting blank filelist.
Where am I doing wrong?
I dont need ajax submission of individual files.
I need to submit all files upload along with other input contents to the view.
UPDATE:
when I checked in the UI by removing css classes of file upload button i could see "No FILE CHOSEN" but I could see list of files like below
I am confused how to use this plugin to submit my form with the selected files and other fields

Why don't you use a Form models:
class FileUploadForm(forms.Form):
file_source = forms.FileField()
Then:
<form action="/upload/" method="post" id="file-upload-form" enctype="multipart/form-data"> {% csrf_token %}
{{ form }}
<button type="submit" class="btn btn-primary" id='upload-btn'>Upload</button>
And your view:
def upload_view(request):
if request.is_ajax():
form = FileUploadForm(request.POST)
if form.is_valid():
print 'valid form'

Related

Django two forms on the same page

I have two forms on the same page.
The first form uses a 3rd party lib to upload a file to s3 and then preview what it just uploaded without changing state/ going to a different page.
The second form is going to save the url of the uploaded file to my model
However, when I submit the second form - the first form throws an error. About not having the required field (it thinks it is supposed to submit another file).
HTML
<form
id="s3form"
name="s3form"
action="{% url 'file_create' employee.uid %}"
method="post"
>
{% csrf_token %}
{{ form }}
</form>
<hr/>
<form
id="save-pic"
name="save-pic"
action="{% url 'employee_update_profile_pic' employee.uid %}"
method="post"
>
{% csrf_token %}
{# jquery inserts hidden input for image link after s3 upload #}
<input
id="save-pic-submit"
name="save-pic-submit"
type="submit"
value="Save"
>
</form>
UPDATE:
urls.py
path('employee/update/<str:uid>/profile-picture', views.file_create, name='file_create'),
path('employee/update/<str:uid>/profile-picture', views.employee_update_profile_pic, name='employee_update_profile_pic'),
views.py
def file_create(request, uid):
employee = Employee.nodes.get(uid=uid)
form = S3UploadForm(request.POST or None)
# this is not getting run... maybe because form intercepted by package?
if form.is_valid():
form.save()
messages.success(request, '''Successfully uploaded new profile pic! Lookin' good''')
return redirect("employee_detail", employee.uid)
return render(request, 'profile-picture.html', {'form': form, 'employee': employee})
def employee_update_profile_pic (request):
pdb.set_trace()
SOLVED: it was because they were sharing the same URL despite both being 'post'

Invalid form with FileField

I have an UpdateView with an object which has a FileField. If the model has a file uploaded, I show the link to the file, and also a file input in case the user wants to update it.
<form method="post" enctype="multipart/form-data">
{% if object.file %}Download{% endif %}
<input type="file" name="{{ form.file.name }}">
<input type="text" name="{{ form.other_field.name }}">
</form>
which works fine if the object is new and does not have a file, in which case the Download link does not show or if it has a file, in which case the Download link shows up.
But, if I select a file to upload, and the form is invalid, the object.file field exists, and it points to a non-existent file.
Is there a way to tell in an invalid form if the file is real?
You should use enctype
<form method="post" enctype="multipart/form-data">

How do you update a many to many field from a form?

I have the following two models:
class TaskFile(models.Model):
file = models.FileField(upload_to='task-files/')
def __str__(self):
return self.file.name
class Task(models.Model):
lesson = models.ManyToManyField(TaskFile, related_name='task_files')
I have a model form to update the Task object that is already created, but the many to many relationships do not show up in the form. It just shows the option to upload a file and does not show the existing files in that object.
How can I fix this?
Edit:
This is my model form code:
class TutorTaskSelectForm(forms.ModelForm):
lesson = forms.FileField(widget=forms.ClearableFileInput(attrs={'multiple': True}))
class Meta:
model = Task
fields = ('lesson')
This is my template:
<form action="{{request.path}}" method="POST" enctype="multipart/form-data">
{%csrf_token%}
<div class="box-body">
<div class="form-group">
<label for="inputEmail3" class="col-sm-2 control-label">Number</label>
<div class="col-sm-10">
{{form.lesson}}
</div>
</div>
</div>
</form>
First, i am not a huge fan of built-in Django Forms. So i am going to suggest you a different way. A way without Django Forms.
Out of context of this question:
There are great, i mean really great, front-end libraries like
React, Vue or Angular. And they are getting more popular every
day, or even every minute. When you decide to choose one of those
fancy libraries, using Django forms doesn't make sense so much.
Anyway, If you want to keep your existing model structure, I think the best thing you can do here is updating the logic inside of your view:
def index(request):
if request.method == 'POST':
print(request.FILES.getlist)
files = request.FILES.getlist('lesson')
# #TODO: check if form is valid or files are proper etc. here
task = Task() # new task instance here
task.save()
for f in files:
task_file = TaskFile()
task_file.file = f
task_file.save() # save uploaded file to the TaskFile
task.lesson.add(task_file) # here add that file to the many to many field of Task Model
return HttpResponse('All files saved!')
else:
ctx = {
'form': TutorTaskSelectForm()
}
return render(request, 'index.html', ctx)
I tested above code. It is working. But you must clarify what you mean by saying uploading multiple files.
Do you want to select multiple files at once? Or do you want different and separate file dialog boxes for each file?
If you want to have multiple selection while picking files from browser dialog box, then above solution should work for you.
But If you want to have multiple files by picking them separately, then you need multiple inputs in your html side. Something like this:
<form action="{{ request.path }}" method="POST" enctype="multipart/form-data">
{% csrf_token %}
<input type="file" name="lesson" required />
<input type="file" name="lesson" required />
<input type="file" name="lesson" required />
<input type="submit" value="Save"/>
</form>
Note that you don't need Django forms in this case. Just create regular input files then handle them in you view. You can reach files inside a request by calling request.FILES.getlist('lesson').
But again, i wouldn't use django forms for this case. Here is the version of not using django forms:
<form action="{{request.path}}" method="POST" enctype="multipart/form-data">
{% csrf_token %}
<div class="box-body">
<div class="form-group">
<label for="inputEmail3" class="col-sm-2 control-label">Number</label>
<div class="col-sm-10">
<input type="file" name="lesson" required multiple />
</div>
</div>
</div>
<input type="submit" value="Save" />
</form>
Put those lines in your html, and use the code above. This is very basic and simple. You can update it according to your requirements.

Django: Image Upload to the Server

I want to upload the image to the server. for that I have created a form and within my views.py file I tried to submit it into the sever. Here it does not uploads the file to "images" folder. instead of that it only update the database filed with new image name. So can anyone give me a solution.
this is views.py file
#login_required
def edit_profile(request):
if request.POST:
employee = Employee.objects.get(user=request.user)
employee.avatar=request.POST.get('image')
employee.save()
return HttpResponseRedirect('/view_profile/')
user_profile = request.user.get_profile()
return render_to_response('edit_profile.html',{'profile':user_profile },context_instance=RequestContext(request))
here my html code
{% block content %}
<form action="." method="post">
{% csrf_token %}
<input type="file" name="image"/>
<input type="submit" value="Save Changes" name="save" />
</form>
{% endblock %}
what should i change to upload image to the "images" folder
You need to add enctype="multipart/form-data" in your form element, so that files are also uploaded and available in request.FILES in the view..
So update it to
<form action="." method="post" enctype="multipart/form-data" >
....
More info at Binding uploaded files to a form
To save the image its easier to use ModelForm and set image file appropriately. But still you want to save the object directly do
...
employee.avatar = request.FILES['image']
employee.save()
Ref File Uploads

Django enctype="multipart/form-data" not setting POST data

I need to send both a file and some data from input texts.
This is the form I'm working on:
<form method="post" action="{% url catalog_create_ajax_upload %}" enctype="multipart/form-data" id="create-form">
<input type="text" id="new-catalog-name" name="catalog_name" class="large-input" placeholder="catalog title" />
<div id="new-catalog">
<input type="file" name="file">
</div>
</form>
When sent, I excpect request.POST['catalog_name']to have a value, but the whole POST attribute in an empty dictionary.
Any help?
You don't seem to have a submit button in that form. Presumably you've got one elsewhere on the page, but it would only submit the fields in its own form - move it inside that <form>...</form>.
Make sure your view function should post image file like this
def index(request):
image = 'file' in request.FILES and request.FILES['file']
Use request.FILES instead of request.POST