I have a ModelForm for a model that has a couple of files and with every file, a type description (what kind of file it is). This description field on the model has CHOICES. I have set these file uploads and description uploads as hidden fields on my form, and not required. Now the file upload is working, but the description is giving field errors, the placeholder in the dropdown is not a valid choice, it says. That's true, but since it is not required, I would like it to just be left out of the validation and I am stuck on how.
My codes, shortened them up a bit to keep it concise.
models.py
class Dog(models.Model):
FILE_TYPE_CHOICES = [
('SB', 'Stamboom'),
('RB', 'Registratiebewijs'),
('SJP', 'SJP-diploma'),
('CDD', 'CDD-diploma'),
('WT', 'Workingtestdiploma'),
('MISC', 'Overig'),
]
dog_id = models.UUIDField(unique=True, default=uuid.uuid4)
file_1 = models.FileField(upload_to=user_directory_path, blank=True, validators=[extension_validator])
desc_1 = models.CharField(choices=FILE_TYPE_CHOICES, blank=True, max_length=5)
forms.py (I excluded all these fields from the model-code above to keep it more clear, but this is to demonstrate that these fields are not required. If I print the required attribute of 'desc_1' in the view, it also says false
class DogForm(ModelForm):
class Meta:
model = Dog
fields = ('stamboomnummer', 'stamboomnaam', 'date_of_birth', 'breed',
'sex', 'sire', 'dam', 'microchip', 'breeder', 'owner',
'file_1', 'desc_1')
required = ('stamboomnummer', 'stamboomnaam', 'date_of_birth', 'breed',
'sex', 'sire', 'dam', 'microchip', 'breeder', 'owner')
widgets = {'file_1': forms.HiddenInput(),
'desc_1': forms.HiddenInput(),
}
views.py
#login_required
def newdog(request):
file_opties = Dog.FILE_TYPE_CHOICES
if request.method == 'POST':
form = DogForm(request.POST, request.FILES)
if form.is_valid():
dog = form.save(commit=False)
if request.FILES.get('file_1'):
dog.file_1 = request.FILES['file_1']
dog.user = request.user
dog.save()
assign_perm('accounts.view_dog', request.user, dog)
assign_perm('accounts.change_dog', request.user, dog)
assign_perm('accounts.delete_dog', request.user, dog)
return redirect('accounts:profile')
else:
form = DogForm()
return render(request, 'accounts/add_dog.html', {'form': form,
'buttontitle': 'Opslaan',
'formtitle': 'Hond toevoegen',
'file_type': file_opties})
My form template:
{% extends 'base.html' %}
{% load crispy_forms_tags %}
{% block title %}Title{% endblock %}
{% block content %}
<h2>{{ formtitle }}</h2>
<form id='hond' method="post" enctype="multipart/form-data">
{% csrf_token %}
{% for field in form.visible_fields %}
<div class="mb-3">
{{ field.errors }}
{{ field.label }}{% if field.field.required %}*{% endif %} <br>{{ field }}
</div>
{% endfor %}
{% if form.instance.file_1 %}
{{ form.instance.get_desc_1_display }}<br>
{% endif %}
<div class="input-group mb-3">
<input class="form-control" type="file" name="file_1" id="id_file_1">
<select class="form-select" name="desc_1" id="id_desc_1">
<option selected>Type bestand</option>
{% for item in file_type %}
<option value={{ item.0 }}>{{ item.1 }}</option>
{% endfor %}
</select>
</div>
<button class="btn btn-primary" type="submit">{{ buttontitle }}</button>
</form>
<button class="btn btn-primary" style="margin-top:20px" onclick="history.back()">Annuleren</button>
{% endblock %}
This is my form HTML, with the file input and description input right on the bottom
<form id="hond" method="post" enctype="multipart/form-data">
<input type="hidden" name="csrfmiddlewaretoken" value="gxmQEruF9vTKQshK1M4YnRRg4r0X1SkzEJwbAOwQcbq1mmGvBRSC89DwmZfT6Sv7">
<div class="mb-3">
Stamboomnummer* <br><input type="text" name="stamboomnummer" class="form-control textInput" maxlength="20" required="" id="id_stamboomnummer">
</div>
<div class="mb-3">
Stamboomnaam* <br><input type="text" name="stamboomnaam" class="form-control textInput" maxlength="60" required="" id="id_stamboomnaam">
</div>
<div class="mb-3">
Geboortedatum* <br><input type="text" name="date_of_birth" class="form-control" required="" id="id_date_of_birth">
</div>
<div class="mb-3">
Ras* <br><select name="breed" class="form-select" id="id_breed">
<option value="FR" selected="">Flatcoated Retriever</option>
<option value="CBR">Chesapeake Bay Retriever</option>
<option value="CCR">Curly Coated Retriever</option>
<option value="GR">Golden Retriever</option>
<option value="LR">Labrador Retriever</option>
<option value="NSDTR">Nova Scotia Duck Tolling Retriever</option>
<option value="MISC">Ander ras, geen retriever</option>
</select>
</div>
<div class="mb-3">
Geslacht* <br><select name="sex" class="form-select" required="" id="id_sex">
<option value="" selected="">---------</option>
<option value="REU">Reu</option>
<option value="TEEF">Teef</option>
</select>
</div>
<div class="mb-3">
Vader* <br><input type="text" name="sire" class="form-control textInput" maxlength="60" required="" id="id_sire">
</div>
<div class="mb-3">
Moeder* <br><input type="text" name="dam" class="form-control textInput" maxlength="60" required="" id="id_dam">
</div>
<div class="mb-3">
Chipnummer* <br><input type="text" name="microchip" class="form-control textInput" maxlength="30" required="" id="id_microchip">
</div>
<div class="mb-3">
Fokker* <br><input type="text" name="breeder" class="form-control textInput" maxlength="50" required="" id="id_breeder">
</div>
<div class="mb-3">
Eigenaar* <br><input type="text" name="owner" class="form-control textInput" maxlength="50" required="" id="id_owner">
</div>
<div class="input-group mb-3">
<input class="form-control" type="file" name="file_1" id="id_file_1">
<select class="form-select" name="desc_1" id="id_desc_1">
<option selected="">Type bestand</option>
<option value="SB">Stamboom</option>
<option value="RB">Registratiebewijs</option>
<option value="SJP">SJP-diploma</option>
<option value="CDD">CDD-diploma</option>
<option value="WT">Workingtestdiploma</option>
<option value="MISC">Overig</option>
</select>
</div>
<button class="btn btn-primary" type="submit">Opslaan</button>
</form>
Now, form.is_valid() is False, and the form errors are:
desc_1: Selecteer een geldige keuze. Type bestand is geen beschikbare keuze.
Which means something like: Select a valid option, Type bestand (which is the placeholder text in my form) is not a valid option.
I have tried to override the clean-function but the field is not in the cleaned_data (which is logical I guess, since it's not a valid option) and I do not know how to get in before. I think I might have to define a custom field, but I cannot seem to find how to do that on a modelform with a hidden input :/ Any help would be greatly appreciated :)
Your form is submitting desc_1, so there's a an input with name="desc_1" that has a populated value of Type bestand somewhere in your template. blank=True means the value can be left empty. Since your field has choices and blank=True, the submitted value can be either empty or one of the FILE_TYPE_CHOICES.
You're saying that Type bestand is the placeholder for this field, but if you rendered this field as a hidden input ({{ form.desc_1 }} since you have a widget overridden) it would not and should not have a placeholder.
A regular form equivalent would be:
<input type="hidden" name="desc_1" value="">
Where the value attribute is either left empty or populated with one of the existing options, nothing else.
I will also add that if you're displaying desc_1 field as a <select> element, the placeholder option's value also has to be empty.
Edit
You have an option element that is selected by default. Add the disabled attribute to stop the form from submitting the placeholder text as a value for desc_1:
<option value="" selected disabled>Type bestand</option>
View.py
if req.method == 'POST':
df = DocumentForm.objects.filter(document_id=id)
logging.info('LOG: I am here')
if df.exists():
for d in df:
description = req.POST['{}'.format(d.description, False)]
displayName = req.POST['{}'.format(d.displayName, False)]
df.update(displayName=displayName, description=description)
return redirect('/adboard/upd')
HTML File
<form class="needs-validation" action="{{id}}" method="POST" enctype="multipart/form-data" novalidate>
{% csrf_token %}
<div class="row mt-3 mb-3"></div>
{% if messages %}
<div class="alert alert-danger" role="alert">
{% for message in messages %}
{{ message }}
{% endfor %}
</div>
{% endif %}
{% for df in data %}
<div class="form-group">
<small class="text-muted bold-label m-lower">{{{df.field}}}</small>
<label for="validationCustom01">{{df.displayName}}</label>
<input type="text" class="form-control" id="validationCustom01" name="{{df.displayName}}" value="{{df.displayName}}" placeholder="Enter Display Name">
<label for="validationCustom01">{{df.description}}</label>
<input type="text" class="form-control" id="validationCustom01" name="{{df.description}}" value="{{df.description}}" placeholder="Enter description">
<div class="invalid-feedback">
Please enter required fileds.
</div>
<!-- <div class="valid-feedback">
Looks good!
</div> -->
</div>
{% endfor %}
<button type="submit" class="btn btn-primary btn-red btn-block">SAVE</button>
</form>
What I am trying to achieve is.
Pass a variable form to the user to fill
And I get the result.
I can't tell what the input id/name would be because it's a variable.
But I am finding it difficult getting the value from the view.py file.
change
req.POST['{}'.format(d.description, False)]
to
req.POST.get('{}'.format(d.description, False))
Dear all of the Django developer community, I am facing this below issue:
I try to update a db table data which has one field and one drop down field. But I only get basic field data and not drop down list data.
I request expert help me. How can I fix this issue?
Advanced Thanks For All
views.py
def update_brands(request, id):
brand = Brand.objects.get(id=id)
form = AddBrandForms(request.POST, instance=brand)
if form.is_valid():
form.save()
return redirect('/parts/brands')
return render(request, 'parts/edit_brands.html', {'brand': brand })
edit_brands.html
{% extends 'parts/base.html' %}
{% block content %}
<form method="post" action="/parts/update_brands/{{brand.id}}/" class="post-form">
{% csrf_token %}
<div class="form-group row">
<label class="col-sm-2 col-form-label">Country Name:</label>
<div class="col-sm-4">
<input type="text" name="country" value="{{ brand.brand_name }}"/>
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 col-form-label">Country Name:</label>
<div class="col-sm-4">
<select id="cars" name="cars">
{% for db in dbf.all %}
<option value="{{ db.db}}">{{ db.db}}</option>
{% endfor %}
</select>
</div>
</div>
<button type="submit" class="btn btn-success">Submit</button>
</form>
{% endblock %}
try this
{% extends 'parts/base.html' %}
{% block content %}
<form method="post" action="/parts/update_brands/{{brand.id}}/" class="post-form">
{% csrf_token %}
<div class="form-group row">
<label class="col-sm-2 col-form-label">Country Name:</label>
<div class="col-sm-4">
<input type="text" name="country" value="{{ brand.brand_name }}"/>
</div>
</div>
<div class="form-group row">
<label class="col-sm-2 col-form-label">Country Name:</label>
<div class="col-sm-4">
<select id="cars" name="cars">
{% for car in brand.all %}
<option value="{{ car }}">{{ car }}</option>
{% endfor %}
</select>
</div>
</div>
<button type="submit" class="btn btn-success">Submit</button>
</form>
{% endblock %}
applyonline.html(I have given file fields for adhaarcopy and idcopy)
<body ng-app="">
{% extends "pmmvyapp/base.html" %}
{% load crispy_forms_tags %}
{% load static %}
{% block content%}
<div class="col-md-8">
<form method="post" action="/personal_detail/">
{% csrf_token %}
<div class="form-group">
<div class=" mb-4">
<h6><u>(*Mandatory Fields)Please Fill up the details below </u></h6>
</div>
<legend class="border-bottom mb-4" ,align="center">1.Beneficiary Details</legend>
<label for="formGropuNameInput">Does Beneficiary have an Adhaar Card?*</label>
<input type="radio" name="showHideExample" ng-model="showHideTest" value="true">Yes
<input type="radio" name="showHideExample" ng-model="showHideTest" value="false">No
<!--logic for yes-->
<div ng-if="showHideTest=='true'">
<div class="form-group">
<label for="formGropuNameInput">Name of Beneficiary(as in Aadhar Card)*</label>
<input name="beneficiary_adhaar_name" class="form-control" id="formGroupNameInput" placeholder="Enter name of Beneficiary as in Aadhar Card" required>
</div>
<div class="custom-file">
<input type="file" class="custom-file-input" id="customFile" name="adhaaarcopy">
<label class="custom-file-label" for="customFile">Choose file</label>
</div>
</div>
<!--logic for no-->
<div ng-if="showHideTest=='false'">
<div class="form-group">
<div class="form-group">
<label for="adhaar_eid">Aadhaar Enrollment ID(EID):</label>
<input name="adhaar_eid" id="identityno" class="form-control" required>
</div>
<div class="form-group">
<label for="formGropuNameInput">Name of Beneficiary(as in Identity Card)* </label>
<input name="beneficiary_id_name" class="form-control" id="formGroupNameInput" placeholder="Enter your name" required>
</div>
<div class="form-group">
<label for="idno">Identity Number(Enclose Copy of Identity Card)*:</label>
<input name="idno" id="identityno" class="form-control" required>
</div>
<div class="custom-file">
<input type="file" class="custom-file-input" name="idcopy" id="customFile">
<label class="custom-file-label" for="customFile">Choose file</label>
</div>
</div>
</div>
<button type="submit" class="btn btn-primary" style="margin-bottom:10px ">Submit</button>
</form>
</div>
{% endblock %}
</body>
this is my views.py i've used POST.get
#login_required
def personal_detail(request):
# ShowHideExample = request.POST.get('showHideExample',False)
beneficiary_adhaar_name=request.POST.get('beneficiary_adhaar_name')
adhaarno=request.POST.get('adhaarno')
adhaarcopy=request.POST.get('adhaarcopy')
idcard=request.POST.get('idcard')
adhaar_eid=request.POST.get('adhaar_eid')
beneficiary_id_name=request.POST.get('beneficiary_id_name')
idno=request.POST.get('idno')
idcopy=request.POST.get('idcopy')
apply_online = Personal_Detail(beneficiary_adhaar_name=beneficiary_adhaar_name,adhaarno=adhaarno,adhaarcopy=adhaarcopy,
idcard=idcard,adhaar_eid=adhaar_eid,beneficiary_id_name=beneficiary_id_name,idno=idno,idcopy=idcopy)
apply_online.save()
return render(request,'users/applyonline.html')
this is my models.py where i have created FileField for both
class Personal_Detail(models.Model):
beneficiary_adhaar_name=models.TextField(blank=True, null=True)
adhaarno=models.IntegerField(blank=True, null=True)
adhaarcopy = models.FileField(upload_to='adhaar/')
idcard=models.TextField(blank=True, null=True)
adhaar_eid=models.IntegerField(blank=True,null=True)
beneficiary_id_name=models.TextField(blank=True, null=True)
idno=models.IntegerField(blank=True, null=True)
idcopy=models.FileField(upload_to='identitycard/')
def __str__(self):
return self.beneficiary_adhaar_name or self.beneficiary_id_name
settings.py I have given the media root and provided the media url
STATIC_URL = '/static/'
MEDIA_ROOT = os.path.join(BASE_DIR,'media')
MEDIA_URL ='/media/'
CRISPY_TEMPLATE_PACK='bootstrap4'
Like I want to know how can I upload the images like what should be my next steps.
You should get the file after submitted the form as below...
idcopy = request.FILES['idcopy']
adhaaarcopy = request.FILES['adhaaarcopy']
insted of...
idcopy=request.POST.get('idcopy')
adhaaarcopy=request.POST.get('adhaaarcopy')
And so on for other fields...
After that you can save and get it in appropriate location in media.
For some reason I can't get the list of Countries in django-countries-plus to render in my template.
The table is imported fine under Countries Plus > Countries and I've set the models.py up as follows:
from countries_plus.models import Country
class Project(models.Model):
title = models.CharField(max_length=500)
status = models.BooleanField(default=True)
location = models.CharField(max_length=500)
projectcountry = models.ForeignKey(Country)
Then added the new field projectcountry to the form on forms.py:
from django.forms import ModelForm
from .models import Project, Proposal
class ProjectForm(ModelForm):
class Meta:
model = Project
fields = ['title', 'status', 'location', 'projectcountry']
Then in the template I'm trying to bring in the 252 countries in the table to render in a Bootstrap dropdown:
<form class="form-horizontal" method="POST" enctype="multipart/form-data">
{% csrf_token %}
<div class="form-group">
<label class="col-sm-2 control-label">PROJECT TITLE</label>
<div class="col-sm-6">
<textarea rows="1" class="form-control" name="title"></textarea>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">STATUS</label>
<div class="col-sm-6">
<select name="status" class="form-control">
<option value="1">Active</option>
<option value="0">Disabled</option>
</select>
</div>
<div class="col-sm-4">
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">CITY / TOWN</label>
<div class="col-sm-6">
<textarea rows="1" class="form-control" name="location"></textarea>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">COUNTRY</label>
<div class="col-sm-6">
<select name="projectcountry" class="form-control">
{% for country in countries %}
<option value="{{ country.iso }}">{{ country.name }}</option>
{% endfor %}
</select>
</div>
<div class="col-sm-4">
</div>
</div>
</form>
Can you see what I'm doing wrong? I've been struggling with this researching all day but not cracked it.