I'm trying to show information from two models, in a single view in a Django project.
I have 2 models: Main (parent), Visits (child)
I would like to show a details view of Main (name, date of birth) and then show a list of the Visits. Effectively, show one record from parent table, and all the related children tables. But the children tables are only partially showing up (see the image).
Also, can someone tell me how the Django code knows to render only the child records that are associated with the parent record (where/when are foreign keys filtered?)
Image showing the problem
eg:
Main.name
Visit.date - Visit.type
Visit.date - Visit.type
Visit.date - Visit.type
views.py
class MainDetailView(generic.DetailView):
model = Main
template_name = "myapp/main-detail.html"
def get_context_data(self, **kwargs):
context = super(MainDetailView, self).get_context_data(**kwargs)
context['visit'] = Visit.objects.all()
# And so on for more models
return context
models.py
class Visit(models.Model):
fk_visit_patient = models.ForeignKey(Main, on_delete=models.CASCADE,
verbose_name=('Patient Name'))
visit_date = models.DateField()
visit_label = models.CharField(max_length=256, blank=True, null=True)
visit_specialty_list = (
(str(1), 'General Practice'),
(str(2), 'Internal Medicine'),
(str(3), 'Surgery'),
visit_specialty = models.CharField(
max_length=256,
choices=visit_specialty_list,
default=1, )
def __str__(self):
return str(self.visit_label)
def get_absolute_url(self):
return reverse('myapp:main-detail', kwargs={'pk': self.pk})
template.html
<div class="container-fluid">
<div class="row">
<div class="col-sm-12 col-md-7">
<div class="'panel panel-default">
<div class="panel-body">
<h1>{{ main.name }}</h1>
<p><strong>Date of Birth:</strong> {{ main.date_of_birth }}</p>
<div style="margin-left:20px;margin-top:20px">
<h4>Visits</h4>
{% for visit in main.visit_set.all %}
<li>{{ Visit.visit_date }} - {{ Visit.visit_specialty }}</li>
{% endfor %}
</div>
</div>
</div>
</div>
</div>
</div>
You loop defines the variable as visit, but inside you refer to Visit. You need to be consistent.
{% for visit in main.visit_set.all %}
<li>{{ visit.visit_date }} - {{ visit.visit_specialty }}</li>
{% endfor %}
Note, there is no need to pass the Visits separately to the template as you are doing in get_context_data - you should remove that method completely.
Related
I have two models, ProjectNotes and ProjectNoteComments. ProjectNoteComments are related to ProjectNotes via a foreign key. I want to display the number of comments each note has on a listview. I am just learning Django and so far I have not been able to figure out how to retrieve and display the comment count.
My view:
(I do import count)
class ProjectNotesList(ListView):
model = ProjectNotes
template_name = 'company_accounts/project_notes.html'
comments = ProjectNotes.comments
def related_project(self, **kwargs):
project = get_object_or_404(Project, id=self.kwargs.get('pk'))
notes = ProjectNotes.objects.all
return notes
def get_context_data(self, **kwargs):
# Call the base implementation first to get a context
context = super().get_context_data(**kwargs)
context['project'] = get_object_or_404(Project, id=self.kwargs.get('pk'))
return context
commentscount = ProjectNotes.objects.annotate(num_comments=Count('comments'))
My template:
{% extends 'base.html' %}
{% block content %}
<div class="section-container container">
<h1>Notes for {{ project }}</h1>
{% if project.notes.all %}
{% for note in project.notes.all %}
<div class ="projectnotes-entry">
<div class="col-sm-8">
<div class="row-sm-6">
<div class="card mb-2">
<div class="card-body">
<div class="card-title">{{ note.title }}</div>
<div class="card-text">{{ note.body | safe | truncatewords:"20"|linebreaks }}
read more</div>
</div>
</div>
</div>
</div>
</div>
<h2>comments count</h2>
{{ commentscount }}
{% endfor %}
{% else %}
<p>No notes have been have been added yet.</p>
{% endif %}
</div>
{% endblock content %}
The models:
class ProjectNotes(models.Model):
title = models.CharField(max_length=200)
body = tinymce_models.HTMLField()
date = models.DateField(auto_now_add=True)
project = models.ForeignKey(Project, default=0, blank=True, on_delete=models.CASCADE, related_name='notes')
def __str__(self):
return self.title
class ProjectNoteComments(models.Model):
body = tinymce_models.HTMLField()
date = models.DateField(auto_now_add=True)
projectnote = models.ForeignKey(ProjectNotes, default=0, blank=True, on_delete=models.CASCADE, related_name='comments')
Short version:
{{ note.comments.all.count }} # possibly works also without 'all' but can't check right now
I've just answered similar problem with simple explanation of relationships.
https://stackoverflow.com/a/70955851/12775662
Read official docs, it's really rewarding. https://docs.djangoproject.com/en/4.0/topics/db/models/#relationships
I would like to add information in a form, coming from the model linked with a M2M relationship to the model I'm updating.The form works properly, but I'm not able to add any information.
Here is what I get:
Here is the expected result:
My solution: finally, I updated __str__() mthod in UserGroup model to display what I expect (but, at this stage, I lost the dynamic part and my view does not work anymore :-/)
The main model is Event and it's linked to Groups thanks to this relationship; in the form, all groups are listed and displayed with checkboxes, but I'm only able to display the groups' name, no other information.
It looks like I miss some data / information: the group name is displayed only because I use {{grp}}} (see below) but it has no attribute / filed available, even if it is initialized with a query from the group model.
I envisaged a workaround (see below) because my first tries made me consider this kind of solution, but I'm not able to reproduce what I did :-/
Any idea of what I did wrong, or any advice to manage this? Thanks in advance.
Here are related code parts.
Models:
class UserGroup(models.Model):
company = models.ForeignKey(
Company, on_delete=models.CASCADE, verbose_name="société"
)
users = models.ManyToManyField(UserComp, verbose_name="utilisateurs", blank=True)
group_name = models.CharField("nom", max_length=100)
weight = models.IntegerField("poids", default=0)
hidden = models.BooleanField(default=False)
def __str__(self):
return self.group_name
class Event(models.Model):
company = models.ForeignKey(
Company, on_delete=models.CASCADE, verbose_name="société"
)
groups = models.ManyToManyField(UserGroup, verbose_name="groupes", blank=True)
rules = [("MAJ", "Majorité"), ("PROP", "Proportionnelle")]
event_name = models.CharField("nom", max_length=200)
event_date = models.DateField("date de l'événement")
slug = models.SlugField()
current = models.BooleanField("en cours", default=False)
quorum = models.IntegerField(default=33)
rule = models.CharField(
"mode de scrutin", max_length=5, choices=rules, default="MAJ"
)
class Meta:
verbose_name = "Evénement"
constraints = [
models.UniqueConstraint(fields=["company_id", "slug"], name="unique_event_slug")
]
def __str__(self):
return self.event_name
Form:
class EventDetail(forms.ModelForm):
groups = forms.ModelMultipleChoiceField(
label = "Liste des groupes",
queryset = None,
widget = forms.CheckboxSelectMultiple,
required = False
)
class Meta:
model = Event
fields = ['event_name', 'event_date', 'quorum', 'rule', 'groups']
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
instance = kwargs.get('instance', None)
self.fields['groups'].queryset= UserGroup.objects.\
filter(company=instance.company).\
order_by('group_name')
View:
#user_passes_test(lambda u: u.is_superuser or (u.id is not None and u.usercomp.is_admin))
def adm_event_detail(request, comp_slug, evt_id=0):
'''
Manage events creation and options
'''
company = Company.get_company(request.session['comp_slug'])
# all_groups = list(UserGroup.objects.filter(company=company, hidden=False).order_by('group_name').values())
if evt_id > 0:
current_event = Event.objects.get(id=evt_id)
event_form = EventDetail(request.POST or None, instance=current_event)
else:
event_form = EventDetail(request.POST or None)
event_form.fields['groups'].queryset = UserGroup.objects.\
filter(company=company, hidden=False).\
order_by('group_name')
if request.method == 'POST':
if event_form.is_valid():
if evt_id == 0:
# Create new event
event_data = {
"company": company,
"groups": event_form.cleaned_data["groups"],
"event_name": event_form.cleaned_data["event_name"],
"event_date": event_form.cleaned_data["event_date"],
"quorum": event_form.cleaned_data["quorum"],
"rule":event_form.cleaned_data["rule"]
}
new_event = Event.create_event(event_data)
else:
new_event = event_form.save()
else:
print("****** FORMULAIRE NON VALIDE *******")
print(event_form.errors)
return render(request, "polls/adm_event_detail.html", locals())
HTML (I did not put each parts of the 'accordion' widget, I do not think they have anything to do with the problem):
{% if evt_id %}
<form action="{% url 'polls:adm_event_detail' company.comp_slug evt_id %}" method="post">
{% else %}
<form action="{% url 'polls:adm_create_event' company.comp_slug %}" method="post">
{% endif %}
{% csrf_token %}
<!-- Hidden field where the referer is identified to go back to the related page after validation -->
<input type="hidden" name="url_dest" value="{{ url_dest }}" />
<br>
<!-- Accordion -->
<div id="eventDetails" class="accordion shadow">
<div class="card">
<div class="card-header bg-white shadow-sm border-0">
<h6 class="mb-0 font-weight-bold">
Evénement
</h6>
</div>
<div class="card-body p-5">
<p>Nom : {{event_form.event_name}} </p>
<p>Date : {{event_form.event_date}} </p>
</div>
</div>
<!-- Accordion item 2 - Event's groups -->
<div class="card">
<div id="headingTwo" class="card-header bg-white shadow-sm border-0">
<h6 class="mb-0 font-weight-bold">
<a href="#" data-toggle="collapse" data-target="#collapseTwo" aria-expanded="false" aria-controls="collapseTwo" class="d-block position-relative collapsed text-dark collapsible-link py-2">
Groupes d'utilisateurs
</a>
</h6>
</div>
<div id="collapseTwo" aria-labelledby="headingTwo" data-parent="#eventDetails" class="collapse show">
<div class="card-body p-5">
<p>Sélectionnez le(s) groupe(s) d'utilisateurs participants à l'événement :</p>
<ul>
{% for grp in event_form.groups %}
<li>{{ grp }}
{{ grp.weight }}
{{ grp.hidden }}
{{ grp.nb_users }}
</li>
{% endfor %}
</ul>
<p></p>
</div>
</div>
</div>
</div> <!-- Accordion end -->
<button class="btn btn-success mt-5" type="submit">{% if evt_id %}Mettre à jour{% else %}Créer{% endif %}</button>
     
<a class="btn btn-secondary back_btn mt-5" href="*">Annuler</a>
<div class="row">
<div hidden>
<!-- List of groups in event -->
{{ event_form.group_list }}
</div>
</div>
</form>
Workaround
If it's not possible to achieve this directly, I thought to a workaround that would be implemented in several parts:
Create a list almost like the queryset: group_list = UserGroup.objects.filter(company=instance.company).order_by('group_name').values()
I already know I can display each group with its details and a checkbox
on client side (javascript), I manage an hidden list that would be part of the form, with the ID of each selected group. That means that the list will be dynamically updated when a box is checked on unchecked
on the POST request, read the list to update the group attribute of updated event.
I would have prefered the users actions having effect directly to the form, but I know this could work
You're accessing the form's groups field, not the model instance. The form field doesn't have any relationship to other models, it's just a field. You can access the underlying instance of the model form using form.instance.
Also note that you get a relationship manager object when querying related models. Hence, use .all to query all groups.
Try
<ul>
{% for grp in event_form.instance.groups.all %}
<li>{{ grp }}
{{ grp.weight }}
{{ grp.hidden }}
{{ grp.nb_users }}
</li>
{% endfor %}
</ul>
Model
class Category(models.Model):
class Meta():
verbose_name_plural = "Categories"
cat_name = models.CharField(max_length=50)
description = models.TextField()
def get_forums(self):
get_forum = Forum.objects.filter(category=self)
return get_forum
def __str__(self):
return f"{self.cat_name}"
class Forum(models.Model):
class Meta():
verbose_name_plural = "Forums"
category = models.ForeignKey(Category, on_delete=models.CASCADE, related_name="forums")
parent = models.ForeignKey('self', blank=True, null=True, on_delete=models.CASCADE)
forum_name = models.CharField(max_length=50)
description = models.TextField()
def __str__(self):
return f"{self.forum_name}"
Views
class Home(ListView):
model = Category
template_name = 'forums/index.html'
context_object_name = 'category'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['cat'] = Category.objects.all()
return context
HTML
{% block content %}
{% for cat in category %}
<div class="row">
<div class="bg-success rounded-top border border-dark" style="width:100%; padding-left:8px;">
{{cat.cat_name}}
</div>
</div>
<div class="row">
<div class="bg-secondary border border-dark" style="width:100%; padding-left:16px;">
Forums_Go_Here
</div>
</div>
{% endfor %}
{% endblock content %}
I am trying to get a homepage where I would be able to list my categories and show the forums in those categories.
The template I have is running a for loop which is looping through all Categories.
In the shell i am able to get the forums with the: Category.objects.get(pk=2).get_forums() command. But this limits it to one category.
You can use related name for that, no need to use additional method:
{% block content %}
{% for cat in category %}
<div class="row">
<div class="bg-success rounded-top border border-dark" style="width:100%; padding-left:8px;">
{{cat.cat_name}}
</div>
</div>
{% for forum in cat.forums.all %}
<div class="row">
<div class="bg-secondary border border-dark" style="width:100%; padding-left:16px;">
{{forum.forum_name}}
</div>
</div>
{% endfor%}
{% endfor %}
{% endblock content %}
Also you have a mistake there:
context['category'] = Category.objects.all()
If you want to access it as category in template put it there with that key, not cat.
I'm trying to set up magnific popup on django.
My goal is to have one main picture in the homepage overview gallery view, which when clicked, would open a popup with the related images from the same photoshoot i.e. images with the same ID or PK.
I tried to apply the following approach
but i just cannot get it to work, maybe someone could help me out in this
My models.py
class Item(models.Model):
name = models.CharField(blank=False, max_length=200)
category = models.ForeignKey(Category, blank=True, null=True, on_delete=models.SET_NULL)
order = models.IntegerField(blank=True, null=True)
active = models.BooleanField(blank=True, default=False)
objects = models.Manager()
class Meta:
verbose_name_plural = 'items'
def __str__(self):
return self.name
class ItemImage(models.Model):
image = ProcessedImageField(
blank=True,
null=True,
processors=[ResizeToFit(width=1680, upscale=False)],
format='JPEG',
options={'quality':90})
order = models.IntegerField(blank=True, null=True)
main = models.BooleanField(blank=True, default=False)
cover = models.BooleanField(blank=True, default=False)
item = models.ForeignKey(Item, related_name='items', blank=True, null=True, on_delete=models.SET_NULL)
objects = models.Manager()
class Meta:
verbose_name_plural = 'item images'
Views.py
def portraits(request):
port = ItemImage.objects.filter(item__category__slug='portraits', item__active=True, main=True,).order_by('item__order')
portall = ItemImage.objects.filter(item__category__slug='portraits', item__active=True).order_by('item__order')
context = {
'main_portraits': port,
'all_portraits': portall
}
return render(request, 'gallery/portraits.html', context)
and Template:
{% block content %}
<div class="grid">
{% for pic in main_portraits %}
<div class="item">
<div class="item">
<div class="outer-text">
<div class="text">
{{ pic.item.name }}
<p>Click to view gallery</p>
</div>
</div>
<a><img class="lazy" alt=""
sizes="(min-width:1400px) 1220px
(min-width:1000px) 1000px,
(min-width:500px) 700px,
(min-width:320px) 420px,
280px"
srcset="{{ pic.image_xs.url }} 280w,
{{ pic.image_s.url }} 420w,
{{ pic.image_m.url }} 700w,
{{ pic.image_l.url }} 1000w,
{{ pic.image_xl.url }} 1220w" />
</a> {{ pic.item.pk }}
</div>
<div class="lazy">
{% for p in all_portraits %}
{% endfor %}
</div>
</div>
{% endfor %}
</div>
{% endblock %}
I have set
z.item.pk
just as a test, to see if any of my manipulations result in the pk's to bunch up. For example the first for-loop returns a picture with PK "24", I need for the second for-lop to return only images with the same PK; and so for every image. I think the answer might be connected with _set.all function, just like in the related question above, but I cant seem to get it to work in my case. Feels like I'm missing something here.
current output:
<div class="grid">
<div class="item">
<div class="item">
<div class="outer-text">
<div class="text">
Palagā tītā
<p>Click to view gallery</p>
</div>
</div>
<a><img class="lazy" alt=""
sizes="(min-width:1400px) 1220px
(min-width:1000px) 1000px,
(min-width:500px) 700px,
(min-width:320px) 420px,
280px"
srcset="/media/CACHE/images/IMG_8329_3Vi8mYO_GD621ql/958ba5dbee5efe28fd2f5054b8f819e1.jpg 280w,
/media/CACHE/images/IMG_8329_3Vi8mYO_GD621ql/02d12ca7f0633fee2fc762cf96f7889e.jpg 420w,
/media/CACHE/images/IMG_8329_3Vi8mYO_GD621ql/ba5fa6633e92a288e3b2f47a713d64c2.jpg 700w,
/media/CACHE/images/IMG_8329_3Vi8mYO_GD621ql/fe0d559fef5b02434c43f841005d4961.jpg 1000w,
/media/CACHE/images/IMG_8329_3Vi8mYO_GD621ql/96d0e52dff14d1bc4b60bbec674565db.jpg 1220w" />
</a> 24
</div>
<div class="lazy">
</div>
</div>
You need prefiltered querysets containing the related images for every main image before handing over to the template.
def portraits(request):
ports = ItemImage.objects.filter(item__category__slug='portraits', item__active=True, main=True,).order_by('item__order')
for p in ports:
# You may not need the item__category__slug filter
# if there are only images of the same category
# associated with an item.
# Also, if you want to exclude the main image
# from the set of related images, you need to add the filter
# main=False
p.related_images = ItemImage.objects.filter(item__category__slug='portraits', item__id=p.item.id)
context = {
'main_portraits': ports,
}
return render(request, 'gallery/portraits.html', context)
Then you can loop over main_portraits in the template, and get the related images for each main image in a nested loop:
{% for mainp in main_portraits %}
{% for im in mainp.related_images %}
{# do something with the related images #}
{% endfor %}
{% endfor %}
You can break down the models like this it will make the querying easier.
# models.py
class Item(mdoels.Model):
name = models.CharField(blank=False, max_length=200)
category = models.ForeignKey(Category, blank=True, null=True, on_delete=models.SET_NULL)
...
display_image = models.ProcessedImageField(...)
class ItemImage(models.Model):
item = models.ForeignKey(Item, related_name='images', blank=True, null=True, on_delete=models.SET_NULL)
image = models.ProcessedImageField(...)
...
#views.py
def portraits(request):
items = Item.objects.filter(category__slug='portraits', active=True)
return render(request, 'gallery/portraits.html', context={items: items})
#template
{% for item in items %}
<h1> {{item.name}} </h1>
<img src={{item.display_image}} />
{% for item_image in item.images.all %}
<img src={{item_image.image}} />
{% endfor %}
{% endfor %}
I would like to add some Order details(DetailView) in the Order history page(ListView), See image example below ( I have made the image on photoshop). I was able to get the grey part (order list to show) But I am not able to get the item details to show in this page correctly. If I click View Order Detail it goes to detail page where I can show all this. But I need a small summary in the ListPage too. See example below. How do I change my views or templates to achieve this? See my views and templates below
Below is how I need my order history page to look like
Below are my my models.py
class Order(models.Model):
token = models.CharField(max_length=250, blank=True)
total = models.DecimalField(max_digits=6, decimal_places=2, verbose_name='USD Order Total')
emailAddress = models.EmailField(max_length=100, blank=True, verbose_name='Email Address')
created = models.DateTimeField(auto_now_add=True)
billingName = models.CharField(max_length=350, blank=True)
billingAddress1 = models.CharField(max_length=350, blank=True)
billingCity = models.CharField(max_length=100, blank=True)
billingZipcode = models.CharField(max_length=10, blank=True)
billingCountry = models.CharField(max_length=50, blank=True)
class OrderItem(models.Model):
product = models.CharField(max_length=250)
quantity = models.IntegerField()
price = models.DecimalField(max_digits=5, decimal_places=2, verbose_name='USD Price')
order = models.ForeignKey(Order, on_delete=models.CASCADE)
image = models.ImageField()
Below is my template
{% block body %}
<div>
<div class="text-center">
<br/>
<h1 class="text-center my_title">Order Purchase History</h1>
<br/>
{% if order_details %}
{% for order in order_details %}
<div class="row order_detail_div" >
<div class="col-md-2">
<b>Order Number: 1234{{ order.id }}</b><br/>
<small><em>Order Date: {{ order.created|date:"M d Y" }}</em></small>
</div>
<div class="col-md-1"></div>
<div class="col-md-3 text-left">
<b>Status: Paid</b><br/>
<b>Total items in Order: ()</b>
</div>
<div class="col-md-1"></div>
<div class="col-md-3 order_total_text">
<b>Order Total: ${{ order.total }}</b>
</div>
<div class="col-md-2 view_order_details">
<b>View Order Details</b>
</div>
</div>
{% for item in order_items %} <!-- This gets the order items from the Order -->
<div class="row order_item_detail_div">
<div class="col-md-2">
<img src="{{ item.image }}" >
</div>
<div class="col-md-2">
{{ item.product}}
</div>
<div class="col-md-2">
{{ item.id}}
</div>
<div class="col-md-2">
{{ item.quantity}}
</div>
<div class="col-md-2">
{{ item.price}}
</div>
</div>
{% endfor %}
<br/>
{% endfor %}
{% else %}
<p>
You do not have any orders yet.<br/><br/>
Add more recipes
</p>
{% endif %}
</div>
</div>
<br/>
<br/>
{% endblock %}
Views.py 1st try
Error: For some reason the print statement in terminal shows correctly but in the browser it shows. See image below code
class OrderHistory(LoginRequiredMixin, ListView):
model = Order
template_name = 'order/order_list.html'
def get_context_data(self, **kwargs):
context = super(OrderHistory, self).get_context_data()
context['order_details'] = Order.objects.filter(emailAddress=self.request.user.email) #The code is correct till here
order_details = Order.objects.filter(emailAddress=self.request.user.email)
for order in order_details:
print("Order items are", OrderItem.objects.filter(order=order))
context['order_items'] = OrderItem.objects.filter(order=order)
return context
The Order details in grey are correct but the OrderItems do not correspond to the order. It should be like in the 1st image(above)
Views.py 2nd try Error: I thought will do OrderItem.objects.all()) in the views.py and the forloop in the template will fix the view but below is the error I get
class OrderHistory(LoginRequiredMixin, ListView):
model = Order
template_name = 'order/order_list.html'
def get_context_data(self, **kwargs):
context = super(OrderHistory, self).get_context_data()
context['order_details'] = Order.objects.filter(emailAddress=self.request.user.email) #The code is correct till here
print("Order items are", OrderItem.objects.all())
context['order_items'] = OrderItem.objects.all()
return context
Again this is not correct these 2 items do not belong to Order. See the 1st image for how it should be. The grey part which contains order details is still correct
Its a bit confusing, but i guess i manage to get the points...
The problem is here... since Django is not dinamic, they will send your data after processing everything to your template... what you doing here is overring every value at your context['order_items'] so they will send to template only the last data.
for order in order_details:
context['order_items'] = OrderItem.objects.filter(order=order)
When you made the change to context['order_items'] = OrderItem.objects.all() without the forloop now you getting all Order Item without set any order... so when you try to show the OrderItem from first Order they will show all OrderItem.
The Sollution is use TEMPLATETAGS so that way you can filter your data while the HTML is processing...
So you need to filter your OrderItem based in your Order... since in your page you will show many orders and you must filter the OrderItem based in this Orders
create one folder called templatetags inside your app, create one file to be your templatetag (dont forget to create __init__.py file too) in that case we will call order_templatetags.py
app/templatetags/order_templatetags.py
from django import template
from .models import OrderItem
register = template.Library()
#register.filter
def filter_order_items(self):
return OrderItem.objects.filter(order__id=self.id)
IN YOUR HTML
<!-- IN TOP OF YOUR HTML (After Extends if you have it) PLACE THIS CODE -->
{% load order_templatetags %}
<!-- REST OF YOUR HTML CODE -->
{% for order in order_details %}
<!-- REST OF YOUR HTML CODE -->
{% for item in order|filter_order_items %} <!-- This gets the order items from the Order -->
<!-- YOUR HTML STUFFS -->
{% endfor %}
{% endfor %}
My Snippet: https://github.com/Diegow3b/django-utils-snippet/blob/master/template_tag.MD
Django Docs: https://docs.djangoproject.com/en/2.0/howto/custom-template-tags/
Well I did finally figure it out
models.py (Add related_name in order field)
class OrderItem(models.Model):
product = models.CharField(max_length=250)
quantity = models.IntegerField()
price = models.DecimalField(max_digits=5, decimal_places=2, verbose_name='USD Price')
order = models.ForeignKey(Order, on_delete=models.CASCADE, related_name="order_cushions")
image = models.ImageField()
views.py is
class OrderHistory(LoginRequiredMixin, ListView):
model = Order
template_name = 'order/order_list.html'
def get_context_data(self, **kwargs):
context = super(OrderHistory, self).get_context_data()
context['order_details'] = Order.objects.filter(emailAddress=self.request.user.email)
print("Order items are", OrderItem.objects.all())
context['order_items'] = OrderItem.objects.all()
return context
and finally in templates.py
{% for order in order_details %}
{% for item in order.order_cushions.all %} #this is the models related_name
{{item.image}} #this will get your image
{{item.product}}
{{item.price}}
{{item.quantity}} #decorate using bootstrap the way you like
{% endfor %}
{% endfor %}
My way was with a method inside Order returning a Queryset
models.py
class Order(models.Model):
...
def items(self):
return OrderItem.objects.filter(order=self)
Call items inside a loop
Orderlist.html
{% for order in order_details %}
{% for item in order.items %}
<!-- YOUR HTML STUFFS -->
{% endfor %}
{% endfor %}