django - 'ModelName' object is not iterable - python

I have a model class named TemplateImages that holds the reference to images in my media folder.
I want to display the images in a loop on a html file.
Here is my models.py code:
class TemplateImages(models.Model):
image = models.ImageField(upload_to='template_images') # template_images/en/chronological/en-chronological-resume-1.png.
type = models.CharField(max_length=40) # e.g. chronological, functional, combination, coverletter
language_code = models.CharField(max_length=7, choices=languages.LANGUAGE_CHOICES, default='en') # en.
def __str__(self):
return '{}'.format(self.image)
Here is my views.py code:
def templates(request):
...
language_pref = request.user.userprofile.language_preference
chronological_images = core_models.TemplateImages('chronological', 'en')
...
return render(request, 'templates/templates.html', {
...
'chronological_images': chronological_images,
...
})
Here is a screen shot of my db:
On my html page, I have placed the following django for loop to display the 25 images on the page:
{% for c_image in chronological_images %}
{{c_image.image|file_url|safe}}"
{% endfor %}
I receive the following error message:
'TemplateImage' object is not iterable
I have searched google, but cannot locate any useful examples.
Can someone explain what I have done wrong?

You've simply constructed a TemplateImages object, not run a query. Try this:
chronological_images = TemplateImages.objects.filter(
type='chronological',
language_code='en',
)

You only constructed a new TemplateImages object that you did not save to the database, and of course that single object is not iterable. If you want to perform a query, you should use TemplateImages.objects.filter(), like:
def templates(request):
# ...
language_pref = request.user.userprofile.language_preference
chronological_images = core_models.TemplateImages.objects.filter(
type='chronological',
language_code='en'
)
# ...
return render(request, 'templates/templates.html', {
# ...
'chronological_images': chronological_images,
# ...
})

Related

Django 1.11: export queryset to csv using classes

I am having trouble exporting the results of a Django query to csv using a subclass of my query class as suggested here. https://stackoverflow.com/a/29678525/3973597
I end up with a Page not found (404) error. Here is the relevant code...
views.py
class QueryResultsView(ListView):
template_name = 'query/query_results.html'
model = StDetail
context_object_name = "object_list"
def get_queryset(self):
form_input = self.request.GET
filters = {"person_name": form_input.get('name'),
"city": form_input.get('city'),
}
# delete keys that are None
filters = {k: v for k, v in filters.items() if v is not ''}
self.detail_data = get_list_or_404(self.model, **filters)
return(self.detail_data)
def get_context_data(self, **kwargs):
context = super(QueryResultsView, self).get_context_data(**kwargs)
context['query_results'] = self.get_queryset()
return(context)
class QueryResultsCsvView(QueryResultsView):
# Subclass of above view, to produce a csv file
template_name = 'query/QueryResults.csv'
content_type = 'text/csv'
urls.py
app_name = QueryConfig.name
urlpatterns = [
...
url(r'^query',
QueryFormView.as_view(),
name='person-query'),
url(r'^results',
QueryResultsView.as_view(),
name='query-results'),
url(r'^results/csv/$',
QueryResultsCsvView.as_view(),
name='query-results-csv'),
]
query_results.html
...
Download Results
...
QueryResults.csv
Date, City, Name, Sex
{% for object in object_list %}
{{object.date}},{{object.city}},{{object.name}},{{object.sex}}
{% endfor %}
The query works without any problems. However, when I click on the Download Results link I get a Page not found (404) error. Can somebody tell me what I'm missing?
Your first problem is that r'^results'matches results/csv/ as well as results because it doesn't use a $ to match the end of the URL.
Try something like the following (I've added trailing slashes to match the usual Django style).
urlpatterns = [
url(r'^query/$',
QueryFormView.as_view(),
name='person-query'),
url(r'^results/$',
QueryResultsView.as_view(),
name='query-results'),
url(r'^results/csv/$',
QueryResultsCsvView.as_view(),
name='query-results-csv'),
]
Once you've done that, you're next problem is that you are simply linking to the query-results-csv results view, but you are not passing any form data to it. In the template for the query-results view, you could add the same querystring to the link by changing it to:
Download Results
Finally, note that form_input.get(key) returns None if the key does not exist, therefore your filter should use if v instead of if v is not '' (if you really only wanted to exclude values with the empty string, you should have used if v != '').
filters = {k: v for k, v in filters.items() if v}

How to put arguments in a jchart.Chart class

I am trying to make a chart in Django using the jchart module and to be able to chose which rows i want to retrieve from the db using the variable hosp from my views.py to HomeTotalStudies() (below)
views.py
from charts.chartsclass import HomeTotalStudies
def home(request):
hosp = request.user.userprofile.hospital
chart = HomeTotalStudies()
return render .....
here is the /charts/chartsclass.py
from jchart import Chart
from jchart.config import (DataSet, Axes, rgba, ScaleLabel, Tick, Tooltips,
Legend, LegendLabel, Title, Hover, InteractionModes,
ElementLine, ElementPoint, ElementRectangle)
class HomeTotalStudies(Chart):
chart_type = 'pie'
responsive = False
def get_labels(self,**kwargs):
return ["CT","MG","RF","DX"]
def get_datasets(self,**kwargs):
modality = ['CT','MG','RF','DX']
count = []
if hosp=='somestring' #this is the variable i want to get from the views.py
studies = GeneralStudyModel.objects.all()
else:
studies = GeneralStudyModel.objects.filter(equipmentattributes__institution_name__exact=hosp)
for mod in modality:
cc = studies.objects.filter(modality_type__exact=mod).count()
count.append(cc)
data = [count[i] for i in range(len(count))]
colors = [
rgba(255,99,132,1),
rgba(54,162,235,1),
rgba(255,159,64,1),
rgba(255,206,86,1)
]
return [DataSet(label="My DataSet",
data=data,
borderWidth=1,
backgroundColor=colors,
borderColor=colors)]
So, my question is, how can I pass this variable hosp from the view to the chart class so that i can make the query to the db table GeneralStudyModel and i retrieve only the rows needed?
Any one has any suggestion / idea / solution?
Thanks
Yep.
You have two possibilites:
the hard way: you make an AJAX call that returns an array, and you populate this in JavaScript. This implies to make a JSON view that returns a JSON array
the easy way: you need to use class-based-view's to make modern application and in your class you override the method get_context_data()
like this:
class GeneralStudyResultsView(generic.TemplateView):
template_name='general_study_results.html'
def get_context_data(self, **kwargs):
# Call the base implementation first to get a context
context = super(GeneralStudyResultsView, self).get_context_data(**kwargs)
# Create a variable you fill
context['my_big_sql'] = GeneralStudyModel.objects.all()
return context
And from there, in your template file (this is your template file, not a JavaScript file) general_study_results.html add something like:
<script>
var myData =
{% for row in my_big_sql %}
{{ row.column }}{% if not forloop.last %},{% endif %}
{% endfor %};
</script>
And then you have all your data in your HTML file ready to be show thanks to charts.js
Just add a suitable initialiser to the chart class as follows:
class HomeTotalStudies(Chart):
def __init__(self, hosp, *args, **kwargs):
self.hosp = hosp
super().__init__(*args, **kwargs)
def get_datasets(self,**kwargs):
modality = ['CT','MG','RF','DX']
count = []
if self.hosp=='somestring' #this is the variable i want to get from the views.py
studies = GeneralStudyModel.objects.all()
else:
studies = GeneralStudyModel.objects.filter(equipmentattributes__institution_name__exact=self.hosp)
...
then in your view:
from charts.chartsclass import HomeTotalStudies
def home(request):
hosp = request.user.userprofile.hospital
chart = HomeTotalStudies(hosp='whatever')
return render .....

Django: Calling a model's function in my template - not working

I'm trying to call a function from my model (check_nick) in my template. It appears that the template is successfully hitting the function since the items in the function are printed. However I'm not getting the expected result (True) as the user.group I'm testing with is NICK which is part of the NICK_BRANDS list.
MODEL.PY:
NICK_BRANDS = ['NICK', 'NICKT', 'NICKN', 'NICKK', 'NICKA']
class User():
group = models.ForeignKey(Brand, null=True, blank=True)
def check_nick(self):
brand = self.group
print brand //prints NICK
print brand in NICK_BRANDS //prints False (should be True!)
if brand in NICK_BRANDS:
return True
else:
return False
TEMPLATE:
{% if user.check_nick %}
//add some markup
{% endif %}
Your debug prints some string representation of brand, but you are checking the actual object. Change your if-clause to sth like:
if str(brand) in NICK_BRANDS:
# if brand.title in NICK_BRANDS:
# if brand.name in NICK_BRANDS:
# or whatever field of Brand is "NICK"
self.group will be an instance of the related Brand model, not a string, and hence would probably not return True with the in statement. I presume there is some Brand.name property and you should be using:
def check_nick(self):
return self.group.name in NICK_BRANDS

How to make foreign key accept field value instead of its id in django?

I have created a checkbox for content filtering of products based on category.So when the user clicks on any checkbox only the books with that category should be shown.In the view I am passing the value of checkbox field(category name) obtained from the template but upon filtering, the foreign key is expecting pk(id) instead of field value.I am getting error like this,invalid literal for int() with base 10: '<category name>'.So is it possible to make foreign key accept value instead of id?
Models.py,
class Add_cat(models.Model):
category = models.CharField("Name",max_length=25,unique=True)
def __unicode__(self):
return u'{0}'.format(self.category)
class Add_prod(models.Model):
book = models.CharField("Book Name",max_length=40)
author = models.CharField("Author",max_length=30)
price = models.PositiveIntegerField("Price")
image = models.ImageField(upload_to='images',null=True)
cat = models.ForeignKey(Add_cat,on_delete=models.PROTECT)
Template file,
{% for i in products %}
<input type="checkbox" name="cat_name" value="{{i.cat}}">{{i.cat}}<br>
{% endfor %}
Views.py,
def welcome_user(request):
if 'cat_name' in request.GET:
filter_category = request.GET.get('cat_name')
my_products = Add_prod.objects.filter(cat__in = filter_category)
context = { "products":my_products}
else:
my_products = Add_prod.objects.all()
context = { "products":my_products}
return render(request,"welcome-user.html",context)
You can check in the category field itself:
my_products = Add_prod.objects.filter(cat__category__in=filter_category)
Have a look at the documentation on how this works.
Above, is only applicable if filter_category is a list. If it is a string you can filter like following:
my_products = Add_prod.objects.filter(cat__category=filter_category)
There are two things wrong with your code
You need to look up the field rather than the foreign key
By using __in you are looking the category is equal to any one of the characters in the filter_category.
Hence to fix, use the field lookup and remove the __in
Add_prod.objects.filter(cat__category=filter_category)
You can try this,it will help you:
Add_prod.objects.filter(cat__category = filter_category)

Django multiple included forms with foreign key

i have a problem. Here is 2 related models:
class Auto(models.Model):
...
class Part(models.Model):
...
parent = models.ForeignKey(Auto, blank = False, null = False)
So, i want to create next django form:
Auto1.field1 Auto1.Part1.field1 Auto1.field2
Auto1.Part1.field2
Auto1.Part2.field1
Auto1.Part2.field2
...
Auto2.field1 Auto2.Part1.field1 Auto2.field2
Auto2.Part1.field2
Auto2.Part2.field1
Auto2.Part2.field2
...
...
All fields must be updatable, as for model Auto and for model Part.
How can i do this?
You should try to use Inline formsets. For example, assuming you have an Auto modelform it can be done like this:
autoforms = []
part_formsets = []
autos = Auto.objects.all()
PartFormSet = inlineformset_factory(Auto, Part, fields=('field1', 'field2'))
for auto in autos:
autoform = AutoForm(instance=auto)
autoforms.append(autoform)
part_formset = PartFormSet(instance=auto)
part_formsets.append(part_formset)
c = {'autoforms': autoforms, 'part_formsets': part_formsets}
return render(request, 'some.html', c)
Now you can iterate autoforms and part_formsets in template to get the desired forms. However, I have not checked if it is easy to render them in a template as you want.

Categories

Resources