Django form: visibly group or separate fields - html

I have a form that I'm displaying within a Django app. This form has a number of fields.
To make the UI more intuitive, I would like to display the fields not simply one after the other, but instead grouped into sections - be it within a box or by separating the sections with a horizontal line or larger spacing or custom text etc.
My main interest is having the subgroups visibly separated from each other. Being able to use some text (basically a label without an attached field) as section devider would be a welcome bonus.
How can I achieve this?
Current example code:
forms.py:
from django import forms
class MyForm(forms.Form):
color1 = forms.CharField()
items_color1 = forms.CharField()
# some devider here
color2 = forms.CharField()
items_color2 = forms.CharField()
mypage.html:
<table>
{{ form.as_table }}
<tr>
<td> </td>
<td><input type="submit" value="Submit" id="form_field" name="submit_btn"></td>
</tr>
</table>
(I'm pretty new to Django. My previous GUI experience is mainly with PyQt5.)

You are luck, my friend.
Take a look at Django Crispy Forms. Using this product, you can programmatically control the layout of your form from within the Form definition.
Once you install Django Crispy Forms into your virtual environment, you'll have to add a line to your settings file to be able to use it:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.humanize',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
...
'crispy_forms',
...
]
After you do that, you'll be able to use django crispy forms in your application.
The example form that you posted could look like this inside of your forms.py file:
from django import forms
from crispy_forms.bootstrap import FormActions
from crispy_forms.helper import FormHelper
from crispy_forms.layout import Field, HTML, Layout, Submit
class MyForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.helper = FormHelper(self)
self.fields['color1'].label = 'Color 1:'
self.fields['items_color1'].label = 'Color 1 Items:'
self.fields['color2'].label = 'Color 2:'
self.fields['items_color2'] = 'Color 2 Items:'
# You can dynamically adjust your layout
self.helper.layout = Layout(Field('color1),
Field('items_color1),
HTML(<hr>),
Field('color2'),
Field('items_color2),
FormActions(Submit('save', 'Save changes')))
You would style it in your CSS.
Here are some nice examples using Django Crispy Forms.

Related

Django sign in form, the stylizing with Bootstrap is not doing anything

I am having some troubles with Django. So, I wanted to use Bootstrap´s sign in template and use it in my project. So, I have been able to do it correctly, except the username and password fields, which are showing up as regular {{form.username}} even though I have used the form-control class. Let me show you:
forms.py
from django import forms
from django.forms import TextInput, PasswordInput
class LogINFO(forms.Form):
username= forms.CharField(label= 'Usuario: ', max_length=20, widget=forms.TextInput(attrs={"placeholder": "Username", 'style': 'width: 300px;', "class": "form-control"}))
password=forms.CharField(widget=forms.PasswordInput(attrs={'placeholder': 'Password', 'style': 'width: 300px;', 'class': 'form-control'}))
and my login.html
{% csrf_token %}
<div class="form-floating">
{{form.username}}
</div>
<div class="form-floating">
{{form.password}}
</div>
Well, it apparently omits everything and it just shows up as a regular form input.
I am not using model as I am using the auth application.
Authentication forms like login have a tendency to override customisations unless set up in a particular way.
Try the following
urls.py
from django.contrib.auth import views
from .forms import LogINFO
....
path('login/',
views.LoginView.as_view(
template_name="registration/login.html", #this is default, change as needed
authentication_form=LogINFO,
),
name='login'
),
views.py
from django.contrib.auth.forms import AuthenticationForm,
class LogINFO(AuthenticationForm):
username= forms.CharField(label= 'Usuario: ', max_length=20, widget=forms.TextInput(attrs={"placeholder": "Username", 'style': 'width: 300px;', "class": "form-control"}))
password=forms.CharField(widget=forms.PasswordInput(attrs={'placeholder': 'Password', 'style': 'width: 300px;', 'class': 'form-control'}))
def __init__(self, *args, **kwargs):
super(LogINFO, self).__init__(*args, **kwargs)
The key elements are:
making your form a subclass of the AuthenticationForm class (which makes sense as you are using Django's auth)
calling the super init function (which allows the subclass to use all the methods of the class)
and providing the class of the authentication_form in your URLs.py file
One final note, when I am overriding a template for another app like django.config.auth, I place the app in question before it in settings.py INSTALLED_APPS so that it finds my new template first.

Django forms. Make ChoiceField required on frontend <select>

I have created a Django form, which uses a ChoiceField:
control_model = forms.ChoiceField(choices=(), required=True)
(The reason 'choices' are empty is because they are set using a function based on my backend database)
The following is the entire form:
class CreateWorkflowForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(CreateWorkflowForm, self).__init__(*args, **kwargs)
self.request = kwargs.pop("request")
self.fields['control_model'].choices = my_function()
control_model = forms.ChoiceField(choices=(), required=True)
class Meta:
model = CreateWorkflowModel
fields = ['control_model']
The model used looks the following:
class CreateWorkflowModel(models.Model):
control_model = models.CharField(max_length=100)
I use this form in a Django template the following way:
<div class="form-content">
{{ form.media }}
{{ form.as_p }}
<input type="submit" id="id_submit" value="Submit" />
</div>
However on my webpage the <select> that corresponds to my ChoiceField doesn't have the attribute 'required':
This means that my form will fail if no value is input into the ChoiceField (because its required in the form) However I would much prefer if a popup box appeared on frontend stating "You need to enter a value on this field".
I know having the "required" value on the <select> would do this exact thing, however I don't know how to make django generate the <select> with this attribute.
If you need required attribute on your select, you must have first chose element with empty value, otherwise it's invalid HTML.
See source code of the widget

Prevent anchor link to adding to the url in Django

I have a project where I can list distributions. I have a homepage where I have the options to click on the lecture or lecturer. Now I want that when I am on the lecturers page that I can click on one anchor tag which redirects me to the target page. However the URL does only add the new slug. I will post the urls and templates. Hope you can help me, Thanks in advance.
urls.py
app_name='distribution'
urlpatterns=[
path('',views.Index.as_view(),name='home'),
path('<slug:slug>/',views.LecturerDistribution.as_view(),name='lecturer_distribution'),
path('dersler/<slug:slug>/',views.LectureDistribution.as_view(),name='lecture_distribution'),
]
this my part in the lecture code template
<p style="text-align:center;"><a style="text-decoration:none" href="{% url 'distribution:lecture_distribution' slug=i.lecturer.slug%}">{{i.lecturer}}</a> | {{i.semester}}</p>
and here is my cbv for the lecture_distribution
class LectureDistribution(generic.DetailView):
model=Lecture
template_name='lecture.html'
def get_success_url(self):
return reverse('lecture_distribution', kwargs={'slug': self.object.slug})
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context ['distribution_'] = Distribution.objects.filter(lecture=self.object).order_by('-created_on')
return context
my url when I am clicking on the anchor tag is this:
http://127.0.0.1:8000/dagilimlar/dersler/mehmet-cem-guclu/
But it should
http://127.0.0.1:8000/dagilimlar/mehmet-cem-guclu/
as you see the "dersler" field is there which should not it is only for the lectures.

Database to checkbox feild in django

How to create a checkboxs field in html with django as backend and how to get the value of the selected checkbox back to the view for more processing
It's simple:
class Sample(models.Model):
checkbox = models.BooleanField(blank=False, null=False, default=True)
In the template you just simply
{{ object.checkbox }}
https://docs.djangoproject.com/en/1.6/topics/db/models/

How to display a date attribute of an object as the default value in HTML date input type

Hi I am trying to implement a editing page that accept the id of an object and load all its original value && enable editing/updateing.
e.g
for text type ,I use
<label>Field1:</label>
<input type="text" id="id_field1" value='{{ objectInstance.filed1}}' name="field1"/>
for Textares
<label>Field2:</label>
<textarea id="id_field2" name="field2">
{{ objectInstance.field2}}
They both worked fine in loading original data of the instance and allowing editing. But for the date field, I cannot find out how to load it..
I am trying something like
<label>Deadline:</label>
<input type="date" id="id_deadline" name="deadline" value={{objectInstance.deadline}}>
(the deadline is of date data type e.g 2013-6-4)
Can anyone help solving this problem? Thanks very much.
You can use the UpdateView generic class based view to simplify this process. A similar question was answered before.
The other way to fix this is to use a ModelForm, and pre-load it with an instance. This is actually what UpdateView does, but if you don't want to use class based views, here is the alternative:
In your forms.py:
from django import forms
from someapp.models import SomeModel
class SomeModelForm(forms.ModelForm):
class Meta:
model = SomeModel
In your views.py:
def someview(request):
obj = SomeModel.objects.get(pk=1) # Fetch the object to be edited
form = SomeModelForm(instance=obj) # Load the form with the object's data
return render(request, 'edit.html', {'form': form})
In edit.html:
<form method="POST">
{% csrf_token $}
{{ form }}
<input type="submit">
</form>
This will automatically create the form, fill it in with the data from the model. You would still have to write the logic to update the record in your view.