Django dropdown is not populated - python

I want my dropdown to get populated with values from one of my db tables in my Django project, yet it remains blank and I can't figure out why.
This is my html code of my home.html page:
<select name="regions" id="regions">
{% for item in regions_list %}
<option val="{{ item.name_reg }}"> {{ item.name_reg }} </option>
{% endfor %}
</select>
models.py:
class data_reg(models.Model):
id = models.AutoField(primary_key=True)
name_reg = models.TextField(db_column='NAME_REG', blank=True, null=True)
class Meta:
managed = True
db_table = 'reg'
views.py:
def MyView(request):
regions_list = RegionChoiceField()
query_results_dict = {
'regions_list': regions_list,
}
return render(request,'home.html', query_results_dict)
forms.py:
class RegionChoiceField(forms.Form):
regions = forms.ModelChoiceField(
queryset=data_immo.objects.values_list("name_reg", flat=True).distinct(),
empty_label=None
)

when passing ModelChoiceField to context I think the template should be different.
{% for item in regions_list %}
<option val="{{ item.name_reg }}"> {{ item.name_reg }} </option>
{% endfor %}
change to
{% for item in regions_list %}
{{ item }}
{% endfor %}
or even simpler, just put your form in the template
{{regions_list}}
Hope this works,
Greeting
Ken

I just tested this and it seems to work for me.
Can you print the query in your forms.py
print(data_immo.objects.values_list("name_reg", flat=True).distinct())
This will show the query set in your terminal:
<QuerySet ['a_value']>
I find it always good to print at various levels for debugging, fast and easy.

I managed to make it work and did it by avoiding using forms.py. I simply generated my 'regions_list' variable directly in views.py and only after that it managed to get properly recognized. So this is how it finally looked like:
def MyView(request):
regions_list = data_immo.objects.values_list("name_reg", flat=True).distinct()
query_results_dict = {
'regions_list': regions_list,
}
return render(request,'home.html', query_results_dict)
Also, I amended my html code slightly, as per Ken's suggestion:
<select name="regions" id="regions">
{% for item in regions_list %}
<option val="{{ item.name_reg }}"> {{ item}} </option>
{% endfor %}
</select>

Related

How to get Option field value in Request in Django?

I am trying to update my foem, and I have Country value in dropdown and I want to get this value in request, so that i can update my form using this value in request, Please check my code and let me know where I am mistaking.
Here is my test.html file...
<select name='country'>
<option>Select One</option>
{% for countries in country %}
<option value="{{country.id}}" {% if countries.id == datas.country_id %}selected{% endif
%}>{{countries.country}}</option>
{% endfor %}
</select>
here is my views.py file...
datas = MyModelName.objects.get(pk=id)
if request.method == "POST"
datas.country = request.POST.get('country')
datas.save()
it's not selecting the country, it's giving me error, Please guide me how i can solve this issue.
you better use ModelForm to edit data in your models, it allows you to check all entered values in more clean way
create ModelForm to edit your data
class MyModelNameEditForm(forms.ModelForm):
class Meta:
model = MyModelName
then in your views.py you can do this:
datas = MyModelName.objects.get(pk=id)
if request.POST:
edit_form = MyModelNameEditForm(request.POST, instance=datas)
if edit_form.is_valid():
edit_form.check()
else:
edit_form = MyModelNameEditForm(instance=datas)
# don't forget to send your form as a parameter to your template
return render(request, "path_to_template/test.html", {'edit_form': edit_form})
then in your test.html you can replace:
<select name='country'>
<option>Select One</option>
{% for countries in country %}
<option value="{{country.id}}" {% if countries.id == datas.country_id %}selected{% endif
%}>{{countries.country}}</option>
{% endfor %}
</select>
with one line
{{ edit_form.country }}
you can read more about ModelForm in official docs https://docs.djangoproject.com/en/3.1/topics/forms/modelforms/#modelform

Django Populate Dropdown Menu With Choices From Many To Many Database

I would like to populate my dropdown menu with records from the Subject table which is a many to many choices field that is populated with subjects by adding them manually from the admin page. A course can have many subjects such as "business" and "marketing".
Code:
https://dpaste.de/825n
How would I do that with django-select2 or use a form with model select or multiple model select?
https://docs.djangoproject.com/en/2.2/ref/forms/fields/#modelchoicefield
https://docs.djangoproject.com/en/2.2/ref/forms/fields/#modelmultiplechoicefield
https://django-select2.readthedocs.io/en/latest/
Or maybe I could do it with a for loop on the template?
For loops I have tried but no luck:
https://dpaste.de/5MVi
Desired Result:
https://imgur.com/a/Iw9lk6I
Can someone please help me figure it out? I have been stuck for a while now.
here hope this helps your missing the .all() on while querying the many to many fields. you're also not going deep enough to the actual name of the many to many fields so you're trying to print the object on your loop.
example view:
def tester(request):
tes = Test.objects.get(id=1)
testlist = tes.category.all()
context = {
'test': testlist,
}
return render(request, 'core/t.html', context)
example loop:
{% for item in test %}
<p>- {{item.cat}}</p>
{% endfor %}
example model:
class cats(models.Model):
cat = models.CharField(max_length=10,)
class Test(models.Model):
name = models.CharField(max_length=10,)
category = models.ManyToManyField(cats)
nested loop example:
{% for item in item_list %}
<h2>{{ item.name }}</h2>
<ul>
{% for sub in item.subjects.all %}
<li>{{ sub.name }}</li>
{% endfor %}
</ul>
{% endfor %}
After creating your model form you can use something like this to get a dropdown
class CourseForm(forms.ModelForm):
subjects = forms.ModelMultipleChoiceField(
queryset=Subject.objects.all(),
required=True,
)
class Meta:
model = Course
fields = [......, subjects]
or you can use the other widget, widget=forms.CheckboxSelectMultiple,depending on your requirement
<form method="post" action="">
<div>
{% csrf_token %}
{{ form }}
<input type="submit" class="btn btn-primary" id="submit" value="Save">
</div>
</form>
Add a create view to create a course something like below
class CourseCreateView(CreateView):
model = Course
form_class = CourseForm
template_name = 'course_form.html'
success_url = reverse_lazy('/')

Mongoengine, Flask and ReferenceField in WTForms

Hy everybody,
I'm realizing a Flask/MongoDB project and since I am new to this world, I've followed the tutorial at this page:
http://docs.mongodb.org/ecosystem/tutorial/write-a-tumblelog-application-with-flask-mongoengine/
After that, I've started to code my own application and this is part of the code:
MODELS:
class Generic(db.Document):
descrizione = db.StringField(max_length=255, required=True)
meta = {
'allow_inheritance': True,
'indexes': [
{'fields': ['descrizione'], 'unique': True}
]
}
class Category(Generic):
def __call__(self, *args):
pass
class User(db.Document):
email = db.EmailField(max_length=255, required=True)
nickname = db.StringField(max_length=255, required=True)
password = db.StringField(max_length=16, required=True)
categoria = db.ReferenceField('Category', required=True)
meta = {
'indexes': [
{'fields': ['nickname', 'email'], 'unique': True}
]
}
As you can see above, I've a "Category" class which inherits the "Generic" class. The "User" class finally has a ReferenceField to the Category. This way when I create a user, the category field on mongo db is stored as an ObjectID, related to the "generic" collection which has all the categories I've created.
The next step is to create the form to insert new documents into the user collection.
In my Views python file I've this cose:
def iscrizione():
form = model_form(User, only=['email', 'nickname', 'password', 'categoria'])(request.form)
if request.method == 'GET':
ctx = {
'form': form
}
return render_template('users/iscrizione.html', **ctx)
The template uses the Jinja macro reported in the tutorial page:
{% macro render(form) -%}
<fieldset>
{% for field in form %}
{% if field.type in ['CSRFTokenField', 'HiddenField'] %}
{{ field() }}
{% else %}
<div class="clearfix {% if field.errors %}error{% endif %}">
{{ field.label }}
<div class="input">
{% if field.name == "body" %}
{{ field(rows=10, cols=40) }}
{% else %}
{{ field() }}
{% endif %}
{% if field.errors or field.help_text %}
<span class="help-inline">
{% if field.errors %}
{{ field.errors|join(' ') }}
{% else %}
{{ field.help_text }}
{% endif %}
</span>
{% endif %}
</div>
</div>
{% endif %}
{% endfor %}
</fieldset>
{% endmacro %}
And finally, this is my problem
(If you have reached this text, you are my hero)
When I visit the webpage with the rendered form, the macro correctly show the text fields, and for the ReferenceField in my model it show a combo box.
The options values in the select combo are perfectly aligned with the object id of the category documents I've created. Choosing one of these and submitting the form, my application correctly creates the new user document.
Unfortunately, the select box labels doesn't show a human readable value, reporting "Category object".
<select id="categoria" name="categoria">
<option value="530536363c74031c24ee7ab6">Category object</option>
<option value="5305362d3c74031c24ee7ab5">Category object</option>
<option value="530535793c74031b73dd07b4">Category object</option>
</select>
How can I manage to show a correct label for the select box?
Finally I've made it!
Suppose that the field "categoria" of the User document is a ReferenceField to the "Category" collection.
Just add the "label_attr" attribute to "form.categoria" using the field name of the Category model that you want as label.
def iscrizione():
form = model_form(User, only=['email', 'nickname', 'password', 'categoria'])(request.form)
form.categoria.label_attr='descrizione' #<< add this line
if request.method == 'GET':
ctx = {
'form': form
}
return render_template('users/iscrizione.html', **ctx)
This can also be made through the field args in the model_form function:
form = model_form(
User,
only=['email', 'nickname', 'password', 'categoria'],
field_args={'categoria': {'label_attr': 'descrizione'}}
)
Maybe its will be useful to someone. You can use standard approach, like define
def __str__(self):
return self.descrizione
for your Category class

Django - ModelChoiceField empty choice missing

Django docs say when using ModelChoiceField on a form and form is set to required=False and model is set to blank=True in addition to no default values, then I should receive a free empty choice within my select tag. I am not. Any ideas to what I've done to lose the empty choice?
models.py
class Location(models.Model):
location_name = models.CharField(max_length=50, blank=True)
address = models.CharField(max_length=50)
active = models.BooleanField(default=True)
def __unicode__(self):
return self.location_name
forms.py
class CalcForm(forms.Form):
startAddr = forms.ModelChoiceField(queryset=Location.objects.all(), required=False)
waypoint1 = forms.ModelChoiceField(queryset=Location.objects.all(), required=False)
waypoint2 = forms.ModelChoiceField(queryset=Location.objects.all(), required=False)
...
endAddr = forms.ModelChoiceField(queryset=Location.objects.all(), required=False)
template.html
<form action="../calcview" method="get">{% csrf_token% }
<label>
<div>Start Address</div>
<select name="startAddr">
{% for location in form.fields.startAddr.queryset %}
<option value = "{ location.location_name }">{{location.location_name}}/option>
{% end for %}
</select>
...
</form>
You will only get the 'free' empty option if you allow django forms to render the form field automatically. Because you are rendering it yourself in your template (and I don't know why you would want to do that...) you would need to add the empty select yourself:
<select name="startAddr">
<option value="">-----------</option>
{% for location in form.fields.startAddr.queryset %}
<option value = "{ location.location_name }">{{location.location_name}}</option>
{% end for %}
</select>
You can test this by allowing django form to render it for you:
<div>Start Address</div>
{{ form.startAddr }}
You can use the empty_label on your ModelChoiceField.
startAddr = forms.ModelChoiceField(empty_label='---------', queryset=Location.objects.all(), required=False)
Then render the form field into the template.
{{ form.startAddr }}
https://docs.djangoproject.com/en/2.1/ref/forms/fields/#django.forms.ModelChoiceField.empty_label
I know, you asked more than half a year ago, but I thought I post another answer anyway. Because I think there is a more elegant solution that uses the "empty_label" that you can define in your form.
You can access this empty_label attribute through form.fields.startAddr.empty_label or form.startAddr.field.empty_label in your template. So you can include it like this:
<select id="{{ form.fields.startAddr.id_for_label }}" name="{{ form.fields.startAddr.html_name }}">
<option value="">{{ form.fields.startAddr.empty_label }}</option>
{% for location in form.fields.startAddr.queryset %}
<option value="{{ location.location_name }}">{{ location.location_name }}/option>
{% endfor %}
</select>
I wonder if you did not actually want to use {{ location.id }} as value? Or is the location_name unique? As it could even be empty, the auto-generated id might be better as a reference.
As you can see, I have also replaced name="startAddr" with information the form object provides anyway for every field: id="{{ form.fields.startAddr.id_for_label }}" name="{{ form.fields.startAddr.html_name }}. Using these variables should make your template code more flexible and robust.
For more details, please check the Django documentation:
ModelChoiceField: https://docs.djangoproject.com/en/dev/ref/forms/fields/#modelchoicefield
Automatic primary key field: https://docs.djangoproject.com/en/dev/topics/db/models/#automatic-primary-key-fields

WTForms display foreignkey fields' name in dropdown

I am using appengine webapp2 as wsgihandler, jinja2 as the template engine and wtforms as the form module for its support to app engine models.
Following is my simple model:
class TaskCategory(db.Model):
title = db.StringProperty()
description = db.TextProperty()
class TaskList(db.Model):
title = db.StringProperty()
description = db.TextProperty()
category = db.ReferenceProperty(TaskCategory)
start_date = db.DateProperty()
target_finish_date = db.DateProperty()
Inside my handlers i write stuff as follows:
from wtforms.ext.appengine.db import model_form
model_dict = {'category': TaskCategory,
'task': TaskList}
class CreateForm(webapp2.RequestHandler):
def get(self, slug):
form = model_form(model_dict[slug]) # slug can either be category or task.
self.render_template('index.html', {'form': form()})
Following is my template:
<form method="POST" action"">
<table>
{% for field in form %}
<tr>{{ field.label }}</tr>
<tr>{{ field()|safe }}</tr>
<tr>
{% if field.errors %}
<td>
<ul class=errors>
{% for error in field.errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
</td>
{% endif %}
{% endfor %}
</table>
<input type="submit" class="btn" value="Submit Form"/>
</form>
Everything renders perfectly in the template, except the dropdown for the foreign key the values listed over there are something like:
<tr><label for="category">Category</label></tr>
<tr><select id="category" name="category"><option selected value="__None"></option><option value="ahhkZXZ-bmV3LXByb2plY3QtdGVtcGxhdGVyEgsSDFRhc2tDYXRlZ29yeRgCDA"><models.TaskCategory object at 0xb22d74c></option>
<option value="ahhkZXZ-bmV3LXByb2plY3QtdGVtcGxhdGVyEgsSDFRhc2tDYXRlZ29yeRgDDA"><models.TaskCategory object at 0xb22dbec></option>
<option value="ahhkZXZ-bmV3LXByb2plY3QtdGVtcGxhdGVyFgsSDFRhc2tDYXRlZ29yeSIEdGVzdAw"><models.TaskCategory object at 0xb22d74c></option></select></tr>
As is visible the names are not being displayed for the category, instead the objects are displayed, how can i rectify it, in a generic manner?
Well this has got nothing to do with, WTForm or jinja or webapp2.
Change your database file to return the title in your case, instead of the object using repr as follows:
class TaskCategory(db.Model):
title = db.StringProperty()
description = db.TextProperty()
def __repr__(self):
return unicode(self.title)

Categories

Resources