Django filter child by parent - django

I'm trying to filter children by its parent in my templates. Example being I have houses that are displayed and want to display their amenities(children) along with them. When I try and do so each house list all amenities for every house. How would I make is so that I list a house and only its amenities?
Here are my models:
class Home(models.Model):
name = models.CharField(max_length=255)
photo = models.ImageField()
def __str__(self):
return self.name
class Amenities(models.Model):
home = models.ForeignKey(Home)
amenities = models.CharField(max_length=255)
In my views I am trying to filter the child by its parent:
def index(request):
home = Home.objects.filter()
amenities = Amenities.objects.filter(home=home)
return render(request, 'home/home.html', {'home': home, 'amenities': amenities})
In my template I am try and loop through each home and their amenities like so:
{% for house in home %}
<div class="row">
<div class="col-md-6 portfolio-item">
<a href="house1.html">
<img class="img-responsive" src=" media/{{ house.photo }}" alt="">
</a>
<h3>
House
</h3>
<ul>
{% for i in amenities %}
<li>{{ i.amenities }}</li>
{% endfor %}
</ul>
</div>
</div>
{% endfor %}
thank you

I think you are looking for this
{% for house in home %}
<div class="row">
<div class="col-md-6 portfolio-item">
<a href="house1.html">
<img class="img-responsive" src=" media/{{ house.photo }}" alt="">
</a>
<h3>
House
</h3>
<ul>
{% for i in house.amenities_set.all %}
<li>{{ i.amenities }}</li>
{% endfor %}
</ul>
</div>
</div>
{% endfor %}

Related

DJ-Stripe metadata not attaching to product

I am following this guide:
https://www.saaspegasus.com/guides/django-stripe-integrate/#contents
I get to "Adding metadata to your Stripe objects" and am told to create a metadata.py file. It doesn't tell me where to import #dataclass and List from so I had to guess. The issue is that, moving forward from this point in the guide, the metadata does not print to my template but I can retrieve product information. I'm thinking this guide is missing or assuming I know stuff about metadata that is required to make it work.
my metadata.py:
from dataclasses import dataclass
from pip import List
from project.subscriptions import features
#dataclass
class ProductMetadata(object):
"""
Metadata for a Stripe product.
"""
stripe_id: str
name: str
features: List[str]
description: str = ''
is_default: bool = False
PREMIUM = ProductMetadata(
stripe_id='<prod id>',
name='Premium',
description='yerp',
is_default=False,
features=[
features.UNLIMITED_WIDGETS,
features.LUDICROUS_MODE,
features.PRIORITY_SUPPORT,
],
)
features.py:
UNLIMITED_WIDGETS = 'Unlimited Widgets'
LUDICROUS_MODE = 'Ludicrous Mode'
PRIORITY_SUPPORT = 'Priority Support'
views:
from django.shortcuts import render
from djstripe.models import Product
def pricing_page(request):
context = {
'products': Product.objects.all()
}
return render(request,'subscriptions/pricing_page.html', context=context)
urls:
path('pricing_page/', view=pricing_page, name='pricing_page'),
template:
{% extends "base.html" %}{% load static socialaccount %}
{% block content %}
<h1>Plans</h1>
<section>
<p class="title">Pricing Plans</p>
<div class="columns">
{% for product in products %}
<div class="column">
<p class="subtitle">{{ product.name }}</p>
{% for plan in product.plan_set.all %}
<div>
<p class="heading">{{ plan.nickname }}</p>
<p>{{ plan.human_readable_price }}</p>
</div>
{% endfor %}
</div>
{% endfor %}
</div>
</section>
<div class="plan-interval-selector">
{% for plan in plans %}
<button class="button">{{ plan.name }}</button>
{% endfor %}
</div>
<div class="columns plan-selector">
{% for product in products %}
{{ product.metadata|pprint }}
<div class="column">
<div {% if product.metadata.is_default %}class="is-selected"{% endif %}>
<span class="icon">
<i class="fa {% if product.metadata.is_default %}fa-check{% else %}fa-circle{% endif %}">
</i>
</span>
<p class="plan-name">{{ product.metadata.name }}</p>
<p class="plan-description">{{ product.metadata.description }}</p>
<div class="plan-price">
<span class="price">{{ product.metadata.monthly_price }}</span> / month
</div>
<ul class="features">
{% for feature in product.metadata.features %}
<li>
<span class="icon"><i class="fa fa-check"></i></span>
<span class="feature">{{ feature }}</span>
</li>
{% endfor %}
</ul>
</div>
</div>
{% endfor %}
</div>
{% endblock content %}
The first forloop gets attributes directly from the product and it works. The second one tries to get the attributes from the metadata. It loops for each product but does not output the metadata. Any advice?

How to display child element in Django MPTT?

I am trying to call parent and child element of a model, I have gone through the MPTT model documentation. I did as mentioned on the documentation, but my template is failing to print children
What can be the possible cause of this problem?
Here is my Views:
def category_view(request):
category = Categories.objects.all()
brands = Brands.objects.all()
context ={
'category':category,
'brands':brands,
}
return render(request,'./ecommerce/categories.html', context)
and Here is my template HTML:
{% load mptt_tags %}
{% recursetree category%}
<div class="category-wrap mb-4">
<div class="category category-group-image br-sm">
<div class="category-content">
<h4 class="category-name">{{ node.name }}
</h4>
<ul class="category-list">
{% if not node.is_leaf_node %}
<li>{{children}}</li>
{% endif %}
</ul>
</div>
</div>
</div>
<!-- End of Category Wrap -->
{% endrecursetree %}
Parent element is printed but children element is not being printed
Doing a lot of hit and trial, generic approach solved my problem. Others having similar problem could be benefited from my answer, hence posting the solution.
Views:
category = Categories.objects.filter(parent=None)
Template:
{% for category in categories %}
<div class="category-wrap mb-4">
<div class="category category-group-image br-sm">
<div class="category-content">
<h4 class="category-name">{{ category.name }}
</h4>
<ul class="category-list">
{% for cat in category.get_children %}
<li>{{ cat.name }} </li>
{% endfor %}
</ul>
</div>
</div>
</div>
<!-- End of Category Wrap -->
{% endfor %}

How to create a search function on a class-based list view?

I am trying to create a search function based on the title of my posts. Right now I am trying to implement this search using a filter but the list view is not rendering. I am unsure if I should implement a URL for my search function.
This is my model:
class Post(models.Model):
title = models.CharField(max_length=100)
image = models.ImageField(default = 'default0.jpg', upload_to='course_image/')
description = models.TextField()
price = models.DecimalField(decimal_places=2, max_digits=6)
date_posted = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE)
feedback = models.ManyToManyField(Feedback)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('post-detail', kwargs={'pk' : self.pk})
This is my class-based list view:
class PostListView(ListView):
model = Post
template_name = 'store/sub_home.html' # <app>/<model>_<viewtype>.html
context_object_name = 'posts'
ordering = ['date_posted']
paginate_by = 12
def get_queryset(self):
object_list = super(PostListView, self).get_queryset()
search = self.request.GET.get('q', None)
if search:
object_list = object_list.filter(title__icontains = title)
return object_list
This is my search bar:
<div id="search">
<form method='GET' action=''>
<input type="text" name='q' placeholder="">
<button id='search_holder'>
<img src="/static/store/search_icon.gif" id="search_icon">
</button>
</form>
</div>
This is my html that is rendering the posts:
{% extends "store/base.html" %}
{% block content %}
{% include "store/home_ext.html" %}
<div style="padding-top: 20px;" id="main" >
<section class="text-center mb-4">
<div class="row" id="random">
{% for post in posts %}
{% include "store/card.html" %}
{% endfor %}
</div>
<div class="row" id="subscription" style="display: none;">
{% if not subs %}
<h2>You have not subscribed to any course :/</h2>
{% endif %}
{% for post in subs %}
{% include "store/card.html" %}
{% endfor %}
</div>
<div class="row" id="content" style="display: none;">
{% if not mine %}
<h2>You have not published anything :/</h2>
{% endif %}
{% for post in mine %}
{% include "store/card.html" %}
{% endfor %}
</div>
</section>
{% include "store/pagination.html" %}
</div>
{% endblock content %}
This is my card.html:
{% load extra_filter %}
<div class="col-lg-3 col-md-6 mb-4">
<div id="course_card">
<div class="view overlay">
<img style="margin-left: -10px;" src="{{ post.image.url }}" alt="">
</div>
<div>
<div>
<strong>
{% if user.is_authenticated %}
<a class="title" href="{% url 'post-detail' post.id %}" >
{% else %}
<a class="title" href="{% url 'login' %}" >
{% endif %}
{% if post.title|length < 30 %}
<span>{{ post.title }}</span>
{% else %}
<span>{{ post.title|cut:27 }}</span>
{% endif %}
<span style="background-color: rgb(253, 98, 98);" class="badge badge-pill danger-color">NEW
</span>
</a>
</strong>
</div>
<div class="star-ratings-css">
<div class="star-ratings-css-top" style="width: {{ post.feedback|calc_rating }}%"><span>★</span><span>★</span><span>★</span><span>★</span><span>★</span></div>
<div class="star-ratings-css-bottom"><span>★</span><span>★</span><span>★</span><span>★</span><span>★</span></div>
</div>
<a href="{% url 'user-posts' post.author.username %}" class="author">
by {{ post.author }}
</a>
<div>
<strong style="text-align: right;" class="price">S${{ post.price }}
</strong>
</div>
<small class="date">
{{ post.date_posted|date:'d F y'}}
</small>
</div>
</div>
</div>
As Nalin Dobhal mentioned in comments, context_object_name should be posts not post. Because in template, you are iterating through posts context variable. Also, when using search functionality, the implementation should be like this:
class PostListView(ListView):
model = Post
template_name = 'store/sub_home.html' # /_.html
context_object_name = 'posts'
ordering = ['date_posted']
paginate_by = 12
def get_queryset(self, *args, **kwargs):
object_list = super(PostListView, self).get_queryset(*args, **kwargs)
search = self.request.GET.get('q', None)
if search:
object_list = object_list.filter(title__icontains = search)
return object_list
Because you are sending the search query through URL querystring(ie: url will look like /posts/?q=title in browser). I am using request.GET.get('q') to fetch those query string values, and use it to filter the queryset.

My generic DetailView not showing list of items

I am following a django tutorial series, the music website contains the ListView which contains Albums(this is showing) but the DetailView Containing the list of songs in each Album is not showing.
I have tried changing the iteration name in the for loop but it still not working, the list shows when i am not using the generic method i.e using index and detail function instead of the IndexView and DetailView classes.
MY music.views Code
class IndexView(generic.ListView):
template_name='music/index.html'
def get_queryset(self):
return Albums.objects.all()
class DetailView(generic.DetailView):
model = Albums
template_name = 'music/detail.html'
My detail.html code which is supposed to show the list of songs but not working
{% extends 'music/base.html' %}
{% block title %} Album Details {% endblock %}
{% block body %}
<img src ="{{ all_album.alb_logo }}">
<h1>{{ all_album.alb_title }}</h1>
<ul>
{% for song in all_album.song_set.all %}
<li>{{ song.song_title }} </li>
{% endfor %}
</ul>
<br>
{% endblock %}
My index.html which shows the list of albums, this is working
{% extends 'music/base.html' %}
{% block body %}
<h2>List of Current albums available</h2>
<div class='container-fluid'>
<div class='row'>
{% for album in object_list %}
<div class='col-lg-4'>
<div class="card" style="width: 18rem;">
<img class="card-img-top" src="{{ album.alb_logo }}" >
<div class="card-body">
<h5 class="card-title">{{ album.alb_title }}</h5>
<p class="card-text">{{ album.alb_artist }}</p>
<a href="{% url 'music:detail' album.id %}" class="btn
btn-primary btn-sm">View details</a>
</div>
</div>
</div>
{% endfor %}
</div>
</div>
My urls.py code#
urlpatterns = [
path('',views.IndexView.as_view(), name='index'),
path('<int:pk>/', views.DetailView.as_view(), name='detail'),
]
The detail.html page is expected to show the list of songs in a selected album that is already in the database when clicked, but it is not showing.
You were using the wrong context variable name(all_album) inside the template, it should be object.
#detail.html
{% extends 'music/base.html' %}
{% block title %} Album Details {% endblock %}
{% block body %}
<img src="{{ object.alb_logo }}">
<h1>{{ object.alb_title }}</h1>
<ul>
{% for song in object.song_set.all %}
<li>{{ song.song_title }} </li>
{% endfor %}
</ul>
<br>
{% endblock %}
Reference: DetailView get_context_data() method--Django Doc

Users created posts not being returned to template? Django

the user is able to create a post and it will be shown the in the list. I've also created a users profile/summary page where the user can edit/delete their posts.
Currently, it's showing blank and I'm not quite sure why?Am I supposed to get the instance or is it fine the way it is?
Model
class Aircraft(AircraftModelBase):
user = models.ForeignKey(User)
manufacturer = SortableForeignKey(Manufacturer)
aircraft_type = SortableForeignKey(AircraftType)
View
def upload_overview(request):
uploaded_aircraft = Aircraft.objects.filter(user=request.user)
return render(request,'account/upload_overview.html',{'UploadedAircraft':uploaded_aircraft})
Template
<div class="container">
<div class="row aircraft">
{% if UploadedAircraft %}
{% for upload in UploadedAircraft %}
<div class="col-lg-offset-0 col-md-4 col-sm-3 item">
<div class="box"><img src="{{ upload.aircraft.image.url }}" width="200px" height="200px" alt="{{ upload.aircraft.title }}"/>
<h3 class="name">{{ upload.aircraft.name }}</h3>
</div>
</div>
{% endfor %}
{% else %}
<h2 class="text-center">No uploaded aircraft posts..</h2></div>
{% endif %}
</div>