I want to create a Django form that allows users to select options from a dropdown menu, but I am getting a value error:
ValueError: need more than 1 value to unpack
Form:
class DropdownForm(forms.Form):
def __init__(self,*args,**kwargs):
choices = kwargs.pop('choices')
label = kwargs.pop('label')
super(DropdownForm,self).__init__(*args,**kwargs)
self.fields['selected'].label = mark_safe(label)
self.fields['selected'].choices = choices
selected = forms.ChoiceField(widget=forms.Select(attrs={'class':"form-control text-center"}))
View.py:
form_rate = DropdownForm(choices=[("HIGH","HIGH")],label="RATE",prefix="Rate")
form_pass_setup = DropdownForm(choices=[("AUTO","AUTO"),("MANUAL","MANUAL")],label="Pass Setup",prefix="pass_setup")
form_dict.update({'form_rate':form_rate,'form_pass_setup':form_pass_setup})
return render(request,'Nominal.html',form_dict)
Template:
<form action="/InterfaceApp/Nominal_Request/" method="post" class="form">
{% csrf_token %}
<div class="panel-body text-center">
<div class="row pad_forms">
<div class="col-xs-3">
{% bootstrap_form form_rate %}
</div>
<div class="col-xs-3">
{% bootstrap_form form_pass_setup %}
</div>
</div>
<br><br>
<button type="submit" class="btn btn-primary center-block" value="Submit" name="Single">
{% bootstrap_icon "fire" %} Generate a Single Requests
</button>
</div>
</form>
Can anyone tell me why I'm getting this value error?
The problem might occur cause you have not set the required argument choices for your ChoiceField.
Here is a link to the docs: https://docs.djangoproject.com/en/1.8/ref/forms/fields/#choicefield.
Related
I reviewed most of the posts here related to Django and BooleanField update, but I couldn't find any related to my problem solution.
I have a custom user models.py:
# Own custom user model
class Account(AbstractBaseUser):
username = models.CharField(max_length=30, unique=True)
guardianSource = models.BooleanField(default=True)
bbcSource = models.BooleanField(default=False)
independentSource = models.BooleanField(default=False)
categoryCoronaVirus = models.BooleanField(default=False)
categoryPolitics = models.BooleanField(default=False)
categorySport = models.BooleanField(default=False)
When I register a user it seems to register in the database all correct values for the checkboxes. The problem is when I want to edit user information I cannot see if a checkbox was checked on registering or not, it displays the checkboxes itself, but they are all empty (False). However, it correctly requests the username and displays it so I can edit it, but all the checkboxes are unchecked.
views.py:
def account_view(request):
if not request.user.is_authenticated:
return redirect('login')
context = {}
if request.POST:
form = AccountUpdateForm(request.POST, instance=request.user)
if form.is_valid():
form.save()
context['success_message'] = "Updated"
else: # Display the saved user details from database
form = AccountUpdateForm(
initial = {
'username':request.user.username,
"guardianSource": request.user.guardianSource,
"bbcSource": request.user.bbcSource,
"independentSource": request.user.independentSource,
"categoryCoronaVirus": request.user.categoryCoronaVirus,
"categoryPolitics": request.user.categoryPolitics,
"categorySport": request.user.categorySport,
})
context['account_form'] = form
return render(request, 'accounts/account.html', context)
account html:
{% extends 'base.html' %}
{% block content %}
<form class="form-signin" method="POST">{% csrf_token %}
<h1 class="h3 mb-3 font-weight-normal">Account Settings</h1>
<label for="username" class="sr-only">Username</label>
<input type="text" name="username" id="username" class="form-control" placeholder="Username" value="{{account_form.initial.username}}">
<br>
<div class="form-control">
<p><b>Please choose news sources!</b></p>
<label for="guardianSource" >The Guardian</label>
<input type="checkbox" name="guardianSource" id="guardianSource" value="{{account_form.initial.guardianSource}}" >
<br>
<label for="bbcSource" >BBC News</label>
<input type="checkbox" name="bbcSource" id="bbcSource" value="{{account_form.initial.bbcSource}}" >
<br>
<label for="independentSource" >The Independent</label>
<input type="checkbox" name="independentSource" id="independentSource" value="{{account_form.initial.independentSource}}" >
</div>
<br>
<div class="form-control">
<p><b>Please choose news category!</b></p>
<label for="categoryCoronaVirus" >The Guardian</label>
<input type="checkbox" name="categoryCoronaVirus" id="categoryCoronaVirus" value="{{account_form.initial.categoryCoronaVirus}}" >
<br>
<label for="categoryPolitics" >BBC News</label>
<input type="checkbox" name="categoryPolitics" id="categoryPolitics" value="{{account_form.initial.categoryPolitics}}" >
<br>
<label for="categorySport" >The Independent</label>
<input type="checkbox" name="categorySport" id="categorySport" value="{{account_form.initial.categorySport}}">
</div>
{% for field in registration_form %}
<p>
{% for error in field.errors %}
<p sttle="color:red"> {{ error }}</p>
{% endfor %}
</p>
{% endfor %}
{% if registration_form.non_field_errors %}
<div style="color:red;">
<p>{{registration_form.non_field_errors}}</p>
</div>
{% endif %}
{% for field in account_form %}
<p>
{% for error in field.errors %}
<p sttle="color:red"> {{ error }}</p>
{% endfor %}
</p>
{% endfor %}
{% if account_form.non_field_errors %}
<div style="color:red;">
<p>{{account_form.non_field_errors}}</p>
</div>
{% endif %}
{% if success_message %}
<p style = "color: green; text-align:center;">{{success_message}}</p>
{% endif %}
<h6 class="text-muted">
If you don't choose a source and category it will automatically assign the ones that are checked!<br>
NOTE: You <b>MUST</b> select at least 1 choice for each!!!
</h6>
<button class="btn btn-lg btn-primary btn-block" type="submit">Save Changes</button>
</form>
<div class="d-flex flex-column">
<a class="m-auto" href="{% url 'password_change' %}">Change password</a>
</div>
{% endblock content %}
Thanks in advance and I am sorry if my post is duplicated.
EDIT:
The issue was found.
In the account.html file the values for each input type checkbox were wrong.
What I changed from:
<input type="checkbox" name="guardianSource" id="guardianSource" value="{{account_form.initial.guardianSource}}" >
To:
<input type="checkbox" name="guardianSource" id="guardianSource" value="{{account_form.guardianSource}}" >
For all the input values after the username input the initial had to be removed
You don't need to pass initial when you are initializing a ModelForm and have the instance
else: # Display the saved user details from database
form = AccountUpdateForm(instance=request.user)
You can use the field directly in the template and it will be rendered with the correct values, you don't need to construct the html for the input yourself
<label for="{{ account_form.guardianSource.id_for_label }}">The Guardian</label>
{{ account_form.guardianSource }}
The docs have a section on how to render fields manually
I have a FBV using django-tables2 so the the template already call the objects but i need to add a button that triggers a modal so I need to call the pk of the objects inside the button
here's the views.py
def Patients_list(request):
patients = Patient.objects.filter(user=request.user)
table = PatientTable(patients)
RequestConfig(request).configure(table)
return render(request, 'patients/patients_list.html',{
'table' : table,
'patients':patients,
})
and the button is callable at the tables.py
class PatientTable(tables.Table):
FirstName = tables.Column(linkify=("patients:patient_detail", {"pk": tables.A("pk")}))
LastName = tables.Column(linkify=("patients:patient_detail", {"pk": tables.A("pk")}))
Telephone_no = tables.Column(linkify=("patients:patient_detail", {"pk": tables.A("pk")}))
delete = TemplateColumn('<button type ="button" class ="btn btn-danger" data-toggle="modal" data-target="#modalDelete" >Deleta</button>',extra_context={'patient': 'Patient'})
class Meta:
model = Patient
attrs = {'class': 'table table-striped table-hover'}
exclude = ("user", "Notes", "Adress")
template_name = 'django_tables2/bootstrap4.html'
and the template:
{% extends 'base.html' %}
{% load render_table from django_tables2 %}
{% block content %}
<div id="content">
{% if user.is_authenticated %}
<h1> Patients list: </h1>
<br>
Add Patient
<br>
<br>
{% render_table table %}
{% else %}
<h2>please login</h2>
{% endif %}
</div>
<div class="modal fade" id="modalDelete" tabindex="-1" role="dialog" aria-labelledby="modalDelete"
aria-hidden="true">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Delete patient!</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<p>Are you sure you want to delete this patient?</p>
</div>
<div class="modal-footer">
<form method="POST" action="{% url 'patients:patient_delete' pk=patients.pk %}">
{% csrf_token %}
<input class="btn btn-danger" value="Yes" type="submit" >
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
</form>
</div>
</div>
</div>
</div>
{% endblock %}
so when i call the patient.pk in this page it always return an error :
Reverse for 'patient_delete' with keyword arguments '{'pk': ''}' not found. 1 pattern(s) tried: ['patients/delete/(?P<pk>[0-9]+)$']
but when i call the same url(with a different name if it's in another context) it worked and every FBV listview tutorial calls the objects in a different scenario using a for loop so how I can achieve that without using the for loop how can I imply that in my scenario here ?
I tried every other method of calling the pk even by
pk=patients.pk
pk=pk
I've been stuck on this for over 10 days now asking here and on forums so any help is really appreciated,I'm really desperate.Thanks.
Short version: Creating dynamically multiple formsets only saves as much formsets specified in extra attribute instead of as many as I've.
Long version: I'm doing my first project with Django and I've to create a CreateView with a Parent and a Child forms. I need to create as many nested Child forms the user wants, so I've created a small code in Javascript that adds/removes the child forms. This is working fine.
The problem is: I can only save as many forms as I've specified in the extra attribute. If I say '3', it creates 3 Child forms and I can save 3 of them, even if I create/remove Child forms. If I say '1', I can create 10, but only will save 1. Seems like I'm missing something in the template, but I don't know what. Here's the relevant code:
forms.py
class ParentForm(ModelForm):
class Meta:
model = Parent
exclude = ()
class ChildForm(ModelForm):
class Meta:
model = Child
fields = ....
ChildFormSet = inlineformset_factory(Parent, Child, form=ChildForm, can_delete=True, extra=1)
views.py
class ParentCreateView(LoginRequiredMixin, CreateView):
model = Entrada
fields = ...
def get_context_data(self, **kwargs):
data = super(ParentCreateView, self).get_context_data(**kwargs)
if self.request.POST:
data['child_form'] = ChildFormSet(self.request.POST)
data['materials'] = Material.objects.all()
else:
data['child_form'] = ChildFormSet()
data['materials'] = Material.objects.all()
return data
def form_valid(self, form):
context = self.get_context_data()
child_form = context['child_form']
with transaction.atomic():
self.object = form.save()
if child_form.is_valid():
child_form.instance = self.object
child_form.field1 = self.object.id
child_form.save()
return super(ParentCreateView, self).form_valid(form)
template.html
<form class="own-form" action="" method="post">
{% csrf_token %}
{% for hidden_field in form.hidden_fields %}
{{ hidden_field }}
{% endfor %}
<h2 class="text-center text-header"> New Entry</h2>
<div class="form-group">
{% for field in form.visible_fields %}
<div class="form-group row">
<div class="col-4 text-center">{{ field.label_tag }}</div>
<div class="col-8">{{ field }}</div>
{% if field.help_text %}
<small class="form-text text-muted">{{ field.help_text }}</small>
{% endif %}
</div>
{% endfor %}
</div>
<hr>
<div class="form-group form-material-box row form-0">
<div class="col-3 text-center">
<label>Total weight: </label>
<input type="number" id="kg_0">
</div>
<div class="col-3 text-center">
<label>Boxes to create: </label>
<input type="number" id="num_boxes_0">
</div>
<div class="col-3 text-center">
<label>Material: </label>
<br>
<select name="item_id" id="material_0">
{% for material in materials %}
<option value="{{ forloop.counter }}">{{ material }}</option>
{% endfor %}
</select>
</div>
<div class="col-3 text-center">
<button type="button" id="create_boxes_0" class="btn btn-danger">Create</button>
</div>
<!-- Nested forms with desired number of boxes -->
<div id="nested_forms_0">
<div class="row" id="box_0">
{% for bala in bala_form %}
<div class="col-3 text-center">
<h5>Bala #1: </h4>
</div>
<div class="col-2 text-center">
{{ bala.kg }}
</div>
<div class="col-2 text-center" >
{{ bala.material }}
</div>
<div class="col-2 text-center" >
{{ bala.box_price }}
</div>
<div class="col-3 text-center">
<button type="button" id='remove_box_0' class="btn btn-danger">Remove box</button>
</div>
{% endfor %}
</div>
</div>
</div>
<p>
{{ child_form.management_form }}
<input id="create" class="btn btn-secondary btn-lg btn-block btn-option btn-form" type="submit" value="Crear" />
</p>
Edit:
javascript relevant code
// Adds the difference between desired boxes and current boxes
function add_boxes(form_id, total, num){
for (let i = total; i != total+num; i++) {
var element = $('#nested_forms_' + form_id + "> :first-child ").clone().css('display', 'none');
element.appendTo('#nested_forms_' + form_id).show('250');
};
$('#id_child-TOTAL_FORMS').val(num + total);
};
// Removes every unneeded boxes
function remove_boxes(form_id, total){
$('#nested_forms_' + form_id).children().each(function(){
if ($(this).index() >= total) {
$(this).fadeTo(150, 0).slideUp(150, function(){
$(this).remove();
});
}
});
$('#id_child-TOTAL_FORMS').val(total);
}
What I'm missing?
Update
I've printed the information passed to Django from the template. Seems like its just getting the empty form without any value when I'm creating more than extra forms. Comparing the diffs when I'm creating 3 forms dynamically (left) and hardcoding 3 as the extra value (right) shows it (bales-materies-primeres is the name of the Child):
https://www.diffchecker.com/XskfB9y3
Your Javascript needs to modify the value of the form-TOTAL_FORMS field in the management form. See the formsets documentation.
i am having a form with only checkboxes:
<div class="container">
<form method="GET" class="form-inline" action="">
<div>
{% for temp in instance.menu_positions_tags.all %}
<label class="checkbox-inline">
<input type="checkbox" name="tags[]" value="{{ temp.name}}">{{ temp.name }}
</label>
{% endfor %}
</div>
<div style="margin-top:10px">
<button type="submit" class="btn btn-default">Submit</button>
</div>
</form>
</div>
When i select few checkboxes and submit the url changes to localhost/test/?tags[]=day4&tags[]=day2. After the page loads the all checkboxes are unselected.
Now, how to, in my form make day4 and day2 checkboxes checked.
If you have checkboxes in your form file you can just render it from the form when you receive the GET request. And I think your form type should be POST.
I am using bootstrap to display my django forms but am having trouble getting them to resize. One of the forms is a text input area and I want it to span most of my panel width. I've tried multiple things but haven't been able to resize it/make the input area bigger.
The html:
<div class="container-fluid">
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="text-center">
Raw sQL Query
</h4>
</div>
<form action="/InterfaceApp/table_search/" method="post" class="form">
{% csrf_token %}
<div class="panel-body text-center">
{% bootstrap_form rawsQL %}
</br>
<div class="container-fluid">
<button type="submit" class="btn btn-primary center-block" value="Submit" name="rawsQL">
{% bootstrap_icon "fire" %} Submit
</button>
</div>
</div>
</form>
</div>
The form:
class TextFieldForm(forms.Form):
def __init__(self,*args,**kwargs):
section_label = kwargs.pop('section_label')
initial_value = kwargs.pop('initial_value')
required_val = kwargs.pop('required')
super(TextFieldForm,self).__init__(*args,**kwargs)
self.fields['text'].label=mark_safe(section_label)
self.fields['text'].initial=initial_value
self.fields['text'].required=required_val
text = forms.CharField()
Right now it looks like this:
Can anyone help me with making the input area wider??
Have a look at grid system and form control sizing.
So it turns out that when you pass in forms to django templates like {% bootstrap_form formname %} you have to go into where you defined the form to edit how it looks. I fixed my resizing issue by doing:
Form:
class TextFieldForm(forms.Form):
def __init__(self,*args,**kwargs):
section_label = kwargs.pop('section_label')
initial_value = kwargs.pop('initial_value')
required_val = kwargs.pop('required')
super(TextFieldForm,self).__init__(*args,**kwargs)
self.fields['text'].label=mark_safe(section_label)
self.fields['text'].initial=initial_value
self.fields['text'].required=required_val
text = forms.CharField(widget=forms.TextInput(attrs={'class':"form-control text-center",'placeholder':".col-md-8"}))
html:
<div class="col-md-8 centering">
{% bootstrap_form rawsQL %}
</div>