Django html template getting data from nested dictionary - python

I'm having a problem with an html template not displaying model fields sent from a view in a context dictionary called content. This dictionary holds a nested dictionary like:
content = {'indredients': {recipe id1: QuerySet 1,
recipe id2: QuerySet 2, ... } }
In model.py:
class Ingredients(models.Model):
id = models.IntegerField(primary_key=True)
recipe = models.ForeignKey(Recipes, on_delete=models.CASCADE, related_name='ingredients')
ingredient = models.CharField(max_length=128)
class Meta:
managed = False
db_table = 'ingredients'
verbose_name_plural = 'Ingredients'
def __str__(self):
return f"{self.id} {self.recipe} - {self.ingredient}"
class Recipes(models.Model):
id = models.IntegerField(primary_key=True)
category = models.TextField(db_column='Category', null=False)
submitted_by = models.TextField(
db_column='Submitted_By', null=False)
origin = models.TextField(db_column='Origin', null=False)
title = models.TextField(db_column='Title', null=False)
directions = models.TextField(
db_column='Directions', null=False)
comments = models.TextField(db_column='Comments', null=False)
created = models.DateTimeField(null=False)
modified = models.DateTimeField(null=True)
def __str__(self):
return f"{self.id} - {self.title}"
class Meta:
managed = False
db_table = 'recipes'
verbose_name_plural = 'Recipes'
In views.py:
recipes = Recipes.objects.all().order_by(
"category", "title")
content['ingredients'] = {}
for recipe in recipes:
ingredients = Ingredients.objects.filter(
recipe=recipe.id).order_by("id")
content['ingredients'][recipe.id] = ingredients
content['recipes'] = recipes
return render(
request,
"myApp/recipes.html",
context=content)
In recipes.html:
{% for recipe in recipes %}
<div id="id-{{recipe.id}}" class="grid-item {{recipe.category}} {{recipe.submitted_by}}">
<div class="row">
<div class="col-12 col-md-3 ingredients">
{% for queryQbject in ingredients.recipe.id %}
{{ queryQbject.ingredient }}<br>
{% empty %}
<span>No ingredients provided</span>
{% endfor %}
</div>
</div>
{% endfor %}
I do get the correct data from the sqlite database and the Queryset is stored in the dictionary 'content' that is passed correctly into the html file. However, the html template doesn't display any of the data and only prints the 'No ingredients provided' {% empty %} case.
See debug info:
What do I need to do to fix this problem?

nigel239's answer got me thinking and researching some more. I found this post
https://fedingo.com/how-to-lookup-dictionary-value-with-key-in-django-template/
to write a custom filter to lookup a dictionary value with a key.
This is my custom_tags.py:
#register.filter
def get_item(dictionary, key):
try:
key = int(key)
value = dictionary.get(key)
except:
value = None
return value
and my updated recipes.html:
<div class="col-12 col-md-3 ingredients">
{% for queryset in ingredients|get_item:recipe.id %}
{{ queryset.ingredient }}<br>
{% empty %}
<span>No ingredients provided</span>
{% endfor %}
</div>
Now the code correctly pulls all the ingredients from the Django Queryset that was passed into the html template in a dictionary called 'ingredients' using the 'recipe.id' as keys.

You are trying to loop over the ID, which is an integer. Not an iterable.
Change
{% for queryQbject in ingredients.recipe.id %}
To
{% for queryQbject in ingredients.recipe %}

Related

Display foreign key info within Django Detail View Template

As the title says I have a detailed view that I'm presenting via Django templates. I have a foreign key that I'd also like to present within that detailed view and I just can't get it to work. I've tried everything, but all I get is the basic detailed view template with no foreign key info. Any help would be greatly appreciated.
Here's what I've got so far:
Models:
class Cust(models.Model): #this is the main model
id = models.UUIDField(
primary_key=True,
default=uuid.uuid4,
editable=False)
email = models.CharField(max_length=200)
firstName = models.CharField(max_length=200)
lastName = models.CharField(max_length=200)
watchmanSlug = models.CharField(max_length=200, unique=True)
class Watchman(models.Model):
group = models.ForeignKey(Cust, on_delete=models.CASCADE,to_field='watchmanSlug',
related_name='watchman_group_slug')
uid = models.CharField(max_length=500)
computer_name = models.CharField(max_length=500)
computer_url = models.CharField(max_length=500)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
Views
class CustomerDetailView(DetailView):
model = Cust
template_name = 'cust/cust_detail.html'
def get_context_data(self, ** kwargs):
context = super(CustomerDetailView, self).get_context_data( ** kwargs)
context['computer_name'] = Watchman.objects.all()
return context
Detail Template
<tbody>
<ul>
{% for p in watchman_group_slug.all %}
<li>{{ watchman.computer_name }}</li>
{% endfor %}
</ul>
</tbody>
You access the related Watchman objects with:
<tbody>
<ul>
{% for p in object.watchman_group_slug.all %}
<li>{{ p.computer_name }}</li>
{% endfor %}
</ul>
</tbody>
so with object.watchman_group_slug.all, and with the .computer_name of p.

Django - Targetting primary key of current "Artist" object as a filter from "All Track" result list

Im working n a record label website in Django 3 using Python3. (Artist, Release, Track structure)
I am attempting to filter out a list of all tracks based on the current artist page.
music/artist/
I'm thining to filter this in the context_processors file, but dont know how, and am willing to do it anyway that works if this is not possible.
artist.html
{% block body %}
<div class="container artistitem">
<h2>{{ artist.artist_name }}</h2>
<h3>{{ artist.artist_url }}</h3>
<h5>{{ artist.artist_id }}</h5>
<div class="artistimage"><img src="{{ artist.artist_logo.url }}"></div>
<div>
<h3>Discography</h3>
<p>
<ul>
<!-- for this artist id in all releases print all release name -->
<!-- {% for release.artist.id in all_releases %}
<li>
{{ release.release_title }}
</li>
{% endfor %} -->
<!-- for this artist id in all releases print all release name -->
{% for track in all_tracks_byartist %}
<li>
{{ track.track_title }}
</li>
{% endfor %}
</ul>
</p>
</div>
</div>
{% endblock %}
models.py
from django.db import models
# Create your models here.
class Artist(models.Model):
artist_name = models.CharField(max_length=250, default='')
artist_logo = models.FileField()
artist_url = models.URLField(blank=True)
def __str__(self):
return self.artist_name
class Release(models.Model):
artist = models.ForeignKey(Artist, on_delete=models.CASCADE, related_name='release')
release_title = models.CharField(max_length=500)
release_cover = models.FileField()
release_duration = models.IntegerField()
def __str__(self):
return self.release_title
class Track(models.Model):
release = models.ForeignKey(Release, default='', on_delete=models.CASCADE)
artist = models.ForeignKey(Artist, default='', on_delete=models.CASCADE)
track_title = models.CharField(max_length=200)
track_version = models.CharField(max_length=200)
track_genre = models.CharField(max_length=100)
track_duration = models.IntegerField()
track_number = models.SmallIntegerField()
class Meta:
ordering = ["track_number"]
def __str__(self):
return self.track_title
app_name = 'music'
context_processors.py
from music.models import Artist, Release, Track
def all_artists(request):
artist = Artist.objects.all()
return {'all_artists':artist}
def all_releases(request):
release = Release.objects.all()
return {'all_releases':release}
def all_tracks(request):
track = Track.objects.all()
return {'all_tracks':track}
def all_tracks_byartist(request):
track = Track.objects.all()
return {'all_tracks_byartist':track}
If you need any other files please let me know.
use reverse relation for getting tracks of a specific artist.
something like:
{% for track in artist.track_set.all %}
<li>
{{ track.track_title }}
</li>
{% endfor %}

Django TypeError objects is not iterable in Templates

I have two models one is club details and the other is player structure. so my plan is to based on the club iteration which has values like'test', 'odi', 'listA' i need to represent its respective player structure in my Django template.
models.py
class Clubstate(models.Model):
name = models.CharField(max_length=255)
def __str__(self):
return self.name
class PlayerStructure(models.Model):
clubstate = models.ForeignKey('Clubstate', on_delete=models.CASCADE, related_name='clubstate')
country = models.ForeignKey('TeamStructure', on_delete=models.CASCADE, null=True, related_name='identifier1')
firstname = models.CharField(max_length=255)
lastname = models.CharField(max_length=255)
imageUri = models.ImageField(upload_to='images/', verbose_name='image')
JerseyNumber = models.IntegerField()
def __str__(self):
return self.firstname + self.lastname
In views.py I'm using DetailView to represent the data.
class PlayerStatistics(DetailView):
context_object_name = 'Clubstate_details'
model = models.Clubstate
template_name = 'CricketDetails/playerstatistics_details.html'
Template html
<div class="jumbotron">
<div class="container">
<div class="row">
{% for club in Clubstate_details %}
<h1>{{club.name</h1>
{% endfor %}
</div>
</div>
</div>
My thought, logic is like
{% for club in clubs %}
{{club.name}}
{{club.player_structure.firstname}}
{{club.player_structure.lastname}}
{% endfor%}
So that for indivdual club i get its respective player structure.
I get TypeError: 'Clubstate' object is not iterable error.
Hope that makes sense...
Detail view won't give a list of items, instead it gives a single view only so change the DetailView to ListView and iterate through the output
class PlayerStatistics(ListView):
context_object_name = 'Clubstate_details'
model = models.Clubstate
template_name = 'CricketDetails/playerstatistics_details.html'
if you want detail view can get it by
{{ Clubstate_details.name }}
with DetailView
FK instance can be accessed by
{% for obj in Clubstate_details.playerstructure_set.all %}
{{ obj.firstname }}
{% endfor %}

Trouble getting related fields in ForeignKeys to show in Template

I'm working in Django 2.2 trying to build a view for a database that compiles everything for a specific company (locations of all of their stores and notes on the companies) into a single view. I've tried methods in several different answers, but still cannot seem to get data from related foreign keys to show in the template.
models.py
class Company(models.Model):
name = models.CharField(max_length=30, primary_key=True)
official_name = models.CharField(max_length=50)
corporate_address1 = models.CharField(max_length=50)
corporate_address2 = models.CharField(max_length=50)
city = models.CharField(max_length=60)
state_province = models.CharField(max_length=30)
country = models.ForeignKey('Country', on_delete=models.CASCADE)
slug = models.SlugField(max_length=30, unique=True)
def __str__(self):
return self.name
class Stores(models.Model):
store_name = models.CharField(max_length=30, primary_key=True)
owner = models.ForeignKey('Company', on_delete=models.CASCADE)
store_address1 = models.CharField(max_length=50)
store_address2 = models.CharField(max_length=50)
city = models.CharField(max_length=60)
state_province = models.CharField(max_length=30)
country = models.ForeignKey('Country', on_delete=models.CASCADE)
type = models.CharField(max_length=30,choices=store_types)
slug = models.SlugField(max_length=30, unique=True)
def get_absolute_url(self):
return reverse("store-detail", kwargs={"slug": self.slug})
class notes(models.Model):
title = models.CharField(max_length=120)
content = models.TextField()
posted = models.DateTimeField(db_index=True, auto_now_add=True)
category = models.ForeignKey('Company', on_delete=models.CASCADE)
active = models.BooleanField(default=True)
def get_absolute_url(self):
return reverse("article-detail", kwargs={"id": self.id})
class Country(models.Model):
country = models.CharField(max_length=30,choices=countries,primary_key=True)
class Meta:
ordering = ["-country"]
db_table = 'country'
def __str__(self):
return self.country
views.py
class CompanyOverView(LoginRequiredMixin, DetailView):
model = Company
template_name = "company-overview.html"
slug_url_kwarg = 'slug'
query_pk_and_slug = True
pk_url_kwarg = "company.name"
template
<div align="center">
<p>{{ object.name }}<br>({{ object.official_name }})</p>
<p>{{ object.corporate_address1 }}<br>{{ object.corporate_address2 }}<br>
{{ object.city }}<br>{{ object.state_province }}<br>
{{ object.country }}</p>
</div>
<p>List of Stores</p>
<p>
{% for instance in object_list %}
{{ instance.company.stores.store_name }}
{{ instance.company.stores.store_address1 }}
{{ instance.company.stores.store_address2 }}
{{ instance.company.stores.city }}
{{ instance.company.stores.state_province }}
{{ instance.company.stores.country }}
{% endfor %}
</p>
<p>Notes</p>
<p>
{% for instance in object_list %}
{{ instance.company.notes.title }}
{{ instance.company.notes.posted }}
{% endfor %}
</p>
With the above code, the only thing that appears when you enter in the company's name is everything at the top (e.g."object.name" appears on the page as "Acme Corporation"). Nothing in the for loop appears on the web page.
Looking at the documentation, object_list is the default name for context unless specified. I have tried different combinations such as "for store_name in company.store_set.all" and other combinations I found in other posts, but none have worked. I've combed the documentation for everything related to foreign keys, but can't find a solution that works.
Thanks in advance if you can help.
No. object_list is the default context name in a ListView. But you have a DetailView, and you already know what the default context name is for those because you're already using it: object. You just need to iterate over the reverse relation from there:
{% for store in object.stores_set.all %}
{{ store.store_name }}
{{ store.store_address1 }}
...
{% endfor %}

Django: Foreign Key Query to post the information on the html template

I'm stuck on my next step of showing the query from the database to the html template. I'm able to put some basic information, but I got stuck on the foreign key queries.
Here is sample of my code:
Here is my model:
class Player_Bios(models.Model):
my_id = models.SlugField(unique=True)
player_id = models.IntegerField(primary_key=True, max_length=50)
name = models.CharField(max_length=50)
last = models.CharField(max_length=50)
def __unicode__(self):
return self.player_id
class BatStat (models.Model):
player_id = models.ForeignKey('Player_Bios')
team_id = models.ForeignKey('Team')
bat_stat_id = models.CharField(max_length=50, unique=True)
sport_code = models.CharField(max_length=50, blank=True)
ab = models.IntegerField(max_length=50, null=True)
def __unicode__(self):
return self.bat_stat_id
My View:
def SpecificPLayer(request, playerslug):
player = Player_Bios.objects.get(player_id=playerslug) #this is the name, last and it is working fine
playerStat = BatStat.objects.filter(player_id=playerslug) #Here I'm calling the foreign key
print playerStat
context = {'player' : player, 'today' : date.today(), 'playerStat' : playerStat }
return render_to_response ('singleplayer.html', context, context_instance=RequestContext(request))
My HTML Template:
{% extends 'base.html' %}
{% block content %}
<div id="singleplayer">
<p>Name: {{ player.name|capfirst }}</p>
<p>Last Name: {{ player.last|capfirst }}</p>
</div>
{% endfor %}
{% endblock %}
Now when I do print playerStat, I get all of the BatStat from the player_id. In y case I get the following:
[<BatStat: 40539520011>, <BatStat: 40539520021>, <BatStat: 40539520031>]
I get the result that I want on the shell by doing the following:
playerStatID=BatStat.objects.filter(player_id='the player id here')
print playerStatID
[<BatStat: 40539520011>, <BatStat: 40539520021>, <BatStat: 40539520031>]
for i in playerStatID:
playerStat= BatStat.objects.get(bat_stat_id=i)
print BatStat.ab
200
So by doing that I can get the information that I need it, now how can I get that, but to put it on the template. I can't use a loop on the template to get a query, so I guess the loop has to be done on the view, but how. Thanks
Since you have a ForeignKey between BatStat and Player_Bios, you can use a batstat_set to get all related BatStats for the single player.
[Docs for _set here.][1]
So you would have your views.py as:
def SpecificPLayer(request, playerslug):
player = Player_Bios.objects.get(player_id=playerslug) #this is the name, last and it is working fine
batstats = player.batstat_set.all()
context = {'player' : player, 'today' : date.today(), 'batstats': batstats, }
return render_to_response ('singleplayer.html', context,context_instance=RequestContext(request))
and in your template:
{% for stat in batstats %}
{{ stat.ab }}
{% endfor %}

Categories

Resources