Hello,
I’m having an issue saving a file upload with my ModelForm.
When I click the Save button after ADDING a new instance, it does not look like the ‘doc_file’ value is being set.
models.py
class Doc(models.Model):
client = models.ForeignKey(Client, on_delete=models.CASCADE)
name = models.CharField(max_length=100, default='')
doc_file = models.FileField("File", upload_to="clients_docs", null=True, blank=True)
category = models.CharField(max_length=50, choices=DocsCategoriesClient.choices, default='')
class Meta:
verbose_name = "Doc"
verbose_name_plural = "Docs"
def __str__(self):
return str(self.name)
views.py
class DocAdd(UserAccessMixin, SuccessMessageMixin, generic.CreateView):
permission_required = 'docs.add_doc'
model = Doc
form_class = DocForm
template_name = 'clients/generic_add.html'
success_message = model._meta.verbose_name + " added successfully."
def get_context_data(self, **kwargs):
context = super(DocAdd, self).get_context_data(**kwargs)
client_id = self.kwargs['client_id']
context['c_id'] = client_id
context['client_full_name'] = get_object_or_404(Client, id=client_id)
context['obj_name'] = self.model._meta.verbose_name
return context
def form_valid(self, form):
print('in form_valid')
doc = form.save(commit=False)
client_id = form.data['hidden_client_id']
client = get_object_or_404(Client, id=client_id)
doc.client = client
file_check = str(doc.doc_file)
print('file check: ' + str(doc.doc_file))
print('name check: ' + str(doc.name))
print(self.request.POST)
if file_check == "":
form.add_error('doc_file', 'ERROR: The file was not uploaded. Please try again.')
return super(DocAdd, self).form_invalid(form)
else:
return super(DocAdd, self).form_valid(form)
def get_success_url(self):
return reverse('clients:detail', args=[self.kwargs['client_id']])
forms.py (using crispy forms)
class DocForm(ModelForm):
class Meta:
model = Doc
exclude = ['client']
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.layout = Layout(
Fieldset('',
'name',
'doc_file',
'category',
),
Hidden('hidden_client_id', '{{ c_id }}'),
ButtonHolder(
Submit('submit', 'Save'),
HTML("<a href='{{ view.get_success_url }}' class='btn btn-light'>Cancel</a>")
)
)
generic_add.html template
{% extends "base.html" %}
{% block title %}Add {{ obj_name }}{% endblock %}
{% block content %}
<div class="row">
<div class="col-sm-12 col-lg-6">
<h2>New {{ obj_name }} for {{ client_full_name }}</h2>
{% load crispy_forms_tags %}
<form action="" method="POST">
{% csrf_token %}
{% crispy form %}
</form>
</div>
</div>
{% endblock content %}
When I fill out the form for a new Doc, and click the Save button, this is the output in my console:
[17/Mar/2022 09:35:10] "GET /clients/2/doc/add HTTP/1.1" 200 5315
in form_valid
file check:
name check: test
<QueryDict: {'csrfmiddlewaretoken': ['I_removed_for_clarity'], 'name': ['test'], 'doc_file': ['cute-dog.jpg'], 'category': ['Planning'], 'hidden_client_id': ['2'], 'submit': ['Save']}>
[17/Mar/2022 09:35:16] "POST /clients/2/doc/add HTTP/1.1" 200 5499
The page is returned to the same “add” page, and I receive the error message I created in the views.py file of: “ERROR: The file was not uploaded. Please try again.”
This means the line in views.py is not returning a doc_file value:
file_check = str(doc.doc_file)
Can you please help troubleshoot what I do not have right in my code?
Thank you in advance!