Getting error in printing the dictionary values to html - html

I want to print to get the details of different cities weather and I had written the code as below. While retrieving the data, I am not able to fetch the data to HTML.
views.py:
from django.shortcuts import render
# Create your views here.
import urllib.request
import json
import requests
def display(request):
city=['vijayawada','guntur','tenali','rajahmundry','amaravathi']
for i in city:
source = urllib.request.urlopen(
'https://api.openweathermap.org/data/2.5/weather?q=' + i + '&units=metric&appid=5980455dc827c861d5ac4125c3673b43').read()
list_of_data = json.loads(source)
data = {
"country_code": str(list_of_data['sys']['country']),
"coordinate": str(list_of_data['coord']['lon']) + ', '
+ str(list_of_data['coord']['lat']),
"temp": str(list_of_data['main']['temp']) + ' °C',
"pressure": str(list_of_data['main']['pressure']),
"humidity": str(list_of_data['main']['humidity']),
'main': str(list_of_data['weather'][0]['main']),
'description': str(list_of_data['weather'][0]['description']),
'icon': list_of_data['weather'][0]['icon'],
}
print(data)
return render(request, "display.html",data)
display.html:
<html>
<head>
<title>API Display</title>
</head>
<body>
<h1>Weather details</h1>
<form>
{% for i in data %}
{{ country_code }}
{{ temp }}
{{ i }}
{% endfor %}
</form>
</body>
</html>
I am trying to print the values of the dictionary to html but not getting printed. The values are printing correctly in the console which means the for loop in views.py is working correctly.
Please tell me where I am wrong

You might want to make a function that handles the request for each city:
def get_city_weather(city_name):
source = urllib.request.urlopen(
'https://api.openweathermap.org/data/2.5/weather?q=' + city_name + '&units=metric&appid=5980455dc827c861d5ac4125c3673b43').read()
list_of_data = json.loads(source)
return {
"country_code": str(list_of_data['sys']['country']),
"coordinate": str(list_of_data['coord']['lon']) + ', '
+ str(list_of_data['coord']['lat']),
"temp": str(list_of_data['main']['temp']) + ' °C',
"pressure": str(list_of_data['main']['pressure']),
"humidity": str(list_of_data['main']['humidity']),
'main': str(list_of_data['weather'][0]['main']),
'description': str(list_of_data['weather'][0]['description']),
'icon': list_of_data['weather'][0]['icon'],
}
Then use dict comprehension to compile the data dict to send to the template:
def display(request):
cities=['vijayawada','guntur','tenali','rajahmundry','amaravathi']
data = {city_name: get_city_weather(city_name) for city_name in cities}
return render(request, "display.html", data)
At this point data is a dictionary who's key is the city name and who's value is the dictionary returned by get_city_weather, so it looks like (abbreviated):
{'vijayawada':
{'country_code': 'ABC'
# ...
}
# ...
}
Then in the template you could loop through this like:
{% for city_name, city_weather in data.items %}
The temperature in {{city_name}} is {{city_weather.temp}}
and the air pressure is {{city_weather.pressure}}.
{% endfor %}
Or if you don't want to specify the keys like temp and pressure, you could do:
{% for city_name, city_weather in data.items %}
<p>Weather data for {{city_name}}:</p>
<ul>
{% for k,v in city_weather.items %}
<li>{{k}}: {{v}}</li>
{% endfor %}
</ul>
<hr />
{% endfor %}

That is because you are overwriting your data dictionary. It's being passed only as one object, it should render something if you try {{data}} or {{data.country_code}}, {{data.temp}}...
One way to solve this, is to have a nested dictionary with the data of every city:
views.py
def loop_dict(request):
cities=['vijayawada','guntur','tenali','rajahmundry','amaravathi']
data = {}
for city in cities:
source = urllib.request.urlopen(
'https://api.openweathermap.org/data/2.5/weather?q=' + city + '&units=metric&appid=5980455dc827c861d5ac4125c3673b43').read()
list_of_data = json.loads(source)
data[city] = {
"country_code": str(list_of_data['sys']['country']),
"coordinates": {
'latitude': str(list_of_data['coord']['lat']),
'longitude': str(list_of_data['coord']['lon'])
},
"temp": str(list_of_data['main']['temp']) + ' °C',
"pressure": str(list_of_data['main']['pressure']),
"humidity": str(list_of_data['main']['humidity']),
'main': str(list_of_data['weather'][0]['main']),
'description': str(list_of_data['weather'][0]['description']),
'icon': list_of_data['weather'][0]['icon'],
}
context = {'data': data}
return render(request, 'loop_dict.html', context)
loop_dict.html:
{% extends 'base.html' %}
{% block content %}
{% for key, obj in data.items %}
<h2>City: {{key}}</h2><br>
<p>Country Code: {{obj.country_code}}</p><br>
<p>Latitude: {{obj.coordinates.latitude}}</p><br>
<p>Longitude: {{obj.coordinates.longitude}}</p><br>
<p>Temp: {{obj.temp}}</p><br>
<hr>
{% endfor %}
{% endblock %}

AFAIK, django template system recognizes dict variable just like Python itself does.
So, if we try to convert your template code back to Python code, we would get something like this:
for i in data:
print(country_code)
print(temp)
print(i)
Now, ask yourself: will it work?
Obviously, it's not.
So, how exactly in Python you would loop and access dict values?
You can do it like this:
for i in data:
print(i)
Or with k,v loop variables (better way):
for k, v in enumerate(data):
print(f"key: {k}, value: {v}")
But, in your template code, you are trying to access certain values with the key (country_code etc).
In this case, you probably don't even need to use the for-loop.
And your display.html file can be rewritten like this:
<html>
<head>
<title>API Display</title>
</head>
<body>
<h1>Weather details</h1>
<form>
{{ data.country_code }}
{{ data.temp }}
</form>
</body>
</html>
Also, as I can see your view retrieves this data for each given city.
Thought you only pass the last one to your template.
In order to fix this, you must rewrite your view code.
I guess you could add a new variable called collected_data and then at the end of every data retrieve loop just append data to this new variable.
After that, you could just pass the collected_data to the template.
And then loop through it within the template.
But I exactly don't know how your template should look like, so I leave it to you.
I've tried to explain what's the issue is.

Related

Trouble accessing json properties in Jinja2 template

I've searched around but the answers I've found aren't working for some reason.
I'm building a flask web app. I load a csv into a dataframe and display it in a table on a page (index). You can click a button to select a row and the row's details will populate below the table.
Everything works and I can print the json object returned when a row is selected, but can't print any of the properties.
I've tried row.first, row['first'], row.first[0], and other various arrangements.
What am I doing wrong / what is the proper way to interact with json objects in Jinja2?
Json from single row that is correctly returned to the template
{
"seq": {
"0": 1
},
"first": {
"0": "Justin"
},
"last": {
"0": "Powell"
},
"state": {
"0": "ND"
},
"email": {
"0": "idomapsok#bu.ne"
}
}
views.py
from flask import render_template, jsonify
from wsaflask import bp
import pandas as pd
data = pd.read_csv('wsaflask/input.csv')
#bp.route('/update-details/<int:id>', methods = ['POST'])
def update_details(id):
row_details = data.loc[data['seq'] == id]
return jsonify('', render_template('row-details.html', row = row_details.to_json()))
#bp.route('/')
def index():
return render_template('index.html', data = data)
row-details.html
<div id="detail-display">
{% if row %}
<!-- How to print row.first (name) here -->
<p>{{ row }}</p>
{% endif %}
</div>
index.html
<body>
<section class="container">
<div style="max-height: 35vh; overflow-y: scroll;">
<table class="table">
<tr>
{% for col in data.columns %}
<th>{{ col }}</th>
{% endfor %}
<th>
action
</th>
</tr>
{% for _, row in data.iterrows() %}
<tr>
{% for col in data.columns %}
<td>{{ row[col] }}</td>
{% endfor %}
<td>
<button onclick="updateDetails(row_id = {{row['seq']}})" class="btn btn-link btn-sm">Select</button>
</td>
</tr>
{% endfor %}
</table>
</div>
<!-- Div below is replaced with row-details.html via js -->
<div id="detail-display">
</div>
</section>
</body>
Javascript:
function updateDetails(row_id){
var id = row_id
$.ajax({
url:"/update-details/" + id,
type:"POST",
dataType:"json",
success: function(data){
$('#detail-display').replaceWith(data)
}
});
}
Okay I figured it out, #jspcal got me looking in the right direction and I found this post.
In short, Flask's to_json() function returns a json string rather than an actual object, though they look similar.
The view to update the data now looks like this:
import json
#bp.route('/update-details/<int:id>', methods = ['POST'])
def update_details(id):
row_df = data.loc[data['seq'] == id]
row_json = row_df.to_json(orient = 'records')
results = json.loads(row_json)
return jsonify('', render_template('row-details.html', row = results))
First I added the 'orient' parameter. This changes the structure of the resulting json string. See the docs here. It was a bit of a guessing game for me, but here's how the json looks now:
[
{
'seq': 1,
'first': 'Justin',
'last': 'Powell',
'state': 'ND',
'email': 'idomapsok#bu.ne'
}
]
Then after importing json (just import json), load the json string using json.loads(your_json_string), and pass the results to the template instead of just the string.
Now in my template, I can get the first name using row[0].first.
I'm not 100% sure what's happening so I'm sure this isn't the ideal way to handle this, but it gets the job done.

While trying to reverse a url in django template html file, exception 'NoReverseMatch' occurs. I included the additional parameter in views function

def entry(request, name):
content = util.get_entry(name.strip())
if content == None:
content = "## Page was not found"
content = markdown(content)
return render(request, "encyclopedia/entry.html", {'content': content, 'title': name})
def edit(request,title):
content = util.get_entry(title.strip())
if content == None:
return render(request, "encyclopedia/edit.html", {'error': "404 Not Found"})
if request.method == "POST":
content = request.POST.get("content").strip()
if content == "":
return render(request, "encyclopedia/edit.html", {"message": "Can't save with empty field.", "title": title, "content": content})
util.save_entry(title, content)
return redirect("entry", name=title)
return render(request, "encyclopedia/edit.html", {'content': content, 'title': title})
util has files that help get names of entered files, save a new entry or get content of entry.
{% extends 'encyclopedia/layout.html' %}
{% block title %}
{{title}}
{% endblock %}
{% block body %}
Edit This Page
{{entry | safe }}
{% endblock %}
layout has the standard block code of HTML
edit.html contains HTML code that gives a button on each page so that we can edit the content of the page entry and passes name='content' for the content to be edited.
urlpatterns = [
path("", views.index, name="index"),
path("wiki/<str:name>", views.entry, name = 'entry'),
path("search", views.search, name= 'search'),
path("newpage",views.create,name='create'),
path("random",views.random,name='random'),
path("edit", views.edit, name='edit')
]
THIS IS A CS50w project and I have taken references from other sources.
You are passing variable to the url while it doesn't really need any
Just add title parameter to edit path
path("edit/<str:title>/", views.edit, name='edit')
when passing an argument to django view, you have to set it in the url
<type:argument_name>
and in the view arguments
def viewname(request, variable1, variable2...): pass

Why is using jinga template returning data as none on a webpage using flask?

I am trying to print basically a table to display data from a function I have called on flask on a webpage. I looked over Jinga templates and that is what I attempted to use, however to no avail.
My code is attached below. result from my cv_acp file is what I am trying to display in a table form.
Currently, my TSN_PIC returns result as follows:
The input video frame is classified to be PlayingCello - 99.33
PlayingGuitar - 0.28 PlayingPiano - 0.16 BoxingSpeedBag - 0.10
StillRings - 0.06
But I want to be able to display this on a web page using flask in a table format
My code is as follows:
cv_acp
def TSN_PIC(img):
img = image.imread(img)
fig, ax = plt.subplots(figsize=(18, 18))
ax.imshow(img.asnumpy())
transform_fn = transforms.Compose([
video.VideoCenterCrop(size=224),
video.VideoToTensor(),
video.VideoNormalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])])
img_list = transform_fn([img.asnumpy()])
net = get_model('vgg16_ucf101', nclass=101, pretrained=True)
pred = net(nd.array(img_list[0]).expand_dims(axis=0))
classes = net.classes
topK = 5
ind = nd.topk(pred, k=topK)[0].astype('int')
print('The input video frame is classified to be')
for i in range(topK):
result = ('\t%s - %.2f'%(classes[ind[i].asscalar()], nd.softmax(pred)[0][ind[i]].asscalar()*100))
print((result))
return plt.show()
app.py
#app.route("/cv/action_prediction/TSN_PIC", methods=['POST'])
def cv_acp_TSN_PIC_upload_image():
if 'file' not in request.files:
flash('No file part')
return redirect(request.url)
file = request.files['file']
if file.filename == '':
flash('No image selected for uploading')
return redirect(request.url)
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
print(app.config)
path = os.path.join(app.config['UPLOAD_FOLDER'], filename)
print(path)
file.save(path)
#print(file.config)
result = cv_acp.TSN_PIC(path)
# print (results)
#print('upload_image filename: ' + filename)
flash('Image successfully uploaded and displayed below')
return render_template('cv_acp_TSN_PIC.html', filename=filename, result=result)
else:
flash('Allowed image types are -> png, jpg, jpeg, gif')
return redirect(request.url)
#app.route('/cv/action_prediction/TSN_PIC/display/<filename>')
def cv_acp_TSN_PIC_display_image(filename):
#print('display_image filename: ' + filename)
#return MASK_RCNN('static', filename='uploads/' + filename)
return redirect(url_for('static', filename='uploads/' + filename), code=301)
if __name__ == "__main__":
#app.run()
app.run()
cv_acp_TSN_PIC.html
<div id="content" class="p-4 p-md-5 pt-5">
<h2 class="mb-4">TSN PIC</h2>
<!Doctype html>
<title>Python Flask File Upload Example</title>
<h2>Select a file to upload</h2>
<p>
{% with messages = get_flashed_messages() %}
{% if messages %}
<ul>
{% for message in messages %}
<li>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
{% endwith %}
</p>
{% if filename %}
<div>
<img src="{{ url_for('cv_acp_TSN_PIC_display_image', filename=filename) }}">
{% block content %}
<div class="container">
<p>{{results}}</p>
</div>
{% endblock %}
</div>
{% endif %}
<form method="post" action="/cv/action_prediction/TSN_PIC" enctype="multipart/form-data">
<dl>
<p>
<input type="file" name="file" autocomplete="off" required>
</p>
</dl>
<p>
<input type="submit" value="Submit">
</p>
</form>
</div>
Create a list of dictionaries of the data you need and return that. Then you can loop over the data and build your table.
results = []
for i in range(topK):
result = ('\t%s - %.2f'%(classes[ind[i].asscalar()], nd.softmax(pred)[0][ind[i]].asscalar()*100))
datadict = {
'header': yourheadername,
'data': yourdatahere
}
results.append(datadict)
return results
<table border=1>
{% for result in results%}
<tr>
<th>
{{result.header}}
</th>
</tr>
<tr>
<td>
{{result.data}}
</td>
</tr>
{% endfor %}
</table>
If you're working in a terminal or in a Jupyter notebook, plt.show() does what you want. For a web page, not so much.
You have a good start otherwise, based it seems on getting an uploaded image to display. So your challenge will be to either save the matplotlib image to disk before you generate the page, or to defer generating the image until it's requested by way of the <img src=..., then somehow return the image bits from cv_acp_TSN_PIC_display_image instead of a path to the saved file.
To do the former, plt.savefig('uploads/image.png') might be what you need, with the caveat that a fixed filename will break things badly as soon as you have multiple users hitting the app.
To do the latter, see this question and its answer.

how to get the data from view to templates?

i'm trying to get the data from my views.py to the html page.
if the views.py code is this
def VerifiedBySuperuser(request):
if request.method == 'POST':
vbs = MaanyaIT_EXAM48_ManageQuestionBank()
vbs.QuestionID = MaanyaIT_EXAM48_ManageQuestionBank.objects.get(QuestionID=request.POST.get(QuestionID, None))
vbs.QuestionInEnglishLang = request.POST.get('QuestionInEnglishLang', None)
vbs.save()
else:
return render(request, 'exam48app/verifiedbysuperuser.html')
then what shoud the code of html page to view my all data to the tamplates..
this is my html page
<form class="from-horizontal" method="post" enctype="multipart/form-data">
{% csrf_token %}
<div class="post-entry">
{{ MaanyaIT_EXAM48_ManageQuestionBank.QuestionInEnglishLang }}
</div>
</form>
now what should i do?
From your comment, you need to know How to write/render the data from view to html template
I will demonstrate a simple example for you,
Assuming you have a view as below,
def VerifiedBySuperuser(request):
if request.method == 'GET':
context = {
"T_Name": "My Name",
"T_Age": 50,
"T_Phone": 1478523699
}
return render(request, 'verifiedbysuperuser.html', context=context)
and a HTML template as follows,
<!DOCTYPE>
<html>
<body>
Name : {{ T_Name }}<br>
Age : {{ T_Age }}<br>
Phone : {{ T_Phone }}<br>
</body>
</html>
When you access your view, you will get a response like this,
In your case, you can pass as many attributes to template as dict (shown in my example) and in template/html keys of context (that is T_Name,T_Name etct) becomes variable. So you can directly use them in HTML inside the twin braces ({{ variable_name }})
As far as I knew, this is the general procedure for template rendering/ html rendering
UPDATE-1
def VerifiedBySuperuser(request):
if request.method == 'POST':
obj = MyModel.objects.get(id=some_id)
other_data = [1,2,3,4,] # some specific data
context = {
"post_data": request.data,
"object_instance": obj,
"some_other_data": other_data
}
return render(request, 'verifiedbysuperuser.html', context=context)

HTML input textbox in Django admin.py filter

I would like to filter data in Django (admin.py) with text writen in HTML input textbox. I need to filter companies by city in which they are and list of all cities is too long. I would like to replace list of all cities in filter by one text input. I found something similar
here http://djangosnippets.org/snippets/2429/ but there are two problems:
author did not posted models.py, so it is difficuilt to change code for my needs (+ no comments)
there is used class UserFieldFilterSpec(RelatedFilterSpec): but I need to use AllValuesFilterSpec instead of RelatedFilterSpec (more in file django/contrib/admin/filterspecs.py), because list of towns are in the same class as comapny (there shoud by class of towns and they should be referencing to company by foreign key (ManyToMany relationship), but for some reasons it have to be done this way)
important part of models.py looks something like this
class Company(models.Model):
title = models.CharField(max_length=150,blank=False)
city = models.CharField(max_length=50,blank=True)
and something from admin.py
class CatalogAdmin(admin.ModelAdmin):
form = CatalogForm
list_display = ('title','city')
list_filter = ['city',]
So again, I need to:
1. instead of list od cities display one text input in Django filter
2. After inputing city neme in that text input, filter data by city (request for filtering can be sent with some submit button or through javascript)
Thank yoy for all posts.
In case anybody still need this. It is little hackish in template, but implemented without a piece of js.
filters.py:
from django.contrib.admin import ListFilter
from django.core.exceptions import ImproperlyConfigured
class SingleTextInputFilter(ListFilter):
"""
renders filter form with text input and submit button
"""
parameter_name = None
template = "admin/textinput_filter.html"
def __init__(self, request, params, model, model_admin):
super(SingleTextInputFilter, self).__init__(
request, params, model, model_admin)
if self.parameter_name is None:
raise ImproperlyConfigured(
"The list filter '%s' does not specify "
"a 'parameter_name'." % self.__class__.__name__)
if self.parameter_name in params:
value = params.pop(self.parameter_name)
self.used_parameters[self.parameter_name] = value
def value(self):
"""
Returns the value (in string format) provided in the request's
query string for this filter, if any. If the value wasn't provided then
returns None.
"""
return self.used_parameters.get(self.parameter_name, None)
def has_output(self):
return True
def expected_parameters(self):
"""
Returns the list of parameter names that are expected from the
request's query string and that will be used by this filter.
"""
return [self.parameter_name]
def choices(self, cl):
all_choice = {
'selected': self.value() is None,
'query_string': cl.get_query_string({}, [self.parameter_name]),
'display': _('All'),
}
return ({
'get_query': cl.params,
'current_value': self.value(),
'all_choice': all_choice,
'parameter_name': self.parameter_name
}, )
templates/admin/textinput_filter.html:
{% load i18n %}
<h3>{% blocktrans with filter_title=title %} By {{ filter_title }} {% endblocktrans %}</h3>
{#i for item, to be short in names#}
{% with choices.0 as i %}
<ul>
<li>
<form method="get">
<input type="search" name="{{ i.parameter_name }}" value="{{ i.current_value|default_if_none:"" }}"/>
{#create hidden inputs to preserve values from other filters and search field#}
{% for k, v in i.get_query.items %}
{% if not k == i.parameter_name %}
<input type="hidden" name="{{ k }}" value="{{ v }}">
{% endif %}
{% endfor %}
<input type="submit" value="{% trans 'apply' %}">
</form>
</li>
{#show "All" link to reset current filter#}
<li{% if i.all_choice.selected %} class="selected"{% endif %}>
<a href="{{ i.all_choice.query_string|iriencode }}">
{{ i.all_choice.display }}
</a>
</li>
</ul>
{% endwith %}
Then according to your models in admin.py:
class CatalogCityFilter(SingleTextInputFilter):
title = 'City'
parameter_name = 'city'
def queryset(self, request, queryset):
if self.value():
return queryset.filter(city__iexact=self.value())
class CatalogAdmin(admin.ModelAdmin):
form = CatalogForm
list_display = ('title','city')
list_filter = [CatalogCityFilter,]
Ready to use filter would look like this.
I'm running Django 1.10, 1.11 and r_black's solution didn't completely fit because Django was complaining that filter fields must inherit from 'FieldListFilter'.
So a simple change for the filter to inherit from FieldListFilter took care of Django complaining and not having to specify a new class for each field, both at the same time.
class SingleTextInputFilter(admin.FieldListFilter):
"""
renders filter form with text input and submit button
"""
parameter_name = None
template = "admin/textinput_filter.html"
def __init__(self, field, request, params, model, model_admin, field_path):
super().__init__(field, request, params, model, model_admin, field_path)
if self.parameter_name is None:
self.parameter_name = self.field.name
if self.parameter_name in params:
value = params.pop(self.parameter_name)
self.used_parameters[self.parameter_name] = value
def queryset(self, request, queryset):
if self.value():
return queryset.filter(imei__icontains=self.value())
def value(self):
"""
Returns the value (in string format) provided in the request's
query string for this filter, if any. If the value wasn't provided then
returns None.
"""
return self.used_parameters.get(self.parameter_name, None)
def has_output(self):
return True
def expected_parameters(self):
"""
Returns the list of parameter names that are expected from the
request's query string and that will be used by this filter.
"""
return [self.parameter_name]
def choices(self, cl):
all_choice = {
'selected': self.value() is None,
'query_string': cl.get_query_string({}, [self.parameter_name]),
'display': _('All'),
}
return ({
'get_query': cl.params,
'current_value': self.value(),
'all_choice': all_choice,
'parameter_name': self.parameter_name
}, )
templates/admin/textinput_filter.html (unchanged):
{% load i18n %}
<h3>{% blocktrans with filter_title=title %} By {{ filter_title }} {% endblocktrans %}</h3>
{#i for item, to be short in names#}
{% with choices.0 as i %}
<ul>
<li>
<form method="get">
<input type="search" name="{{ i.parameter_name }}" value="{{ i.current_value|default_if_none:"" }}"/>
{#create hidden inputs to preserve values from other filters and search field#}
{% for k, v in i.get_query.items %}
{% if not k == i.parameter_name %}
<input type="hidden" name="{{ k }}" value="{{ v }}">
{% endif %}
{% endfor %}
<input type="submit" value="{% trans 'apply' %}">
</form>
</li>
{#show "All" link to reset current filter#}
<li{% if i.all_choice.selected %} class="selected"{% endif %}>
<a href="{{ i.all_choice.query_string|iriencode }}">
{{ i.all_choice.display }}
</a>
</li>
</ul>
{% endwith %}
Usage:
class MyAdmin(admin.ModelAdmin):
list_display = [your fields]
list_filter = [('field 1', SingleTextInputFilter), ('field 2', SingleTextInputFilter), further fields]
While it's not actually your question, this sounds like a perfect solution for Django-Selectables you can with just a few lines add an AJAX powered CharField Form that will have it's entries selected from the list of cities. Take a look at the samples listed in the link above.
Below is the fix for field name..in queryset function
class SingleTextInputFilter(admin.FieldListFilter):
"""
renders filter form with text input and submit button
"""
parameter_name = None
template = "admin/textinput_filter.html"
def __init__(self, field, request, params, model, model_admin, field_path):
super().__init__(field, request, params, model, model_admin, field_path)
if self.parameter_name is None:
self.parameter_name = self.field.name
if self.parameter_name in params:
value = params.pop(self.parameter_name)
self.used_parameters[self.parameter_name] = value
def queryset(self, request, queryset):
variable_column = self.parameter_name
search_type = 'icontains'
filter = variable_column + '__' + search_type
if self.value():
return queryset.filter(**{filter: self.value()})
def value(self):
"""
Returns the value (in string format) provided in the request's
query string for this filter, if any. If the value wasn't provided then
returns None.
"""
return self.used_parameters.get(self.parameter_name, None)
def has_output(self):
return True
def expected_parameters(self):
"""
Returns the list of parameter names that are expected from the
request's query string and that will be used by this filter.
"""
return [self.parameter_name]
def choices(self, cl):
all_choice = {
'selected': self.value() is None,
'query_string': cl.get_query_string({}, [self.parameter_name]),
'display': ('All'),
}
return ({
'get_query': cl.params,
'current_value': self.value(),
'all_choice': all_choice,
'parameter_name': self.parameter_name
}, )