Django form FileField error 'This Field is required' - django

I am receiving a This field is required error using a form view that django is generating.
I have a Scan model that looks like:
class Scan(models.Model):
device = models.ForeignKey(Device, null=True, on_delete=models.SET_NULL)
created_at = models.DateTimeField('Created', auto_now=True)
data = models.FileField(upload_to='uploads/')
def __str__(self):
return str("{}-{}".format(self.device, self.created_at))
I have a CreateView defined:
class ScanCreate(LoginRequiredMixin, CreateView):
model = Scan
fields = '__all__'
My url route is
urlpatterns = [
...
path('scan/create/', views.ScanCreate.as_view(), name='scan-create'),
...
]
and finally a scan_form.html template
{% block content %}
<form action="" method="post">
{% csrf_token %}
<table>
{{ form.as_table }}
</table>
<input type="submit" value="Submit">
</form>
{% endblock %}
On picking a file to upload and submitting the form, I get the 'This field is required.' error and the request fails:
The file has been selected for upload so why would django report field is required?

The main problem in you code is that you are not using enctype="multipart/form-data" in your form, so when the request is sent to the server, it does not have the file in the request.FILES collection.
you have to write the html code for your form like this:
{% block content %}
<form action="" method="post" enctype="multipart/form-data">
{% csrf_token %}
<table>
{{ form.as_table }}
</table>
<input type="submit" value="Submit">
</form>
{% endblock %}
and ensure that the action is pointing to the correct URL.
finally, this is the documentation for file uploads: https://docs.djangoproject.com/en/dev/topics/http/file-uploads/

Related

how to use a media file in a django view, in other words, how do i get the address of the media file in a view

I have Included the following in my settings.py:
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
This is the model whose FileInput i have to store:
class Clip(models.Model):
owner = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=False)
audio = models.FileField(upload_to='audio/')
class Meta:
db_table = 'Audio_store'
My modelForm:
class AudioForm(forms.ModelForm):
class Meta:
model = Clip
fields = ['audio']
And finally the view where i need the address of this file:
form = AudioForm(request.POST, request.FILES or None)
try:
instance = Clip.objects.get(owner=request.user)
instance.delete()
except Clip.DoesNotExist:
instance = 0
if form.is_valid():
instance = form.save()
else:
return HttpResponse("Failed")
result = function_name("""destination of the audio file in media directory""")
Now as you can see to get the value of result, i need to feed the address of the file to the function. Now i am confused what should i put in the function.
i have a media directory in which i have created a subdirectory 'audio'. But i can't figure out how do i put in the exact address with the file name to this function. (This is the only way i can use this function)
Please help me out here
Edit:
This is how i am taking user input:
<form method="POST" action="{% url 'application:audio' %}">
{% csrf_token %}
{{ form | crispy }}
<br>
{% if form.errors %}
{% for field in form %}
{% for error in field.errors %}
<div class="alert alert-danger">
<strong>{{ error|escape }}</strong>
</div>
{% endfor %}
{% endfor %}
{% for error in form.non_field_errors %}
<div class="alert alert-danger">
<strong>{{ error|escape }}</strong>
</div>
{% endfor %}
{% endif %}
<br>
<input type="submit" class="btn btn-primary mt-3 mb-3 btn-register" value="Upload and Connect!!" />
</form>
The form.errors display nothing, but the form is never validated. I am uploading an mp3 file via the form
Thank You
You can obtain the path of the audio of the instance with the .path attribute [Django-doc]:
instance.audio.path
if you want the media URL, you can use the .url attribute [Django-doc]:
instance.audio.url
You probably should first check if the instance is not 0, since in that case, you do not work with a Clip model.
In your form, you should specify the enctype="…" HTML attribute [dev-mozilla] in the <form> tag:
<form method="POST" action="{% url 'application:audio' %}" enctype="multipart/form-data">
…
</form>

how to process submit on django-tables2 with a class View with FilterView mixin

I have a django-tables2 FilterView.
The filter is templated in a form:
{% if filter %}
<form action="" method="get" class="form form-inline">
{% bootstrap_form filter.form layout='inline' %}
{% bootstrap_button 'filter' %}
</form>
{% endif %}
I have added a checkbox field to each row, and I have the table in a form:
<form action="table_selection" method="get" class="form form-inline">
{% csrf_token %}
{% render_table table 'django_tables2/bootstrap.html' %}
<button class="btn btn-primary red" type="submit" >Submit Rows</button>
</form>
When I submit, I get logging messages like:
GET /three_pl/threepl_fulfilments_filter/table_selection?csrfmiddlewaretoken=...
&select_row=198&select_row=158&select_row=159
so the select_rows are very interesting.
But I am lost with the class view, I can't grapple with how to process the form submission.
This is my view:
class FilteredThreePLFulfimentsView(SingleTableMixin,FilterView):
table_class = ThreePL_order_fulfilmentsTable
model = ThreePL_order_fulfilments
template_name = "three_pl/ThreePLFulfilmentsFilter.html" #three_pl/templates/three_pl/ThreePLFulfilmentsFilter.html
filterset_class = ThreePLFulfilmentsFilter
Answer: set up a url watching for /table_selection.
Make it before the url for the table render.
... url(r'^threepl_fulfilments_filter/table_selection',views.three_pl_fulfilments_selection,name='threepl_fulfilments_selection'),
...
and in the view:
if request.method == 'GET':
try:
selected_rows = request.GET.getlist('select_row')

Uploading multiple images in Django with django-multiupload library

I'm trying to use the below library to implement multi upload in my Django proejct.
https://github.com/Chive/django-multiupload
boutique/models.py
class Photo(models.Model):
store = models.ForeignKey(Store)
photo = models.FileField(null=True, blank=True, upload_to='boutique/index/%Y/%m/%d')
url = models.CharField(max_length=40, null=True, blank=True, verbose_name='Image URL')
created_at = models.DateTimeField(auto_now_add=True)
def __unicode__(self):
return str(self.photo)
def get_absolute_url(self):
return reverse('cms:photo_edit', args=[self.pk])
cms/forms.py
from django import forms
from boutique.models import Photo
from multiupload.fields import MultiFileField
class PhotoCreateForm(forms.ModelForm):
class Meta:
model = Photo
fields = ['store']
attachments = MultiFileField(min_num=1, max_num=3, max_file_size=1024*1024*5)
cms/views.py
class PhotoCreateView(FormView):
model=Photo
template_name='cms/photo_new.html'
form_class = PhotoCreateForm
success_url=reverse_lazy('cms:photo')
queryset = Photo.objects.all()
def form_valid(self, form):
for each in form.cleaned_data['attachments']:
Attachment.objects.create(file=each)
return super(PhotoCreateView, self).form_valid(form)
cms/photo_new.html
{% extends 'cms/base.html' %}
{% load staticfiles %}
{% block page-header %}Add Photo{% endblock %}
{% block content %}
<form action="" method="post">
{% csrf_token %}
<table class="table table-hover store-form">
{{ form.as_table }}
</table>
<input class="btn btn-success btn-block" type="submit" name="" value="Submit">
<br>
</form>
{% endblock %}
FYI, I'm not using Django default admin, but my own customized admin, which is the app named cms. I'm also using models in the app named boutique.
When I upload photos, nothing happens and the page doesn't even move to the success url. After submitting the files, the file input field just says "Thie field is required", and I don't see any uploads on the database.
Is there something wrong on my codes?
Your Model name is Photo, then why you try to save photos at Attachment Model!
cms/views.py
class PhotoCreateView(FormView):
model=Photo
template_name='cms/photo_new.html'
form_class = PhotoCreateForm
success_url=reverse_lazy('cms:photo')
queryset = Photo.objects.all()
def form_valid(self, form):
for each in form.cleaned_data['attachments']:
Photo.objects.create(photo=each)
return super(PhotoCreateView, self).form_valid(form)
If you want to upload any file or image then you need to add enctype="multipart/form-data" to your HTML form.
cms/photo_new.html
{% extends 'cms/base.html' %}
{% load staticfiles %}
{% block page-header %}Add Photo{% endblock %}
{% block content %}
<form action="" method="post" enctype="multipart/form-data">
{% csrf_token %}
<table class="table table-hover store-form">
{{ form.as_table }}
</table>
<input class="btn btn-success btn-block" type="submit" name="" value="Submit">
<br>
</form>
{% endblock %}
Update this two file. hopefully, it'll work. If not then let me know.

Django form field doesn't appear on the template

I try to use Django forms but I have problems displaying all the fields on my Template.
I have created a form in the form.py file as:
class UploadCSVForm(forms.Form):
title = forms.CharField(max_length=255, help_text="Please type here", required=True)
csv_load = forms.FileField()
In my corresponding view I import the form as:
from myproject.myapp.forms import UploadCSVForm
and then in the specific view function I render the form as;
if request.method == 'GET':
....
....
form = UploadCSVForm()
ctx['form'] = form
return render_to_response(template, RequestContext(request, ctx))
Last in my template I call the form as:
<form id="file-uploader" method="post" enctype="multipart/form-data" action="{% url "layer" %}">
<input type="hidden" name="csrfmiddlewaretoken" value="{{ csrf_token }}">
{% for field in form.visible_fields %}
{{ field.errors }}
{{ field.help_text }}
{{ field }}
{% endfor %}
<button type="submit" id="upload-button" class="btn btn-danger">Upload</button>
</form>
I only get to see the csv_load but not the title.
What am I doing wrong here?

Why aren't labels appearing in my Django ModelForm?

I have a very simple ModelForm in my app that looks like this:
# ModelForm
class ProductForm(ModelForm):
class Meta:
model = MyModel
exclude = ['created', 'last_modified', 'serial_number']
# Model
class BaseModel(models.Model):
created = models.DateTimeField(auto_now_add=True, blank=True, null=True)
last_modified = models.DateTimeField(auto_now=True, blank=True, null=True)
class MyModel(BaseModel):
product = models.TextField(verbose_name='Product Name')
serial_number = models.TextField(verbose_name='Serial Number')
And a form that looks like this:
# Form
<form method="POST" action="{% url some_url %}">
{% csrf_token %}
{{ formset.management_form }}
{% for form in formset %}
{% for field in form %}
{% if field.errors %}
<div>{{ field.errors }}</div>
{% endif %}
<div>
{{ field.label_tag }}:
{{ field }}
</div>
{% endfor %}
{% endfor %}
<div class="actions">
<input class="button submit focus" type="submit" value="{% trans "Save" %}" />
</div>
</form>
When I check out the view using this, I just see a colon (:) followed by the textfield: The label is gone.
According to the documentation for ModelForm:
In addition, each generated form field has attributes set as follows:
...
The form field’s label is set to the verbose_name of the model field, with the first character capitalized.
What mistake have I made?
I am using Django 1.4.1 if it matters.
You have to put the field label inside a <label> tag. So:
<div>
<label for="id_{{field.html_name}}">{{field.label}}:</label>
{{ field }}
</div>
The only solution I managed to find that still allowed me to separate each row of the form was doing the following:
<form method="POST" action="{% url some_url %}">
{% csrf_token %}
{{ formset.as_ul }}
<div class="actions">
<input class="button submit focus" type="submit" value="{% trans "Save" %}" />
</div>
</form>
... the key piece being the {{ formset.as_ul }} instead of iterating through each field.
As for why the other listed solution (or the solution in the documentation) didn't work, I will remain baffled.