I want to create a dropdown Course of Trainee where only options of values in CourseName of Course model would be shown. Currently I have tried some soulutions after browsing. But its not working. My course dropdown disappeared after editing in forms.py. If i remove this line
Course = forms.ChoiceField(widget=forms.Select(attrs={'class':'col-sm-4'}), choices=course_obj.get_course_name(), label='Course :')
Then the dropdown would show but with no options
model.py
class Course(models.Model):
CourseID = models.AutoField(primary_key=True)
CourseName = models.CharField(max_length=20)
class Meta():
db_table = "Courses"
def get_course_name(self):
return self.CourseName
class Trainee(models.Model):
Name = models.CharField(max_length=50)
Course = models.CharField(max_length=40)
class Meta():
db_table = "Trainee"
forms.py
class TraineeForm(forms.ModelForm):
course_obj = Course()
Name = forms.CharField(widget=forms.TextInput(attrs={'class':'col-sm-4'}), label='Name :')
Course = forms.ChoiceField(widget=forms.Select(attrs={'class':'col-sm-4'}), choices=course_obj.get_course_name(), label='Course :')
........................
edit.html
<form method="post" class="form-group" type="multipart/form-data">
{%csrf_token%}
{% for Name in form.Name %}
<div class="form-group row">
<label class="col-sm-3 col-form-label">{{ form.Name.label }}</label>
{{ Name }}
</div>
{% endfor %}
{% for Course in form.Course %}
<div class="form-group row">
<label class="col-sm-3 col-form-label">{{ form.Course.label }}</label>
{{ form.Course }}
</div>
{% endfor %}
The Page appears like this
While looping a BoundField object - for Name in form.Name and for Course in form.Course in your case, Django loop through its sub widgets. A CharField has one sub widget, which is its self. A ChoiceField has as many sub widgets as its options, which is zero in your case. This is why your page rendered like that.
According to Django's Doc on choices attribute of ChoiceField:
Either an iterable of 2-tuples to use as choices for this field, enumeration choices, or a callable that returns such an iterable. This argument accepts the same formats as the choices argument to a model field. See the model field reference documentation on choices for more details. If the argument is a callable, it is evaluated each time the field’s form is initialized, in addition to during rendering. Defaults to an empty list.
Try
# forms.py
def course_choices():
return [(course.CourseName, course.CourseName) for course in Course.objects.all()]
class TraineeForm(forms.ModelForm):
Name = forms.CharField(widget=forms.TextInput(attrs={'class':'col-sm-4'}), label='Name :')
Course = forms.ChoiceField(widget=forms.Select(attrs={'class':'col-sm-4'}), choices=course_choices, label='Course :')
class Meta:
model = Trainee
fields = ['Name', 'Course']
And then in your template:
<!-- edit.html -->
<form method="post" class="form-group" type="multipart/form-data">
{% csrf_token %}
<div class="form-group row">
<label class="col-sm-3 col-form-label">{{ form.Name.label }}</label>
{{ Name }}
</div>
<div class="form-group row">
<label class="col-sm-3 col-form-label">{{ form.Course.label }}</label>
{{ form.Course }}
</div>
</form>
===== form.py =====
class TraineeForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(TraineeForm, self).__init__(*args, **kwargs)
self.fields['Course'].widget = forms.Select(choices=Course.objects.values_list('CourseName','CourseName'))
class Meta:
model = Trainee
fields = "__all__"
========= output ===========
Related
I have a Django form that I have created manually in order to keep the format of the styling, but I realized that the form is compromised of several inputs and manually is taking too long to change each.
I am also able to generate the form automatically using {{ form.as_p }} but I lose the HTML style format that I have below. Is there an easy way to make it instead of manually changing each input?
This is the original HTML template that I am trying to keep
</button>
<div class="form-outline mb-4">
<input
type="text"
id="businessName"
class="form-control"
name="businessName"
/>
<label class="form-label" for="typeText"
>Legal Business Name</label>
</div>
Here is the working Django form:
{% if submitted %}
Your forms has been submitted
{% else %}
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<!-- Submit button -->
<button
type="submit"
class="btn btn-primary btn-block mb-4"
id="btn"
>
Submit
</button>
</form>
Here is the views.py
def add_form(request):
submitted=False
if request.method == 'POST':
form = infoForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('/?submitted=True')
else:
form = infoForm()
if 'submitted' in request.GET:
submitted=True
return render(request, 'template/template.html',{'form':form, 'submitted':submitted})
Here is the form
class infoForm(ModelForm):
class Meta:
model = Info
fields = ['businessName']
Here is what I have tried:
<div class="form-outline mb-4">
<input type="text" class="form-control" name="businessName" {% if form.is_bound %}value="{{ form.businessName.value }}"{% endif %}>
<label class="form-label">Legal Business Name</label>
</div>
{% for err in form.businessName.errors %}
<small class="text-danger mb-2 ml-2">{{ err }}</small>
{% endfor %}
My Question:
How to keep the same HTML styling while making it easy by using {{ form.as_p }}?
What is the required input for attributes in this case?
This will be the quickest way to apply custom styling to the django forms so that you let the django take care of processing the form while still using your preferred css styling...
Taken from my answer to: How to markup form fields with in Django
class MyForm(forms.Form):
myfield = forms.CharField(widget=forms.TextInput(attrs={'class': 'myfieldclass'}))
or
class MyForm(forms.ModelForm):
class Meta:
model = MyModel
def __init__(self, *args, **kwargs):
super(MyForm, self).__init__(*args, **kwargs)
self.fields['myfield'].widget.attrs.update({'class': 'myfieldclass'})
or
class MyForm(forms.ModelForm):
class Meta:
model = MyModel
widgets = {
'myfield': forms.TextInput(attrs={'class': 'myfieldclass'}),
}
originally answered
EDIT 1 : Adding Label styling
1 set the class by the above mentioned method
eg:
self.fields['some_field'].widget.attrs.update({'class': 'some_class'})`
2 Select the label of that class and style them
.that_some_class label{
font-size: large;
}
I am new in Django, I am trying to validate a form to get the particular value, if value is not exact validate error. For example, i have a field in a model (cot_code), the field has a integer value (12345). I have created a form for this field, i want if the user enter 12345 in form, the form will be valid as success "code is correct", but when user enter a wrong code (55777) the form will raise a validator error "Wrong code". I do not know how to go on with the views.
Model:
class CotCode(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
cot_code = models.IntegerField(default='0', blank=True) # I have set this field as 12345 in model.
date = models.DateTimeField(auto_now_add=True)
class Meta:
verbose_name = 'CotCode'
verbose_name_plural = 'CotCode'
ordering = ['-date']
def __str__(self):
return self.user.username
Forms:
class CotCodeForm(forms.ModelForm):
class Meta:
model = CotCode
fields = ('cot_code',)
Views:
#login_required
def TransferCOTView(request):
#Don't know how to go on here
return render(request, 'transfer_cotcode.html')
Template:
<form method="POST" action="" class="text-center needs-validation" novalidate>
{% csrf_token %}
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text" id="inputGroup-sizing-default">C.O.T</span>
</div>
<input type="text" class="form-control" aria-label="Sizing example input" aria-describedby="inputGroup-sizing-default" placeholder="Enter your COT Code" required>
<div class="invalid-feedback">
Please enter your C.O.T code.
</div>
</div>
<input type="submit" class="btn btn-primary btn-block btn-sm wave-effect my-2" value="{% trans 'Enter' %}" style="box-shadow:none;font-weight:500;"/>
</form>
It is possible to change the style of form in the view?
I found in documentation this code:
<form action="/contact/" method="post">
{{ form.non_field_errors }}
<div class="fieldWrapper">
{{ form.subject.errors }}
<label for="id_subject">Email subject:</label>
{{ form.subject }}
</div>
<div class="fieldWrapper">
{{ form.message.errors }}
<label for="id_message">Your message:</label>
{{ form.message }}
</div>
<div class="fieldWrapper">
{{ form.sender.errors }}
<label for="id_sender">Your email address:</label>
{{ form.sender }}
</div>
<div class="fieldWrapper">
{{ form.cc_myself.errors }}
<label for="id_cc_myself">CC yourself?</label>
{{ form.cc_myself }}
</div>
<p><input type="submit" value="Send message" /></p>
</form>
But it just put a ugly input. I want to apply a class, or a css in this input. Is it possible?
This is my form:
class LoginView(NextUrlMixin, RequestFormAttachMixin, FormView):
form_class = LoginForm
success_url = '/'
template_name = 'accounts/login.html'
default_next = '/'
class LoginForm(forms.Form):
email = forms.EmailField(label='Email')
password = forms.CharField(widget=forms.PasswordInput)
If you are use a custom css set the class CSS on the forms example:
email = forms.EmailField(label='Email')
email.widget.attrs.update({'class':'customClass', 'required':'required'})
in this case set a customClass if you are using Bootstrap maybe you can use someone like this:
email = forms.EmailField(label='Email')
email.widget.attrs.update({'class':'form-control', 'required':'required'})
this code is on your forms.pyp .. good luck
don't forget load your css file on your template
You can do so by applying some attributes to the widget that you use:
more info can be found here Official Django Documentation
for instance:
email = forms.EmailField(label='Email',
widget=forms.TextInput(attrs={'class':'class_value','placeholder':"Email here"}))
If you want to have the full control of the form html by keeping the same behavior as the one generated by django, the following will work
<input type="email" name="email" id="id_email" value="{{form.email.value}}" class='class_name' attrs='attrs' >
{{ form.email.errors}} <!-- track errors for this field -->
Yes. You can attach a css file to your form (place a {{ form.media }} in your template) with this:
class LoginForm(forms.Form):
email = forms.EmailField(label='Email')
password = forms.CharField(widget=forms.PasswordInput)
class Media:
css = {
'all': ('login-form-layout.css',)
}
js = (
'https://some-cdn.com/some-framework.js'
'login-form-script.js',
)
Inputs have an ID like id_fiedname so login-form-layout.css can be something like:
#id_email, #id_password {
width: 200px;
}
You can do a lot with CSS and with javascript there are endless possibilities.
You may want to check "Customizing widget instances" at the official Django documentation. For example, you can attach arbitrary attributes to the input tag using the attrs argument:
email = forms.EmailField(
label='Email',
widget=forms.TextInput(attrs{
'class': 'my-super-special-input',
'placeholder': "mailbox#example.com"
}),
)
There are other possibilities there, so check it out.
Use Django widget_tweaks. It’s real convenient. And you can easily change any attribute you want.
{% load widget_tweaks %}
{% render_field form.field class=“your-class” %}
This question already has an answer here:
Customize the styles of Django ClearableFileInput widget
(1 answer)
Closed 6 years ago.
I'm working on a web app that has photo upload functionality. I created a ModelForm to gather minimal user info plus a photo, and when I render it in HTML as {{ form.as_p }}, the field that allows the user to upload an image shows up just fine. The problem is, the form doesn't look good.
I need to be able to manually render the form in order to make it look better. I have written the HTML for this, and everything looks right except for the ImageFileField. Only the label gets rendered, not the upload button, checkbox to clear the file, etc.
What do I need to do to get the ImageFileField from the ModelForm to render correctly in my custom HTML? I've looked at the Django docs up and down, looked here on SO and can't find anyone else who's had this issue. Many thanks in advance!
forms.py snippet
class PostForm(forms.ModelForm):
class Meta:
model = Items
fields = ('title', 'description', 'image_file')
new_item.html snippet
<form enctype="multipart/form-data" method="post" action="" class="post-form">
{% csrf_token %}
{{ form.non_field_errors }}
<div class="fieldWrapper">
{{ form.title.errors }}
<label for="{{ form.title.id_for_label }}">Title:</label><br>
{{ form.title }}
</div><br>
<div class="fieldWrapper">
{{ form.description.errors }}
<label for="{{ form.description.id_for_label }}">Description: </label><br>
{{ form.description }}
</div><br>
<div class="fieldWrapper">
{{ form.image_field.errors }}
<label for="{{ form.image_field.id_for_label }}">Image (optional):</label><br>
{{ form.image_field }}
</div>
<button type="submit" class="save btn btn-default">Save</button>
</form>
models.py snippet
class Items(models.Model):
title = models.CharField(max_length=1000, null=False)
description = models.TextField(max_length=1000, null=False)
image_file = models.ImageField(max_length=1000,
blank=True,
default='',
null=True,
upload_to='item_photos')
By default django ModelForm uses django.forms.ImageField and not ClearableInputField for django.db.ImageField as revealed at https://docs.djangoproject.com/en/1.9/topics/forms/modelforms/#field-types
And I do believe you actually meant ClearableFileInput
ClearableFileInput¶
class ClearableFileInput File upload input: ,
with an additional checkbox input to clear the field’s value, if the
field is not required and has initial data.
How you can make use of it is by changing the widget in the class meta
class PostForm(forms.ModelForm):
class Meta:
model = Items
fields = ('title', 'description', 'image_file')
widgets = {
'name': ClearableFileInput(),
}
I ended up using the Chrome tool to inspect the HTML source for the page that rendered correctly (but ugly), and used that as a guide to custom build the form in HTML to my liking. This is what I needed to add into my HTML form to get it right:
{% if item.image_file %}
Currently:
{{item.image_file.url}}
<input id="image_file-clear_id" name="image_file-clear" type="checkbox" /> <label for="image_file-clear_id">Clear</label><br />Change: <input id="id_image_file" name="image_file" type="file" /></p>
{% endif %}
{% if not item.image_file %}
<input id="id_image_file" name="image_file" type="file" /></p>
{% endif %}
SOLVED by Peter DeGlopper:
Thank you for your help it solved my issues, I really do appreciate it. I was banging my head against the table.
I didn't have to change my ModelForm. Looking at the HTML source I noticed in the input tag checked="checked" A subnet was being outputted as checked but it wasn't showing checked in my browser. This was in Firefox 24.2.0 in CentOS (On a VM), so I went to my Windows 7 host and loaded up Firefox 26.0 it worked, and worked fine in IE8 as well. That was weird, but it explains your confusion of that it should just work.
For saving the fields thanks to you I now see how I was over thinking it. And I am able to update the M2M field. I updated the TagUpdateView below to show the working code.
I have 2 issues with trying use an UpdateView with a M2M field...
The currently "tagged" subnets dont show up as checked in my template
How would I handle updating the M2M relationship in my TagUpdateView by overriding form_valid?
Any insight would be greatly appreciated.
Thanks.
Tag m2m models.py:
class Tag(models.Model):
tag = models.CharField(max_length=120)
group = models.ForeignKey(Group)
description = models.TextField(max_length=500)
subnet = models.ManyToManyField(Subnet, null=True, blank=True)
date_created = models.DateTimeField()
created_by = models.ForeignKey(User, related_name='tag_created_by')
date_modified = models.DateTimeField(auto_now=True)
modified_by = models.ForeignKey(User, related_name='tag_modified_by')
def __unicode__(self):
return self.tag
Tag ModelForm:
class TagForm(forms.ModelForm):
subnet = forms.ModelMultipleChoiceField(widget=forms.CheckboxSelectMultiple(), required=True, queryset=Subnet.objects.all())
class Meta:
model = Tag
exclude = ('date_created', 'created_by', 'date_modified', 'modified_by')
Tag views.py:
class TagUpdateView(UpdateView):
template_name = 'tag_update.html'
model = Tag
form_class = TagForm
def form_valid(self, form):
update_tag = form.save(commit=False)
update_tag.modified_by = self.request.user
update_tag.save()
form.save_m2m()
return super(TagUpdateView, self).form_valid(form)
My template "tag_update.html":
{% extends 'base.html' %}
{% load widget_tweaks %}
{% block title %}Tag {{ object.tag }} Update{% endblock %}
{% block content %}
<h1>Tag {{ object.tag }} Update</h1>
<br />
<form action="" method="post" role="form">{% csrf_token %}
<div class="row">
<div class="col-sm-4">
<div class="form-group">
<label for="id_tag">Tag Name</label>
{% render_field form.tag placeholder=form.tag.label class="form-control" %}
</div>
</div>
</div>
<div class="row">
<div class="col-sm-2">
<div class="form-group">
<label for="id_group">Group</label>
{% render_field form.group placeholder=form.group.label class="form-control"%}
</div>
</div>
</div>
<div class="row">
<div class="col-sm-6">
<div class="form-group">
<label for="id_description">Description</label>
{% render_field form.description placeholder=form.description.label class="form-control" rows="5" %}
</div>
</div>
</div>
<div class="row">
<div class="col-sm-6">
<div class="form-group">
<label for="id_checkbox">Link to Subnets</label>
{{ form.subnet }}
</div>
</div>
</div>
<br />
<button type="submit" class="btn btn-primary">Submit</button>
</form>
<br />
{% endblock %}
You're overthinking it. Handling this kind of relationship can be a little bit complicated if you need to track information on the relationship model itself (like a modified timestamp for when a particular subnet/tag pair was created) but for the model relationships you've shown here, form.save_m2m() is sufficient - it handles the m2m relationship for you.
You wouldn't even need that if you didn't need to use commit=False on your initial form save so you can set your modified_by field.
For prepopulation - mostly this looks to me like it should follow the normal behavior and prepopulate. I would probably just use the widget class rather than explicitly instantiating it (widget=forms.CheckboxSelectMultiple rather than widget=forms.CheckboxSelectMultiple()) but I don't see why that would affect it.
For both problems, you might have good results by starting with a simple ModelForm with no customizations on subnet, just exclude set. Once that's working, put in the special view code to handle modified_by. Once that's working, change to a custom widget declaration for subnet - maybe initially using the meta widgets override dictionary rather than a custom field declaration for the first pass.