new to Django and Python here, building my first project.
I´m making a form for registering new user and I´m controlling my fields in a forms.py file
class UserRegisterForm(forms.ModelForm):
password1 = forms.CharField(
label='Contraseña',
required=True,
widget=forms.PasswordInput(
attrs={
# 'placeholder': 'Contraseña',
'class': 'input-group-field',
'oninvalid': "this.setCustomValidity('Ingrese una contraseña')",
'oninput': "setCustomValidity('')"
}
)
)
password2 = forms.CharField(
label='Contraseña',
required=True,
widget=forms.PasswordInput(
attrs={
# 'placeholder': 'Repetir Contraseña',
'class': 'input-group-field',
'oninvalid': "this.setCustomValidity('Repita la contraseña')",
'oninput': "setCustomValidity('')"
}
)
)
class Meta:
"""Meta definition for Userform."""
model = User
fields = (
'user_name',
'full_name',
'phone',
'email',
'role',
'gender',
'date_birth',
)
widgets = {
'user_name': forms.TextInput(
attrs={
# 'placeholder': 'Usuario ...',
'class': 'input-group-field',
'max_length': '20',
'oninvalid': "this.setCustomValidity('Ingrese un nombre de usuario')",
'oninput': "setCustomValidity('')"
}
),
'full_name': forms.TextInput(
attrs={
# 'placeholder': 'Nombres ...',
'class': 'input-group-field',
'max_length': '100',
'oninvalid': "this.setCustomValidity('Ingrese su nombre completo')",
'oninput': "setCustomValidity('')"
}
),
'phone': forms.TextInput(
attrs={
# 'placeholder': 'Teléfono ...',
'class': 'input-group-field',
'max_length': '50',
'oninvalid': "this.setCustomValidity('Ingrese su teléfono')",
'oninput': "setCustomValidity('')"
}
),
'email': forms.EmailInput(
attrs={
# 'placeholder': 'Correo Electronico ...',
'class': 'input-group-field',
'max_length': '100',
'blank': True,
'oninvalid': "this.setCustomValidity('Ingrese un mail válido')",
'oninput': "setCustomValidity('')"
}
),
'role': forms.Select(
attrs={
# 'placeholder': 'Rol ...',
'class': 'input-group-field',
'required': True,
}
),
'gender': forms.Select(
attrs={
# 'placeholder': 'Género ...',
'class': 'input-group-field',
}
),
'date_birth': forms.DateInput(
format='%Y-%m-%d',
attrs={
'type': 'date',
'class': 'input-group-field',
},
),
}
def clean_password2(self):
if self.cleaned_data['password1'] != self.cleaned_data['password2']:
self.add_error('password2', 'Las contraseñas no son iguales')
Everything is working fine showing this kind of "error messages" in my html
So I have a method for clean password2, to check is the same as password 1 (Password confirmation), and I want the error message, to be the same format as the other fields.
Is this possible?
Thanks for your help!
I also attach here my template
{% extends "panel.html" %}
{% load static %}
{% block panel-content %}
<div class="grid-x medium-10">
<h3 class="cell medium-12" style="text-align: center;color: wheat;">Nuevo Usuario</h3>
<div class="cell medium-12">  </div>
<div class="cell medium-12 grid-x">
<div class="cell medium-2"></div>
<form class="cell medium-8 grid-x" method="POST">{% csrf_token %}
<div class="cell medium-4">
<label>Usuario:</label>
<div class="input-group">
<span class="input-group-label"><i class="fi-torso"></i></span>
{{ form.user_name }}
</div>
</div>
<div class="cell medium-9"></div>
<div class="cell medium-4">
<label>Nombre:</label>
<div class="input-group">
<span class="input-group-label"><i class="fi-book"></i></span>
{{form.full_name}}
</div>
</div>
<div class="cell medium-1"></div>
<div class="cell medium-3">
<label>Género:</label>
<div class="input-group">
<span class="input-group-label"><i class="fi-male-female"></i></span>
{{form.gender}}
</div>
</div>
<div class="cell medium-1"></div>
<div class="cell medium-3">
<label>Fecha de Nacimiento:</label>
<div class="input-group">
<span class="input-group-label"><i class="fi-calendar"></i></span>
{{ form.date_birth }}
</div>
</div>
<div class="cell medium-4">
<label>Email:</label>
<div class="input-group">
<span class="input-group-label"><i class="fi-mail"></i></span>
{{form.email}}
</div>
</div>
<div class="cell medium-1"></div>
<div class="cell medium-3">
<label>Teléfono:</label>
<div class="input-group">
<span class="input-group-label"><i class="fi-telephone"></i></span>
{{form.phone}}
</div>
</div>
<div class="cell medium-4"></div>
<div class="cell medium-4">
<label>Rol:</label>
<div class="input-group">
<span class="input-group-label"><i class="fi-star"></i></span>
{{form.role}}
</div>
</div>
<div class="cell medium-8"></div>
<div class="cell medium-4">
<label>Contraseña:</label>
<div class="input-group">
<span class="input-group-label"><i class="fi-key"></i></span>
{{ form.password1 }}
</div>
</div>
<div class="cell medium-1"></div>
<div class="cell medium-4">
<label>Repetir Contraseña:</label>
<div class="input-group">
<span class="input-group-label"><i class="fi-key"></i></span>
{{ form.password2 }}
</div>
</div>
<!-- {% for error in form.password2.errors %}
<p class="cell" style="color: red;">
{{ error|escape }}
</p>
{% endfor %} -->
<div class="cell medium-3"></div>
<div class="cell medium-2">
<button type="submit" class="cell success button "> <i class="fi-save"></i>  Guardar</button>
</div>
</form>
<div class="cell medium-2"></div>
</div>
</div>
{% endblock panel-content %}
I think you might be interested in this answer : https://stackoverflow.com/a/54020111/8439435
Basically you would need to write a custom javascript function to check that both password match each other and use setCustomValidity to show a browser error message on validation of the form if passwords are different.
Related
I am trying to create a form where you can enter the language or languages. I want to use a CheckboxSelectMultiple widget, but it renders already collapsed in the form:
The form with already collapsed select
How can I fix this?
forms.py:
class TweetForm(forms.ModelForm):
class Meta:
model = TweetSearch
fields = ['search_term', 'query_type', 'start_date', 'end_date', 'language', 'country', 'tweet_count']
widgets = {
'search_term': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Search...'}),
'query_type': forms.Select(attrs={'class': 'form-control'}),
'tweet_count': forms.NumberInput(attrs={'class': 'form-control', 'placeholder': 'Number of tweets'}),
'start_date': DateTimePickerInput(attrs={'class': 'form-control', 'placeholder': 'From'}),
'end_date': DateTimePickerInput(attrs={'class': 'form-control', 'placeholder': 'Till'}),
'language': forms.CheckboxSelectMultiple(attrs={'class':'form-control'})
}
html:
<div id="searchcontainer">
<div class="card w-50 text-center mx-auto mt-8" id="searchcard">
<div class="card-header">
Search
</div>
<div class="card-body">
<h5 class="card-title">Search for tweets</h5>
<form action="" method="POST">
{% csrf_token %}
<div class="form-row">
<div class="form-group col-md-4">
{{form.search_term}}
</div>
<div class="form-group col-md-4">
{{form.query_type}}
</div>
<div class="form-group col-md-4">
{{form.tweet_count}}
</div>
</div>
<div class="form-row">
<div class="form-group col-md-6">
{{form.start_date}}
</div>
<div class="form-group col-md-6">
{{form.end_date}}
</div>
</div>
<div class="form-row">
{{form.language}}
</div>
<input class="btn btn-primary mb-2" type="submit">
</form>
</div>
</div>
I got the a problem, widgets in forms.py cannot render in template.
I want to create edit form in my application and i try used widgets in forms.py, but the widgets cannot render in template.
Any solutions ?
Form in html render like this, (class, placeholder, etc not rendering) :
IMAGE FORM EDIT
forms.py
class UserUsulanUpdatePenelitianForm(ModelForm):
class Meta:
model = UserUsulan
exclude = ['status_usulan' ,'jumlah_dana_disetujui', 'keterangan_operator', 'com_reviewer_1', 'com_reviewer_2' ]
widget = {
'anggota' : Select2MultipleWidget({'class' : 'form-control select2-multi', 'multiple' : 'multiple', 'name' : 'tags' }),
'tmt_awal' : forms.TextInput({'class' : 'form-control', 'placeholder' : 'TMT Awal', 'type' : 'date'}),
'tmt_akhir' : forms.TextInput({'class' : 'form-control', 'placeholder' : 'TMT Akhir', 'type' : 'date'}),
'judul_penelitian' : forms.Textarea({'class' : 'form-control', 'placeholder' : 'Judul Penelitian', 'rows':3, 'cols':20}),
}
views.py
class UserUsulanPenelitianUpdateView(LoginRequiredMixin, UpdateView):
template_name = 'dashboard/usulan-penelitian-edit.html'
form_class = UserUsulanUpdatePenelitianForm
queryset = UserUsulan.objects.all()
context_object_name = 'listUsulanPenelitian'
def form_valid(self, form):
messages.success(self.request, 'Usulan Penelitian Telah Diedit!')
return super().form_valid(form)
def get_success_url(self):
return reverse('dashboard:usulan-penelitian')
usulan-penelitian-edit.html
<form method="post">
{% csrf_token%}
{{form.errors}}
<div class="inputbox mt-3"> {{form.ketua}} <span>Ketua Penelitian</span> </div>
<div class="row">
<div class="col-md-6">
<div class="inputbox mt-3 mr-2"> {{form.anggota}} <i class="fa fa-users"></i> <span>Anggota</span> </div>
</div>
<div class="col-md-6">
<div class="d-flex flex-row">
<div class="inputbox mt-3 mr-2"> {{form.tmt_awal}} <span>TMT Awal</span> </div>
<div class="inputbox mt-3 mr-2"> {{form.tmt_akhir}} <span>TMT Akhir</span> </div>
</div>
</div>
</div>
<div class="mt-4 mb-4">
<h6 class="text-uppercase">Detail Penelitian</h6>
<div class="row mt-3">
<div class="inputbox mt-3"> {{form.judul_penelitian}} <span>Judul Penelitian</span> </div>
<div class="col-md-4">
<div class="inputbox mt-3 mr-2"> {{form.tahun}} <span>Tahun</span> </div>
</div>
<div class="col-md-4">
<div class="inputbox mt-3 mr-2"> {{form.jenis_penelitian}} <span>Jenis</span> </div>
</div>
<div class="col-md-4">
<div class="inputbox mt-3 mr-2"> {{form.bidang_penelitian}} <span>Bidang</span> </div>
</div>
</div>
<div class="row mt-2">
<div class="col-md-6">
<div class="inputbox mt-3 mr-2"> {{form.skema_penelitian}} <span>Skema</span> </div>
</div>
<div class="col-md-6">
<div class="inputbox mt-3 mr-2"> {{form.target_luaran}} <span>Target</span> </div>
</div>
</div>
<div class="row mt-2">
<div class="col-md-12">
<div class="inputbox mt-3 mr-2"> {{form.tujuan_sosial_ekonomi}} <span>Tujuan Sosial Ekonomi</span> </div>
</div>
</div>
</div>
<div class="mt-4 mb-4">
<h6 class="text-uppercase">Dana Penelitian</h6>
<div class="row mt-3">
<div class="col-md-6">
<div class="inputbox mt-3 mr-2"> {{form.jumlah_dana_usulan}} <span>Dana Usulan</span> </div>
</div>
</div>
</div>
<input type="submit" name="simpan" id="simpan" class="btn btn-primary btn-user btn-block" value="Simpan"/>
</form>
the widgets cannot render because typo in write code widget. The Correct code is widgets not widget
before
widget = {
'anggota' : Select2MultipleWidget({'class' : 'form-control select2-multi', 'multiple' : 'multiple', 'name' : 'tags' }),
'tmt_awal' : forms.TextInput({'class' : 'form-control', 'placeholder' : 'TMT Awal', 'type' : 'date'}),
'tmt_akhir' : forms.TextInput({'class' : 'form-control', 'placeholder' : 'TMT Akhir', 'type' : 'date'}),
'judul_penelitian' : forms.Textarea({'class' : 'form-control', 'placeholder' : 'Judul Penelitian', 'rows':3, 'cols':20}),
}
after
widgets = {
'anggota' : Select2MultipleWidget({'class' : 'form-control select2-multi', 'multiple' : 'multiple', 'name' : 'tags' }),
'tmt_awal' : forms.TextInput({'class' : 'form-control', 'placeholder' : 'TMT Awal', 'type' : 'date'}),
'tmt_akhir' : forms.TextInput({'class' : 'form-control', 'placeholder' : 'TMT Akhir', 'type' : 'date'}),
'judul_penelitian' : forms.Textarea({'class' : 'form-control', 'placeholder' : 'Judul Penelitian', 'rows':3, 'cols':20}),
}
I have a number of Boolean Field checkbox inputs within a form and I have noticed the following Boolean Fields (avaialble, bfbw, asp and tours) are printing a default value of 'False' whilst the remainder of the Boolean Fields (para_athlete, working_with_children) do not.
When the value of False is there I cannot toggle the checkbox between on/off (True/False)
Is there something obvious that I am missing as I am struggling to see any difference between the fields?
Thanks in advance for any help I can get on this.
Below is the code.
Model
athlete_ref = models.CharField(max_length=10, default=1)
athlete_name = models.CharField(max_length=80)
email = models.EmailField()
phone_number = models.CharField(max_length=120)
home = models.CharField(max_length=120)
education = models.CharField(max_length=120)
sport = models.CharField(max_length=120, choices=sports, default='Shooting')
notes = models.TextField()
gender = models.CharField(max_length=120, choices=genders, default='Not Specified')
para_athlete = models.BooleanField(blank=True)
working_with_children = models.BooleanField(blank=True)
expiry_date = models.DateField(blank=True, null=True)
available = models.BooleanField(blank=True)
available_from = models.DateField(blank=True, null=True)
bfbw = models.BooleanField(blank=True)
latest_bfbw_session = models.DateField(blank=True, null=True)
number_bfbw_sessions = models.CharField(blank=True, null=True, max_length=10)
asp = models.BooleanField(blank=True)
latest_asp_session = models.DateField(blank=True, null=True)
number_asp_sessions = models.CharField(blank=True, null=True, max_length=10)
tours = models.BooleanField(blank=True)
latest_tours_session = models.DateField(blank=True, null=True)
number_tours_sessions = models.CharField(blank=True, null=True, max_length=10)
Form
class EditAthleteForm(forms.ModelForm):
class Meta():
model = Athlete
fields = ('__all__')
widgets = {
'athlete_ref': TextInput(attrs={'id':'athlete_ref', 'name': 'athlete_ref', 'hidden': 'hidden'}),
'athlete_name': TextInput(attrs={'class': 'form-control', 'id': 'edit_athlete_name', 'name': 'edit_athlete_name', 'placeholder': 'John Doe'}),
'email': TextInput(attrs={'class': 'form-control', 'id': 'edit_athlete_email', 'name': 'edit_athlete_email', 'placeholder': 'name#example.com'}),
'phone_number': TextInput(attrs={'class': 'form-control', 'id': 'edit_athlete_phone_number', 'name': 'edit_athlete_phone_number', 'placeholder': '0400 000 000', 'pattern': '^((\+61\s?)?(\((0|02|03|04|07|08)\))?)?\s?\d{1,4}\s?\d{1,4}\s?\d{0,4}$'}),
'home': TextInput(attrs={'class': 'form-control', 'id': 'edit_athlete_home', 'name': 'edit_athlete_home', 'placeholder': 'Home Address'}),
'education': TextInput(attrs={'class': 'form-control', 'id': 'edit_athlete_education', 'name': 'edit_athlete_education', 'placeholder': 'Education'}),
'sport': Select(attrs={'class': 'form-select', 'id': 'edit_athlete_sports', 'name': 'edit_athlete_sports'}),
'notes': Textarea(attrs={'class': 'form-control', 'id': 'edit_athlete_notes', 'name': 'edit_athlete_notes'}),
'gender': Select(attrs={'class': 'form-select', 'id': 'edit_athlete_gender', 'name': 'edit_athlete_gender'}),
'para_athlete': CheckboxInput(attrs={'class': 'form-check-input', 'id': 'edit_athlete_para_athlete', 'name': 'edit_athlete_para_athlete'}),
'working_with_children': CheckboxInput(attrs={'class': 'form-check-input', 'id': 'edit_athlete_wwc_input', 'name': 'edit_athlete_wwc_input'}),
'expiry_date': DateInput(attrs={'type': 'date','class': 'form-control', 'id': 'edit_athlete_expiry_datepicker', 'name': 'edit_athlete_expiry_datepicker'}),
'available': CheckboxInput(attrs={'class': 'form-check-input', 'id': 'edit_athlete_available_input', 'name': 'edit_athlete_available_input'}),
'available_from': DateInput(attrs={'type': 'date','class': 'form-control', 'id': 'edit_athlete_datepicker', 'name': 'edit_athlete_datepicker'}),
'bfbw': CheckboxInput(attrs={'class': 'form-check-input', 'id': 'edit_athlete_bfbw_input', 'name': 'edit_athlete_bfbw_input'}),
'latest_bfbw_session': DateInput(attrs={'type': 'date','class': 'form-control', 'id': 'edit_athlete_bfbw_datepicker', 'name': 'edit_athlete_bfbw_datepicker'}),
'number_bfbw_sessions': TextInput(attrs={'class': 'form-control', 'id': 'edit_athlete_bfbw_number_input', 'name': 'edit_athlete_bfbw_number_input'}),
'asp': CheckboxInput(attrs={'class': 'form-check-input', 'id': 'edit_athlete_asp_input', 'name': 'edit_athlete_asp_input'}),
'latest_asp_session': DateInput(attrs={'type': 'date','class': 'form-control', 'id': 'edit_athlete_asp_datepicker', 'name': 'edit_athlete_asp_datepicker'}),
'number_asp_sessions': TextInput(attrs={'class': 'form-control', 'id': 'edit_athlete_asp_number_input', 'name': 'edit_athlete_asp_number_input'}),
'tours': CheckboxInput(attrs={'class': 'form-check-input', 'id': 'edit_athlete_tour_input', 'name': 'edit_athlete_tour_input'}),
'latest_tours_session': DateInput(attrs={'type': 'date','class': 'form-control', 'id': 'edit_athlete_tour_datepicker', 'name': 'edit_athlete_tour_datepicker'}),
'number_tours_sessions': TextInput(attrs={'class': 'form-control', 'id': 'edit_athlete_tour_number_input', 'name': 'edit_athlete_tour_number_input'}),
View
def update_athlete(request):
if request.method == 'POST':
athlete_ref_id = request.POST.get('athlete_ref')
ath_data = Athlete.objects.get(id=athlete_ref_id)
ath_data.athlete_name = request.POST['athlete_name']
ath_data.email = request.POST['email']
ath_data.home = request.POST['home']
ath_data.education = request.POST['education']
ath_data.sport = request.POST['sport']
ath_data.notes = request.POST['notes']
ath_data.gender = request.POST['gender']
ath_data.para_athlete = request.POST.get('para_athlete') == 'on'
ath_data.working_with_children = request.POST.get('working_with_children') == 'on'
ath_data.expiry_date = request.POST.get('expiry_date')
ath_data.available = request.POST.get('available') == 'on'
ath_data.available_from = request.POST.get('available_from')
ath_data.bfbw = request.POST.get('bfbw') == 'on'
ath_data.latest_bfbw_session = request.POST.get('latest_bfbw_session')
ath_data.number_bfbw_sessions = request.POST.get('number_bfbw_sessions')
ath_data.asp = request.POST.get('asp') == 'on'
ath_data.latest_asp_session = request.POST.get('latest_asp_session')
ath_data.number_asp_sessions = request.POST.get('number_asp_sessions')
ath_data.tours = request.POST.get('tours') == 'on'
ath_data.latest_tours_session = request.POST.get('latest_tours_session')
ath_data.number_tours_sessions = request.POST.get('number_tours_sessions')
ath_data.save()
print(ath_data.available)
return HttpResponseRedirect(request.META.get('HTTP_REFERER'))
HTML
<!-- EDIT Athlete Modal -->
<form method="post" action="update_athlete/" id="edit_athlete_form">
{% csrf_token %}
{{ form.non_field_errors }}
{{ form.source.errors }}
{{ form.source }}
<div class="modal fade" id="edit_athlete_modal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered modal-dialog-scrollable">
<div class="modal-content">
<div class="modal-header card-header">
<h5 class="modal-title"><i class="fa fa-pencil mx-1"></i> Edit Athlete Details</h5>
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="card text-dark bg-light mb-3">
<div class="card-body">
<div class="form-floating mb-3">
{{edit_ath_form.athlete_name}}
<label for="edit_name">Name & Last Name</label>
</div>
<div class="form-floating mb-3">
{{edit_ath_form.email}}
<label for="edit_email">Email address</label>
</div>
<div class="form-floating mb-3">
{{edit_ath_form.phone_number}}
<label for="edit_athlete_phone_number">Phone number</label>
</div>
<div class="form-floating mb-3">
{{edit_ath_form.home}}
<label for="edit_home">Home</label>
</div>
<div class="form-floating mb-3">
{{edit_ath_form.education}}
<label for="edit_education">Education</label>
</div>
<div class="form-floating mb-3">
{{edit_ath_form.sport}}
<label for="edit_sports">Sports</label>
</div>
<div class="form-floating mb-3">
{{edit_ath_form.notes}}
<label for="edit_notes">Notes</label>
</div>
<div class="form-floating mb-3">
{{edit_ath_form.gender}}
<label for="edit_gender">Gender</label>
</div>
<div class="form-check form-switch">
{{edit_ath_form.para_athlete}}
<label class="form-check-label" for="edit_athlete_para_athlete">Para athlete</label>
</div>
</div>
</div>
<div class="card text-dark bg-light mb-3">
<div class="card-body">
<div class="form-check form-switch">
{{edit_ath_form.working_with_children}}
<label class="form-check-label" for="edit_athlete_wwc_input">Has WWC</label>
</div>
<div class="form-floating mb-3">
{{edit_ath_form.expiry_date}}
<label for="edit_athlete_expiry_datepicker">Expires on</label>
</div>
<div class="form-check form-switch">
{{edit_ath_form.available}}
<label class="form-check-label" for="edit_athlete_available_input">Available</label>
</div>
<div class="form-floating mb-3">
{{edit_ath_form.available_from}}
<label for="edit_athlete_datepicker">Available from</label>
</div>
<div class="form-check form-switch">
{{edit_ath_form.bfbw}}
<label class="form-check-label" for="edit_athlete_bfbw_input">BFBW</label>
</div>
<div class="row">
<div class="col-6">
<div class="form-floating mb-3">
{{edit_ath_form.latest_bfbw_session}}
<label for="edit_athlete_bfbw_datepicker">Latest BFBW Session</label>
</div>
</div>
<div class="col-6">
<div class="form-floating mb-3">
{{edit_ath_form.number_bfbw_sessions}}
<label for="edit_athlete_bfbw_number_input">Number of BFBW Sessions</label>
</div>
</div>
</div>
<div class="form-check form-switch">
{{edit_ath_form.asp}}
<label class="form-check-label" for="edit_athlete_asp_input">ASP</label>
</div>
<div class="row">
<div class="col-6">
<div class="form-floating mb-3">
{{edit_ath_form.latest_asp_session}}
<label for="edit_athlete_asp_datepicker">Latest ASP Session</label>
</div>
</div>
<div class="col-6">
<div class="form-floating mb-3">
{{edit_ath_form.number_asp_sessions}}
<label for="edit_athlete_asp_number_input">Number of ASP Sessions</label>
</div>
</div>
</div>
<div class="form-check form-switch">
{{edit_ath_form.tours}}
<label class="form-check-label" for="edit_athlete_tour_input">VIS Tours</label>
</div>
<div class="row">
<div class="col-6">
<div class="form-floating">
{{edit_ath_form.latest_tours_session}}
<label for="edit_athlete_tour_datepicker">Latest VIS Tour</label>
</div>
</div>
<div class="col-6">
<div class="form-floating mb-3">
{{edit_ath_form.number_tours_sessions}}
<label for="edit_athlete_tour_number_input">Number of Tours</label>
</div>
</div>
</div>
</div>
</div>
</div>
{{edit_ath_form.athlete_ref}}
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="submit" class="btn btn-primary" name="save_edit_athlete">Save Changes</button>
</div>
</div>
</div>
</div>
</form>
<!-- END EDIT Athlete Modal -->
Fixed - Was a issue with JavaScript adding the false value.
I'm using Django FilterSet to enable the user to filter a list of products on my website. Everything is working perfectly, I'm using standard html code to display a form. However there is a RadioSelect field that is not rendering correclty and I don't understand why. I provide you below the relevant parts of my code as well as a screenshot of the rendering problem. Does anyone know how I can solve that ?
filters.py
class PlatFilter(django_filters.FilterSet):
titre = django_filters.CharFilter(
field_name='titre', label='Mot clé :', lookup_expr='icontains',
widget=forms.TextInput(attrs={'class': 'form-control'}),
)
prix_min = django_filters.NumberFilter(
field_name='prix', label='Prix minimum :', lookup_expr='gte',
widget=forms.NumberInput(attrs={'class': 'form-control'}),
)
prix_max = django_filters.NumberFilter(
field_name='prix', label='Prix maximum :', lookup_expr='lte',
widget=forms.NumberInput(attrs={'class': 'form-control'}),
)
nb_portions = django_filters.NumberFilter(
field_name='nb_portions', label='Nombre de portions minimum :', lookup_expr='gte',
widget=forms.NumberInput(attrs={'class': 'form-control'}),
)
date_prep = django_filters.DateFilter(
field_name='date_prep__date', label='Date de préparation (format JJ/MM/AAAA)', lookup_expr='exact',
widget=forms.DateTimeInput(attrs={'class': 'form-control'}),
)
CHOICES = ((True, 'Oui'), (False, 'Non'))
is_delivering = django_filters.BooleanFilter(
field_name='chef__is_delivering', label='Livraison comprise',
widget=forms.RadioSelect(attrs={'class': 'form-control'}, choices=CHOICES),
)
class Meta:
model = Plat
fields = ['titre', 'nb_portions', 'date_prep']
html file (using Bootstrap)
<div class="col-md-3">
<div class="filters shadow-sm rounded bg-white mb-4">
<div class="filters-header border-bottom pl-4 pr-4 pt-3 pb-3">
<h5 class="m-0" style="font-size: 200%">Filtrer par</h5>
</div>
<div class="filters-body">
<form method="get">
<div class="well">
<div class="row">
<div class="col-md-12 pl-5 pb-4 pt-4 pr-5">
{% csrf_token %}
{% for field in filter.form %}
<div class="fieldWrapper form-group" style="font-size: 150%">
{{ field.label_tag }}
{{ field }}
</div>
{% endfor %}
<button type="submit" class="btn btn-primary">
<span class="glyphicon glyphicon-search"></span> Rechercher
</button>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
Screenshot of the problem :
I'm developing the backend of my personal blog and, using this tutorial for the date and time, I've created a form for the creation of a blog post.
Even if I select one or more tags, they aren't added to the post. The post after the pubblication using this form doesen't have tags. But if I do the same thing via django admin I can't create a post without the tags.
create_post.html
<form class="" method="POST" enctype="multipart/form-data" novalidate>{% csrf_token %}
<div class="form-group">
<div class="row">
<div class="col-sm-9">
<div class="form-group mb-4">
<div>{{ form.title }}</div>
<label for="id_title">
<span class="text-info" data-toggle="tooltip" title="{{ form.title.help_text }}">
<i class="far fa-question-circle"></i>
</span>
<small class="text-danger">{{ form.title.errors }}</small>
</label>
</div>
<div class="form-group mb-4">
<div>{{ form.description }}</div>
<label for="id_description">
<span class="text-info" data-toggle="tooltip" data-placement="bottom" title="{{ form.description.help_text }}">
<i class="far fa-question-circle"></i>
</span>
<small class="text-danger">{{ form.description.errors }}</small>
</label>
</div>
<div class="form-group mb-4">
<div>{{ form.contents }}</div>
<label for="id_contents">
<span class="text-info" data-toggle="tooltip" data-placement="bottom" title="{{ form.contents.help_text }}">
<i class="far fa-question-circle"></i>
</span>
<small class="text-danger">{{ form.contents.errors }}</small>
</label>
</div>
<div class="form-group mb-4">
<div>{{ form.header_image_link }}</div>
<label for="id_header_image">
<span class="text-info" data-toggle="tooltip" title="{{ form.header_image_link.help_text|safe }}">
<i class="far fa-question-circle"></i>
</span>
<small class="text-danger">{{ form.header_image_link.errors }}</small>
</label>
</div>
</div>
<div class="col-sm-3">
<div class="form-group mb-4">
<div class=""><h4>{{ form.post_category.label }}</h4></div>
<div>{{ form.post_category }}</div>
<label for="id_category">
<span class="text-info" data-toggle="tooltip" title="{{ form.post_category.help_text }}">
<i class="far fa-question-circle"></i>
</span>
<small class="text-danger">{{ form.post_category.errors }}</small>
</label>
</div>
<div class="form-group mb-4">
<div class=""><h4>{{ form.post_tag.label }}</h4></div>
<div>{{ form.post_tag }}</div>
<label for="id_tag">
<span class="text-info" data-toggle="tooltip" title="{{ form.post_tag.help_text }}">
<i class="far fa-question-circle"></i>
</span>
<small class="text-danger">{{ form.post_tag.errors }}</small>
</label>
</div>
<div class="form-inline mb-4 py-0">
<div class="input-group mx-1">
<label for="id_highlighted">{{ form.highlighted.label }}</label>
<div class="ml-1">{{ form.highlighted }}</div>
</div>
<div class="input-group mx-1">
<label for="id_draft">{{ form.draft.label }}</label>
<div class="ml-1">{{ form.draft }}</div>
</div>
</div>
<div class="form-group mb-4">
<div class=""><h4>{{ form.publishing_date.label }}</h4></div>
<div class="input-group date" data-target-input="nearest">
{{ form.publishing_date }}
<div class="input-group-append" data-target="#publishing_date_field" data-toggle="datetimepicker">
<div class="input-group-text"><i class="fa fa-calendar"></i></div>
</div>
</div>
<label for="publishing_date_field">
<span class="text-info" data-toggle="tooltip" title="{{ form.publishing_date.help_text }}">
<i class="far fa-question-circle"></i>
</span>
<small class="text-danger">{{ form.publishing_date.errors }}</small>
</label>
<script>
$(function () {
$("#publishing_date_field").datetimepicker({
format: 'DD/MM/YYYY HH:mm',
});
});
</script>
</div>
<div class="form-group mb-4">
<div class=""><h4>{{ form.author.label }}</h4></div>
<div>{{ form.author }}</div>
<label for="id_author">
<span class="text-info" data-toggle="tooltip" title="{{ form.author.help_text }}">
<i class="far fa-question-circle"></i>
</span>
<small class="text-danger">{{ form.author.errors }}</small>
</label>
</div>
</div>
</div>
</div>
<hr>
<div class="row justify-content-md-center">
<div class="col-md-auto">
<input type="submit" class="btn btn-info shadow" value="Pubblica">
</div>
</div>
</form>
forms.py
class BlogPostForm(forms.ModelForm):
title = forms.CharField(
max_length=70,
help_text="<small>Write post title here. The title must be have max 70 characters.</small>",
widget=forms.TextInput(
attrs={
"placeholder": "Titolo",
"type": "text",
"id": "id_title",
"class": "form-control form-control-lg",
}
),
)
description = forms.CharField(
max_length=200,
help_text="<small>Write a post short description here. The description must be have max 200 characters.</small>",
widget=forms.Textarea(
attrs={
"placeholder": "Descrizione",
"type": "text",
"id": "id_description",
"class": "form-control",
"rows": "2",
}
),
)
contents = forms.CharField(
help_text="<small>Write your contents here.</small>",
widget=forms.Textarea(
attrs={
"placeholder": "Contenuti",
"type": "text",
"id": "id_contents",
"class": "form-control",
"rows": "20",
}
),
)
publishing_date = forms.DateTimeField(
input_formats=['%d/%m/%Y %H:%M'],
label="Data di pubblicazione",
help_text="<small>Write data and hour of publication. You can use also a past or a future date.</small>",
widget=forms.DateTimeInput(
attrs={
"id": "publishing_date_field",
'class': 'form-control datetimepicker-input',
'data-target': '#publishing_date_field',
}
),
)
draft = forms.BooleanField(
label="Bozza",
widget=forms.CheckboxInput(
attrs={
"type": "checkbox",
"id": "id_draft",
"class": "form-check-input mx-2",
}
),
required=False,
)
author = forms.ModelChoiceField(
label="Autore",
help_text="<small>Select the author.</small>",
widget= forms.Select(
attrs={
"id": "id_author",
"class": "custom-select",
}
),
empty_label=" ",
queryset= User.objects.all(),
)
post_tag =forms.ModelMultipleChoiceField(
label="Tag",
help_text="<small>Select one or more tags. Press CTRL and click on a tag for multiple selection.</small>",
widget= forms.SelectMultiple(
attrs={
"id": "id_category",
"class": "custom-select",
"size": "4",
}
),
queryset= BlogTag.objects.all(),
)
post_category = forms.ModelChoiceField(
label="Categoria",
help_text="<small>Select a category.</small>",
widget= forms.Select(
attrs={
"id": "id_category",
"class": "custom-select",
}
),
empty_label=" ",
queryset= BlogCategory.objects.all(),
)
header_image_link = forms.CharField(
max_length=1000,
help_text="<small>Past here the image link.</small>",
widget=forms.TextInput(
attrs={
"placeholder": "Url dell'immagine di testata",
"type": "text",
"id": "id_header_image",
"class": "form-control",
}
)
)
highlighted = forms.BooleanField(
label="In evidenza",
widget=forms.CheckboxInput(
attrs={
"type": "checkbox",
"id": "id_highlighted",
"class": "form-check-input mx-2",
}
),
required=False,
)
class Meta:
model = BlogPost
fields = [
"author",
"title",
"description",
"contents",
"header_image_link",
"post_tag",
"post_category",
"highlighted",
"draft",
"publishing_date",
]
models.py
class BlogPost(models.Model):
publishing_date = models.DateTimeField(
default=timezone.now,
blank=True,
)
updating_date = models.DateTimeField(
auto_now=True,
)
timestamp = models.DateTimeField(
auto_now=False,
auto_now_add=True,
)
title = models.CharField(
max_length=70,
unique=True,
)
slug_post = models.SlugField(
max_length=70,
unique=True,
)
description = models.TextField(
max_length=200,
blank=True,
)
contents = models.TextField(
blank=True,
)
draft = models.BooleanField(
default=False,
)
author = models.ForeignKey(
User,
related_name = "author_blogpost",
on_delete=models.CASCADE,
)
highlighted = models.BooleanField(
default=False,
)
header_image_link = models.CharField(
max_length=1000,
)
post_category = models.ForeignKey(
BlogCategory,
related_name = "category_blogpost",
on_delete=models.CASCADE,
)
post_tag = models.ManyToManyField(
BlogTag,
related_name = "tag_blogpost",
)
def __str__(self):
return self.title
class Meta:
ordering = ['-publishing_date']
views.py
def createPost(request):
if request.method == "POST":
form = BlogPostForm(request.POST or None)
if form.is_valid():
new_post = form.save(commit=False)
new_post.slug_post = slugify(new_post.title)
new_post.save()
return redirect('blogpost_list')
else:
form = BlogPostForm()
context = {
'form': form,
}
template = 'blog/editing/create_post.html'
return render(request, template, context)
def updatePost(request, slug_post=None):
update_post = get_object_or_404(BlogPost, slug_post=slug_post)
form = BlogPostForm(request.POST or None, instance=update_post)
if form.is_valid():
update_post = form.save(commit=False)
update_post.slug_post = slugify(update_post.title)
update_post.save()
return redirect('blogpost_list')
context = {
'form': form,
}
template = 'blog/editing/create_post.html'
return render(request, template, context)
What I've wrong?
Many to many relationships have to be manually set. You can either override your ModelForm's save method, this would mean that you can never use "commit=False"
def save(self, commit=True):
if not commit:
raise Exception('Cannot save many to many fields if the blog post is not committed')
instance = super().save()
instance.post_tag.add(*self.cleaned_data['post_tag'])
return instance
or you can add the tags in your view
if form.is_valid():
update_post = form.save(commit=False)
update_post.slug_post = slugify(update_post.title)
update_post.save()
update_post.post_tag.add(*form.cleaned_data['post_tag'])
return redirect('blogpost_list')