show form data in template - django

In my application,i am keeping some choices in forms.The choices are check box input and user can click and save the choices.In database saved choice are stored as integer like 1,2,3.How to query the saved value from database and show it in template as their corresponding options.
forms.py
OPTIONS = (
('1', 'Today'),
('2', 'This Week'),
('3', 'This Month'),
('4', 'This Year'),
('5', 'All'),
)
class ReporForm(forms.ModelForm):
optons = forms.ChoiceField(widget=forms.Select(), choices=OPTIONS,required=False, initial=0)
template
{{ reportform.as_p}}
Here,if user selected "This week" as their option,then in database the value of "This week" "2" will be saved.
In usual if i query the data from table,it is rendering the value as "2".But i want it to display "This week" in template.I don't see any tutorial or blog in this way.
I don't know how to do this in Django.

In order to retrieve the value of your dictionary in django, you can use the following syntax:
ReporForm.get_optons_display()
So for example, if you wanted to check if the database query was 'All' or the key '5' you could simply do:
if ReporForm.get_optons_display() == 'ALL':
#do something
Django Docs
An excerpt for an example:
Views.py
#Query your database to retrieve your instance of 'ReporForm'
#I will assume there is a primary key of some type (Reportcode)
foo = ReporForm.objects.get(ReportCode = 1234)
#Pass foo to the context
context = {'foo':foo}
#Send this context to your render_to_response so it goes to template
reportform.html
<b>You have selected the option :</b> '{{ foo.get_optons_display }}'

Related

Coreapi field showing wrong name(data) in swagger

I'm implementing the schema fields by using the method get_schema_fields in DRF. On the swagger UI for the form field instead of the name which ["metrics"] I have given it is displaying the data as the name. Also the model example is also not coming.
This is the code
def get_schema_fields(self, view):
return [
coreapi.Field(
name='metrics',
location='form',
required=True,
schema=coreschema.Object(),
description='metrics type',
),
How can rename that field name from data to metrics also how to display the model sample?
I'm not sure why you want to change data to metrics, all I know is you can add or remove fields in the "Example Value" or "Model" using get_manual_fields or get_serializer_fields, here there is an example:
def get_serializer_fields(self, path, method):
fields = []
if path == 'my_path' and method == 'PUT':
fields = [coreapi.Field(
"custom_field",
required=True,
location="",
schema=coreschema.String()
)]
return fields
Here more documentation:
http://www.django-rest-framework.org/api-guide/schemas/#get_serializer_fieldsself-path-method

Django testing a form is valid when it contains a ModelChoiceField

I have the following test...
def test_contact_form(self):
form_data = {'name': 'Reiss Johnson',
'email': 'reissjohnson#test.com',
'_type': 'General Enquiry',
'content': 'This is some content'}
form = ContactForm(data=form_data)
self.assertTrue(form.is_valid())
This was originally passing as '_type' was a CharField, however it is now a ModelChoiceField & so does anybody know why this is failing? Im guessing im inputting the '_type' into the dictionary incorrectly now?
How could I get the above test to pass again?
My form is as so...
class ContactForm(forms.Form):
name = forms.CharField(max_length=50)
email = forms.EmailField()
content = forms.CharField()
_type = forms.ModelChoiceField(queryset=EnquiryType.objects.values_list('text', flat=True), empty_label=None)
I had the same issue.
To expand on Shang's answer:
Yes, it looks like using the primary key of the model you're referencing will work.
Here's what I did:
valid_pk = NameOfModel.objects.all()[0].pk
# You may need to replace 0 with the right number.
form_data = {'name': 'Reiss Johnson',
'email': 'reissjohnson#test.com',
'_type': str(valid_pk),
'content': 'This is some content'}
I think the problem is that you didn't understand what does ModelChoiceField do. It would generate a list of id(which is the Primary Key for that model) that corresponds to each object that the model has, so when you save, it saves the id as foreign key. You can't feed the form field with a text, which is only a field of model EnquiryType. Think about it, if you don't refer to the primary key of another table but .text, which object should the ModelChoiceField select? What if you create another object that has the same text?
The easy fix would change your test data with the id of the object that has General Enquiry as .text.

Django get derived form CHOICES in templates

Hi I have a Django form:
BAR_CHOICES = (
('1', 'Cheers'),
('2', 'The Blue Oyster'),
...
)
class ProjectInfoForm(forms.Form):
foo = forms.ChoiceField(
CHOICES = BAR_CHOICES,
)
...
of course when I save this data to a model the values are stored as integers in the db. Now, when I grab these values from the saved data they are integers. What is the best approach for getting the choice strings they are associated with. Should I import the BAR_CHOICES into the template?
Django provides a way to directly fetch the related string. Take a look here
Update:
Example:
BAR_CHOICES = (
('1', 'Cheers'),
('2', 'The Blue Oyster'),
...
)
class Project(models.Model):
foo = models.PositiveIntegerField(choices=BAR_CHOICES)
...
In the template you could simply do {{project.get_foo_display}}
If you want to render the choices in a template, you can iterate over form.field.choices.
If you want the string representation of a selected value in the template, you're going to have to write something in your view or form that can get you that information.
You could emulate get_FOO_display in your form..
def get_foo_display(self):
return dict(BAR_CHOICES)[self.foo]

Django set form initial data in view

I'm trying to populate a django modelform with initial data provided from an external source. To achieve that I start by pull all the needed data from the external source:
url =('http://myapi.example.com')
data = urllib2.urlopen(url)
result = json.load(data)
api_data_name = result['properties']['name']
api_data_type = result['properties']['type']
Followed by populating a dict which will serve as initial data to my form:
data = {}
for field in my_model._meta.fields:
if field.name == 'name':
data[field.name] = api_data_name
form = MyEditForm(initial=data)
Then I'm passing the form to the template and the initial data is populating my text fields as expected, but now I need to be able to set a value of a select field based on a string I receive from my external source and Im not getting how can I achieve that, since doing something like:
if field.name == 'type':
data[field.name] = api_data_type
Wont do the job cause the select element has "0", "1", "2", etc as options value and not the long description i get from api_data_type variable.
How can I get the long_description from all the options <option value="1">long_description</option> of my select field in my view so i can compare each one with api_data_type?
Heres a sample of my models.py and forms.py:
#models.py
TYPE = (
('0',_(u'Type1')),
('1',_(u'Type2')),
('2',_(u'Type3')),
)
class MyModel(models.Model):
...
type=models.CharField(max_length=30,choices=TYPE,blank=True)
...
#forms.py
class MyEditForm(forms.ModelForm):
class Meta:
model = MyModel
widgets = {
...
'type': Select(attrs={'class':'select-small span2'}),
...
}
Found out how to accomplish what I asked.
# For select fields
if field.name == 'classification':
for choice in field.choices:
if choice[1].lower() == api_poi_classification.lower():
data[field.name] = choice[0]
And for any of ya trying to populate many-to-many fields (as checkboxes in my case)
# Many to many fields populate
for field in hotel_poi._meta.many_to_many:
if field.name == 'views':
if u'Vista' in api_poi_review_fields:
api_vistas = api_poi_review[u'Vista']
# The api_vistas string comes from api in the format (v1; v2; v3; v4)
views = api_vistas.split(';')
choices = field.get_choices()
temp = []
for view in views:
for choice in choices:
if view.lower().strip() == choice[1].lower().strip():
temp.append(choice[0])
data[field.name]=temp
All of this could be avoided if I had direct database access... In that case i would just need to set an object instance like m = MyModel.objects.filter(id=1) and call form = MyEditForm(instance=m)
But that was not the case and that's what makes this question a bit particular.

django admin filters cascading

I've got a question - can Django Admin interface be customized in such a way, that it presents only those filter options that occur in the subset of data matching currently selected filters?
Say I have a db of three objects:
a.Foo = "One"
a.Bar = "Drink"
b.Foo = "One"
b.Bar = "Shot"
c.Foo = "Two"
c.Bar = "Shot"
And a django admin interface with filters on 'Foo' and 'Bar'. I want the following behavior:
If no filters are chosen, 'Foo' lists "One","Two"; 'Bar' lists "Drink", "Shot"
If 'Foo' filter is set to "One", 'Bar' lists both "Drink" and "Shot"
If 'Foo' filter is set to "Two", 'Bar' lists only "Shot"
If 'Bar' filter is set to "Shot", 'Foo' lists both "One" and "Two"
If 'Bar' filter is set to "Drink", 'Foo' lists only "One"
Cheers!
To be more specific - after reading some docs:
from django.contrib.admin import SimpleListFilter
class SomeFilter(SimpleListFilter):
title = "Foo"
parameter_name="Some"
def lookups(self, request, model_admin):
qs = model_admin.queryset(request)
print qs.query
return (('Foo', 'Bar'))
def queryset(self, request, queryset):
if (self.value()):
return queryset.filter(Some=self.value())
else:
return queryset
What it does, however, is gets the 'queryset' as it would've been without other filters. How can I pass it through other filters?
I could theoretically parse the request and filter manually - but there surely needs to be a way to pipe all filters.
This kind of dynamic filtering really looks like faceting. While you may be able to achieve this result with a standard queryset, this will probably not be optimal. You may have more chance using a dedicated tool, like Solr.
Haystack has also a doc page on faceting.
in case anyone needs a lightweight solution, this one does a Country filter that is hidden when no Continent is selected in the filter and only offers those countries that exist in the selected Continent:
from django.utils.translation import ugettext_lazy as _
class ContinentCountryListFilter(admin.SimpleListFilter):
# Human-readable title which will be displayed in the
# right admin sidebar just above the filter options.
title = _('country')
# Parameter for the filter that will be used in the URL query.
parameter_name = 'country__iso_code__exact'
def lookups(self, request, model_admin):
"""
Returns a list of tuples. The first element in each
tuple is the coded value for the option that will
appear in the URL query. The second element is the
human-readable name for the option that will appear
in the right sidebar.
"""
continent = request.GET.get('country__continent__iso_code__exact', '')
if continent:
countries = models.Country.objects.filter(continent__iso_code__exact=continent)
else:
countries = models.Country.objects.none()
return countries.values_list('iso_code', 'name')
def queryset(self, request, queryset):
"""
Returns the filtered queryset based on the value
provided in the query string and retrievable via
`self.value()`.
"""
continent = request.GET.get('country__continent__iso_code__exact', '')
# only apply filter if continent is set and country exists in continent
if continent and models.Country.objects.filter(continent__iso_code__exact=continent, iso_code__exact=self.value()).count():
return queryset.filter(country__iso_code__exact=self.value())
return queryset
and then apply with:
list_filter = ('country__continent', ContinentCountryListFilter, )