I have a django form and I need to display unit of measurement.
For example, for a form field I have label and value. I also need to have another 'label' for unit measurement.
E.g. Weight [Textbox] Kg
How can I add Kg in a form in forms.py? I'm using crispy forms module to render my forms.
This is an example from forms.py .
class WeightForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(LifeEventsForm, self).__init__(*args, **kwargs)
self.helper=FormHelper(self)
self.helper.layout = Layout(
'weight',
FormActions(
Submit('submit', "Save changes"),
Submit('cancel',"Cancel")
),
)
self.helper.form_tag = False
self.helper.form_show_labels = True
class Meta:
model = myWeight
My models.py looks like:
class myWeight(models.Model):
id = models.IntegerField()
weight = models.IntegerField(null=True,blank=True)
def __str__(self):
return str(self.id)
Maybe not best idea, but pretty straightforward:
You can override from crispy_forms.layout import Field with custom template
class DoubleLabeledField(Field):
template = "your_custom_field.html"
copypaste to your_custom_field.html everything from .../site-packages/crispy_forms/templates/bootstrap3/field.html (replace bootstrap3 if another template package) and put some info near every entrance of {{ field.label|safe }}
Then in your form should be:
self.helper.layout = Layout(
DoubleLabeledField('weight'),
FormActions(
Submit('submit', "Save changes"),
Submit('cancel',"Cancel")
),
)
Related
I have a form with lots of repetition and I want to use the wrap function of django crispy forms to reduce this. This is the form as it stands:
class MyForm(ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.helper = FormHelper(self)
self.helper.layout = Layout(
Row(Field(PrependedText('field1', 'Field1title', wrapper_class='col-12 stretchprepend')),
title = self.base_fields['field1'].help_text, data_bs_toggle='tooltip',
data_bs_placement='bottom', data_html="true"),
#fields 2-29
Row(Field(PrependedText('field30', 'Field30title', wrapper_class='col-12 stretchprepend')),
title = self.base_fields['field1'].help_text, data_bs_toggle='tooltip',
data_bs_placement='bottom', data_html="true")
)
CHOICES = [tuple([x,x]) for x in range(1,8)]
help_text = {'field1': ''''help text for field 1''' #etc for other fields)
field1 = IntegerField( label='Field1title', widget=Select(choices=CHOICES), help_text=help_text['field1'])
# Repeat up to field 30
class Meta:
model = mymodel
fields = ['field1',...,'field30']
I can get wrap to generate some aspects of the form like so:
self.helper.layout('field1'...'field30')
self.helper[:].wrap(Field, wrapper_class='col-12 stretchprepend')
I cant' seem to get it to work to include all the other aspects e.g. PrependedText, title, data_bs_toggle etc Please could anyone advise?
I wish to only display a subset of the choices for a model form field. E.g Depending on the url the user is at I might want only 'weight gain' and 'parkinsonism' displayed as options for the 'se_name' field.
I can work out how to get the url as a parameters in the view (p = self.request.GET.get("p", None)) But I cant work out how to use this parameter to limit the choices available.
This is the formset
SideeffectFormSet = inlineformset_factory(
Case,
SideEffect,
fields=("se_name",),
widgets={'concern': RangeInput()},
extra=0,
min_num=1,
validate_min=True,
)
Which is based on the model:
class SideEffect(TimeStampedModel):
SE_CHOICES = [
("weight_gain", "Weight Gain"),
("parkinsonism", "Parkinsonism"),
("dystonia", "Dystonia"),
("none", "None"),
]
se_name = models.CharField("",max_length=200, choices=SE_CHOICES, default="none")
case = models.ForeignKey(Case, on_delete=models.CASCADE)
And the form is rendered by this view:
class CaseView(LoginRequiredMixin, TemplateView):
model = Case
template_name = "se_balance/se_balance.html"
def get(self, *args, **kwargs):
p = self.request.GET.get("p", None)
sideeffect_formset = SideeffectFormSet(queryset=SideEffect.objects.none(),)
return self.render_to_response(
{ "sideeffect_formset": sideeffect_formset,
"sideeffect_formsethelper": SideEffectFormSetSetHelper,
}
)
To change the choices of a field in a formset dynamically you need to define a custom form class that does the choice alteration on __init__
from django import forms
from .models import SideEffect
class SideEffectForm(ModelForm):
class Meta:
model = SideEffect
fields = ['se_name']
def __init__(self, *args, p, **kwargs):
super().__init__(*args, **kwargs)
if p == 'foo':
self.fields['se_name'].choices = [
("weight_gain", "Weight Gain"),
("parkinsonism", "Parkinsonism"),
]
else:
...
Use the form class in your formset
SideeffectFormSet = inlineformset_factory(
Case,
SideEffect,
form=SideEffectForm,
extra=0,
min_num=1,
validate_min=True,
)
Then in your view you can pass custom parameters to the formset form
sideeffect_formset = SideeffectFormSet(queryset=SideEffect.objects.none(), form_kwargs={'p': p})
I have a cripsy django form.
What is the best way to hide the field label in the template when I use {% cripsy form %}?
I do not want the user to see MY_FIELD_1 and MY_FIELD_2.
class mYForm(forms.ModelForm):
MY_FIELD_1 = forms.BooleanField()
MY_FIELD_2 = forms.BooleanField()
def __init__(self, *args, **kwargs):
...
...
self.helper = FormHelper()
self.helper.layout = Layout(
Field('MY_FIELD_1',),
Field('MY_FIELD_2',),
)
...
If you want to remove all labels from your form when using the crispy forms FormHelper then you can use:
self.helper.form_show_labels = False
If you want to remove labels from certain fields then you can do
self.fields['some_field'].label = False
Where some_field is the name of the field whose label you want to remove.
I have a form that is displaying well only for the label text that I don't want and I have tried all I could to let it off my form but it won't just go...
forms.py:
class sign_up_form(forms.ModelForm):
class Meta:
model = Users
fields =['email']
widgets = {
'email': forms.EmailInput(attrs={
'id': 'email',
'class': 'form-control input-lg emailAddress',
'name': 'email',
'placeholder': 'Enter a valid email'})}
I have tried:
views.py:
from django.shortcuts import render
from mysite.forms import sign_up_form
def register(request):
sign_up = sign_up_form(auto_id=False)
context = {'sign_up_form': sign_up}
return render(request, 'mysite/register.html', context)
I need my widgets as defined above.
In ModelForms there will be default labels so you have to over-ride where you don't need labels
you can define it like this
class sign_up_form(forms.ModelForm):
email = forms.CharField(widget=forms.Textarea, label='')
class Meta:
model = Users
fields =['email']
This method will not include labels for your form, other method depends on rendering in template. You can always avoid labels from form
<label>MY LABEL</label> instead of {{ form.field.label }}
In __init__ method set your field label as empty.This will remove label text.
def __init__(self, *args, **kwargs):
super(sign_up_form, self).__init__(*args, **kwargs)
self.fields['email'].label = ""
If you're wanting to remove all labels, you can use:
class sign_up_form(forms.ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
for key, field in self.fields.items():
field.label = ""
I'm trying to display all my model items but add some crispy elements. However it shows my html and buttons above the model form fields instead of being under the html and above the buttons.
Form
class BusinessForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(BusinessForm, self).__init__(*args, **kwargs)
self.helper = FormHelper(self)
self.helper.form_class = 'form-horizontal'
self.helper.form_action = 'update'
self.helper.form_method = 'post'
self.helper.layout = Layout(
HTML("<p class='alert-info alert'>Please confirm your business contact information is updated and correct.</p>"),
Div(
FormActions(
Submit('save_changes', 'Save changes', css_class="btn-primary"),
),
css_class='row-fluid'
)
)
# self.helper.add_input(Submit('save_changes', 'Save changes', css_class="btn-primary"))
class Meta:
model = Business
exclude = ('inactive',)
View
def index(request, token):
try:
business = Business.objects.get(token__token=token)
except Token.DoesNotExist:
business = None
except Business.DoesNotExist:
business = None
return render(request, 'business/index.html', {'form': BusinessForm(instance=business)})
I saw use Crispy form with ModelForm however it displays my model fields below the formactions and I even tried an add_input which did the same thing. How would I get my model form fields to be displayed between the alert-info and above the submit button?