initial value for django form choice field ignored - django

I have this form:
class UserUsesSourceForm(forms.Form):
# some fields here
username = forms.CharField(label=("Username"), max_length=30, help_text = ("Required"))
provider = forms.ChoiceField(widget=forms.Select(), choices=SOURCES_CHOICES, initial=SOURCES_CHOICES[1])
The available choices are:
E = 'e'
A = 'a'
SOURCES_CHOICES = (
(A, 'A'),
(E, 'E'),
)
The view:
form = UserUsesSourceForm(initial={"username":request.user.username, 'provider':SOURCES_CHOICES[1]})return render_to_response('update_datasource.html', context_instance=RequestContext(request, params))
And the template:
<form action="" method="post">
{% csrf_token %}
{% if form.non_field_errors %}
<p>
{% for error in form.non_field_errors %}
<div class="text-error">{{ error|escape }}</div>
{% endfor %}
</p>
{% endif %}
<div class="control-group">
<label class="control-label" for="id_provider">Data source</label>
<div class="controls">
{{form.provider}}
</div>
</div>
</form>
The problem is that even if the initial value is correctly set, and I can test it in debug (i.e., the form "provider" field initial value is the tuple I want), the final html always show the first element in the select box:
<select name="provider" id="id_provider">
<option value="A">A</option>
<option value="E">E</option>
</select>
..while I'd expect it to have a "default" or "active" option.
Please note that the username field is correctly initialized.
How can I investigate further to find out where the problem is?

You need to pass the option value instead of tuple in initial data:
form = UserUsesSourceForm(
initial={'username':request.user.username,
'provider':SOURCES_CHOICES[1][0]})

Related

Django checkbox for filter

Im having some problem when I want to keep a checkbox checked. When I send the form all the checkbox are checked. so idk how to change the if statement for that :(
<div class="form-group">
<label >Marca</label>
{% for brand in q %}
<div class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" id="{{brand.brand}}" name="test" value="{{brand.brand}}" {% if marca %} checked="checked" {%endif%}>
<label class="custom-control-label" for="{{brand.brand}}" style="cursor: pointer;">{{brand.brand}}</label>
</div>
{% endfor %}
</div>
And here is the view:
marca = request.GET.get('test')
if marca :
products = products.filter(brand__name__in=request.GET.getlist('test'))
All the other things are fine. It shows me the brands that I choose. So I just want to keep the checkbox that I checked :( and I think the problem is that If statement in the template
Just pass a set of the values in the values to the template:
marca_vals = set(request.GET.getlist('test'))
# …
context = {
'marca_vals': marca_vals,
# …
}
return render(request, 'some_template.html', context)
in the template you can then render it with checked in case the value is in the marca_vals:
<input type="checkbox" {% if brand.brand in marca_vals %}checked{% endif %} class="custom-control-input" id="{{brand.brand}}" name="test" value="{{brand.brand}}">
You might however want to consider using a form, or even django-filters [readthedocs] to both make filtering and rendering the form more convenient.

Django template multiple for loop

I have a tuple which holds multiple color and their codes:
color_list = (
('#CD5C5C', 'Indian Red'),
('#F08080', 'Light Coral'),
('#FA8072', 'Salmon'),
................
)
and this is the model:
class ColorList(models.Model):
color = models.CharField(choices=color_list, max_length=10)
class Product(models.Model):
color_list = models.ManyToManyField(ColorList)
view:
def product_edit(request, pk):
product = get_object_or_404(Product.objects.prefetch_related('color_list'), pk=pk)
context = {'product': product,'color_list': color_list}
return render(request, 'admin/product/product_edit.html', context)
Now I want to edit previously saved data in template using a form:
<div class="form-group">
<label><strong>Color List</strong></label>
<select name="color_list" class="form-control selectpicker" multiple data-live-search="true" >
{% for key, value in color_list %}
{% for pro_color in product.color_list.all %}
<option value="{{ key }}" {% if pro_color.color == key %} selected {% endif %}>
{{ value }}
</option>
{% endfor %}
{% endfor %}
</select>
</div>
I want to show previously selected color with other color options, but using this template code, it generating multiple duplicate <options>. So the problem is how can I use multiple for loop in template with preselected color <options> ?
The reason your colors are duplicating is because you nested two loops unnecessarily to get the key/value pairs. You can use .get_FOO_display() instead.
<div class="form-group">
<label><strong>Color List</strong></label>
<select name="color_list" class="form-control selectpicker" multiple data-live-search="true" >
{% for pro_color in product.color_list.all %}
<option value="{{ pro_color.get_color_display }}" {% if pro_color.color == color_list.color %} selected {% endif %}>
{{ pro_color.color }}
</option>
{% endfor %}
</select>
</div>
https://docs.djangoproject.com/en/dev/ref/models/instances/#django.db.models.Model.get_FOO_display
For Edit Related Issues, Refer Template of Django Admin > Edit User
Probable url will be: http://localhost:8000/admin/auth/user/{id}/change/
Here They Have Permissions column which is Select Many and it ofcause retains its value on refresh too.

Determining of option is initial value in template

I'm manually rendering a modelchoicefield in my form so that I can insert a custom attribute on each option. I'd like to know what template tag I can userto determine if the option is the initial value so that I can set it as the selected option in the dropdown menu on page load.
forms.py
self.fields['formpricing'].choices = ZERO_BLANK_CHOICE + tuple([(t.id, t) for t in FormPricingMethod.objects.filter(industryname=industry)])
self.fields['formpricing'].queryset = FormPricingMethod.objects.filter(industryname=industry)
views.py
formpricing = userprofile.formpricing
form3 = BasisOfPricingForm(request.POST or None, user=user, initial={'formpricing': formpricing})
template
<div class="fieldname">Form Pricing</div>
<div class="fieldvalue">
<select name="formpricing" required="" id="id_formpricing">
{% for value, object in form3.formpricing.field.choices %}
<option typenumber="{{object.typenumber}}" value="{{value}}">
{{object.title}}
</option>
{% endfor %}
</select>
</div>
</div>
Thanks!
Got it.
{% if form3.formpricing.initial.id == value %}selected{% endif %}

In django, how to use another model data from function based views

So I have a form that updates a key_instance object with a borrower. Currently my app needs the user to enter the name of the borrower, but I want it to display a dropdown list of data from another model the user model to select from, is there anyway to do this in a class based view? Here are my views.py and my template. What I was thinking is that I would like to use a get_list_or_404 on the user model and display it as a drop down list in the template and use that selection to populate the form field.
I manged to get the dropdown list to display in my template but I'm not sure as to how to save that value in my views.
Does anyone know if this is the right way or if this is doable? Thank you!!
views.py
def submit_key_request(request, pk):
"""
View function for renewing a specific keyInstance by admin
"""
key_inst=get_object_or_404(KeyInstance, pk=pk)
names = get_list_or_404(Users)
# If this is a POST request then process the Form data
if request.method == 'POST':
# Create a form instance and populate it with data from the request (binding):
form = UpdateKeyForm(request.POST)
# Check if the form is valid:
if form.is_valid():
# process the data in form.cleaned_data as required (here we just write it to the model due_back field)
key_inst.is_requested = True
key_inst.status = 'r'
key_inst.date_requested = datetime.date.today()
key_inst.borrower = form.cleaned_data['borrower']
key_inst.save()
# redirect to a new URL:
return HttpResponseRedirect(reverse('all-available-keys') )
# If this is a GET (or any other method) create the default form.
else:
form = UpdateKeyForm(initial={'borrower': 'N/A'})
return render(request, 'catalog/keyinstance_request_update.html', {'form': form, 'keyinst':key_inst})
template
{% extends "base_generic.html" %}
{% block content %}
<div class="wrapper">
<div class="centered"> <h1>Request Keys For Room: {{keyinst.roomkey}}</h1></div>
<div class="square-box">
<div class="square-content">
<form action="" method="post" >
{% csrf_token %}
<table style="display: inline-flex">
{{ form}}
</table>
<select name = 'name'>
{% for name in names %}
<option value="{{ name }}">{{ name }}</option>
{% endfor %}
</select>
<p>
(Please use their login name i.e. <b>{{ user.get_username }}</b>)
</p>
<p><input required id="checkBox" type="checkbox" onclick="validate()"> I accept the terms and conditions</p>
<p id="text" style="display:none">You Have Agreed To the Terms and Conditions</p>
<input type="submit" value="Submit" />
</form>
</div>
</div>
</div>
{% endblock %}
Here is how I manged to do it, Not sure if this is the best 'pythonic' or best practice. Please let me know if it's not.
my views.py
def submit_key_request(request, pk):
"""
View function for renewing a specific keyInstance by admin
"""
key_inst=get_object_or_404(KeyInstance, pk=pk)
names = get_list_or_404(User)
# If this is a POST request then process the Form data
if request.method == 'POST':
name = request.POST['name']
key_inst.is_requested = True
key_inst.status = 'r'
key_inst.date_requested = datetime.date.today()
key_inst.borrower = name
key_inst.save()
return HttpResponseRedirect(reverse('all-available-keys') )
# If this is a GET (or any other method) create the default form.
else:
pass
return render(request, 'catalog/keyinstance_request_update.html', {'keyinst':key_inst, 'names':names})
template
{% extends "base_generic.html" %}
{% block content %}
<div class="wrapper">
<div class="centered"> <h1>Request Keys For Room: {{keyinst.roomkey}}</h1></div>
<div class="square-box">
<div class="square-content">
<form action="" method="post" >
{% csrf_token %}
</br>
<select name = 'name' required>
{% for key in names %}
<option value="{{ key }}">{{ key }}</option>
{% endfor %}
</select>
<p>
(Please use their login name i.e. <b>{{ user.get_username }}</b>)
</p>
<p><input required id="checkBox" type="checkbox" onclick="validate()"> I accept the terms and conditions</p>
<p id="text" style="display:none">You Have Agreed To the Terms and Conditions</p>
<input type="submit" value="Submit" />
</form>
</div>
</div>
</div>
{% endblock %}

Django - Rendering Model Choices in template when not using Forms or ModelForms

I created a model and one of the fields has choices. I created a select form in my template and the choices are not been displayed. I'm not using Forms or ModelForms for a few reasons. But my understanding is that I should be able to make this work using CHOICES in the model, building a form in the template and save the information using the object manager. How can I get the choices to populate the form?
Models.py
class NewRating(models.Model):
EXCELLENT = 'EX'
GOOD = 'GD'
FAIR = 'FR'
BAD = 'BD'
RATING_CHOICES = (
(EXCELLENT, 'Excellent'),
(GOOD, 'Good'),
(FAIR, 'Fair'),
(BAD, 'Bad')
)
function = models.ForeignKey(Function, related_name='frating')
timeline = models.ForeignKey(Timeline, related_name='trating')
rating = models.CharField(max_length=25,choices=RATING_CHOICES)
Views.py
def f_page(request, Function_id):
assignments = Function.objects.get(id=Function_id)
time = Timeline.objects.all()
ratings = NewRating.objects.all()
context = {
'assignments': assignments,
'time' : time,
'ratings' : ratings,
}
return render (request, 'project/pager.html', context)
HTML
<div id=for_rat>
{% for rated in time %}
<form action= "/project/rated" method='POST'>
{% csrf_token %}
{{rated.segment}}
<input type="hidden" name="year" value="{{rated.year}}">
<input type="hidden" name="month" value= "{{assignments.id}}">
<select name="ratings">
<option value="">Choose From List</option>
{% for rating in ratings %}
<option value="{{rating.choices}}">{{rating.choices}}</option>
{% endfor %}
</select>
{% endfor %}
<input type="submit" value="Save">
</form>
</div>
Using {% for rating in ratings %}
{{rating.choices}}
{% endfor %} is not working. Can I set the choices in the models if I'm building my own forms? If yes, what am I doing wrong that this is not rendering?
Easiest, simplest and the 100% working method is:
Get the objects [lets say 'my_Model_with_choices'] with my_Model_with_choices = yourModel.objects.first() and you can get the choices with my_Model_with_choices._meta.get_field('your_foreign_key_variable_name').choices
def f_page(request, Function_id):
assignments = Function.objects.get(id=Function_id)
ratings = NewRating.RATING_CHOICES
context = {
'ratings' : ratings,
}
return render (request, 'project/pager.html', context)
Inside HTML template:
<select class="custom-select col-md-5" name="ratings" id="ratings" required>
<option disabled selected value="">Ethnic Group</option>
{% for value, ratings_group in ratings %}
<option value='{{value}}'>{{ratings_group}}</option>
{% endfor %}
</select>
If you're strictly not willing to use Form or ModelForm, you need to have choices to be iterable which is possible via enum.
You can check my sample code about how to implement choices with enums here.
You'll have to make some tweaks to your context and template after doing this.
You might want to look how to get the list of choices with enum.
try this
{% for rating in ratings %}
<select name="ratings">
<option value="">Choose From List</option>
{% for x, y in rating._meta.get_field('rating').choices %}
<option value="{{ x }}">{% if rating.rating == x %} selected{% endif %}>
{{ y }}
</option>
{% endfor %}
</select>
{% endfor %}
Make sure that this code is outside the
{% for rated in time %}
...
{% endfor %}
block