Django queryset for list item - python

I am still fairly new to django and I ran into a problem which I am having a hard time figuring out even with using google or maybe I am not seeing the solution. So I have a model named movieTitles like so:
class movieTitle(models.Model):
title = models.Charfield(max_length=50)
image = models.URLField(max_length=100)
description = models.TextField()
year = models.PositiveSmallIntegerField()
director = models.Charfield(max_length=50)
Then I have my view as so:
from Movie.models import movieTitles
def movieListView(request):
movie = movieTitle.objects.all()
return render(request, 'index.html', {'movies':movie})
and my html as so:
<body>
{% for info in movies %}
{{info.title}}
{% endfor %}
</body>
What I want it to do is once user goes to the movie list and they decide to click on a certain movie, how can I take the user to another html page which will show the info.image, info.description, info.year, and info.director belonging to the movie they decided to click on. I know how to write the template and all that but what im confused on is how can I write the template using {{info.???}} and not having to create a template for every movie to link to but instead use the previous template in which the user chose a movie to create the details in the next template.

You should create a new view, which get a pk of choosen movie and retrives all informations about it.
# Add to urls.py
urlpatterns += [url(r'^detail/(?P<pk>\d+)/$', views.movie_detail, name='movie_detail')]
# Add to views.py
from django.shortcuts import get_object_or_404
def movie_detail(request, pk):
movie = get_object_or_404(movieTitle, pk=pk)
return render(request, 'movie_detail.html', {'movie': movie})
# movie_detail.html
<h1>Title: {{ movie.title }}</h1>
<img src="{{ movie.image }}">
{{ movie.description|linebreaks }}
<p>Year: {{ movie.year }}</p>
<p>Director: {{ movie.director }}</p>
Last thing you should do is to put right url in html with movie list
# Your initial html
<body>
{% for movie in movies %}
{{ movie.title }}
{% endfor %}
</body>
And that's all

add a unique field in ur model like id foreg:-
class movieTitle(models.Model):
id = models.Charfield(max_length=50)
title = models.Charfield(max_length=50)
image = models.URLField(max_length=100)
description = models.TextField()
year = models.PositiveSmallIntegerField()
director = models.Charfield(max_length=50)
and amke a url like this:
supppose app name is:
app_name = 'movie'
url(r'^movie-list/show/(?P<university_id>[0-9]+)/$', view.view_list, name='view-list'),
and pass ur url in template like this:
<body>
{% for info in movies %}
{{info.title}}
{% endfor %}
</body>

Related

How can I lists all the products according to their foreign key?

I am working on my first eshop website using django framework and I got stuck on a problem.
I have created a general model for different kinds of products (like laptops, books etc.). Each product that is added to the website can be found by on its foreign key that links that product to a specific category.
The question is how can I display on laptops.html only the products that have the foreign key which points to the right category? Like, to display only the products from laptops category.
Thank you very much for your time!
EDIT:
in urls:
urlpatterns=[
path('', views.HomePage.as_view(), name='home'),
path('ComputerScience/', views.ComputerScience.as_view(), name='computer_science'),
path('category/<int:category_pk>/list-products/', views.CompSProd.as_view(), name='category_products_list')]
In computerscience.html I render all the cateogries.
Here in views.py I have the two controllers, first for categories and second for laptops for instance.
views.py
class ComputerScience(ListView):
model = ComputerScienceCategory
template_name = "computer_science.html"
context_object_name = "category"
class CompSProd(ListView):
model = ComputerScienceProducts
template_name = "laptops.html"
context_object_name = "products"
def get_queryset(self):
queryset = super().get_queryset()
# If you wish to still keep the view only for specific category use below line
category = get_object_or_404(ComputerScienceCategory, pk=self.kwargs.get('category_pk'))
queryset = queryset.filter(category=category)
return queryset
Here I have the template where I want to display all categories.
computer_science.html
<div class="computerScienceContent" id="slide">
{% for cat in category %}
<a href="{% url 'category_products_list' category.pk %} " id="aBar">
<div>
<h4 class="cSh">{{ cat.name }}</h4>
<img src="{{ cat.img.url }}" alt="image" class="img">
</div>
</a>
{% endfor %}
Here is laptops html, where I'd like to have the whole products displayed.
laptops.html
{% extends 'index.html' %}
{% block title %}
<title>Laptops</title>
{% endblock %}
{% block cont2 %}
{% endblock %}
My main goal is that to have a page (computerscience.html) where I have displayed a list with all available categories and when you click on one category, to redirect you to another page where you have listed all the products that belongs to that category.
This is the error that has been thrown to me:
Reverse for 'category_products_list' with arguments '('',)' not found. 1 pattern(s) tried: ['category/(?P<category_pk>[0-9]+)/list\\-products/$']
You should override get_queryset to filter your objects. Also as you are writing a view for a specific instance of category you would end up writing a lot of views, also when a new category would be added this would be very tedious you should use one view for all categories instead. Try this:
from django.shortcuts import get_object_or_404
class CompSProd(ListView):
model = ComputerScienceProducts
template_name = "laptops.html"
context_object_name = "products"
def get_queryset(self):
queryset = super().get_queryset()
category = get_object_or_404(ComputerScienceCategory, pk=self.kwargs.get('category_pk')) # Assuming category_pk will be passed in url
# If you wish to still keep the view only for specific category use below line
# category = get_object_or_404(ComputerScienceCategory, pk=<pk-of-category-here>)
queryset = queryset.filter(category=category)
return queryset
To pass the categories primary key in the url you need to do something as follows:
In your urls.py:
urlpatterns = [
...
path('category/<int:category_pk>/list-products/', views.CompSProd.as_view(), name='category_products_list'),
...
]
Now in the page where you display all categories:
{% for cat in category %}
<a href="{% url 'category_products_list' cat.pk %}" id="aBar">
<div>
<h4 class="cSh">{{ cat.name }}</h4>
<img src="{{ cat.img.url }}" alt="image" class="img">
</div>
</a>
{% endfor %}
Also you write id="aBar" but this line is in a loop meaning you would end up with multiple same ids you should use a class instead.

How to Get Items in a model connected to another model using a foreign key in detail view in django?

I am trying to create a cartoon streaming website in which when a user clicks on their cartoon of choice(Eg:Pokemon), they get to see the seasons as a list as well as the detail of the cartoons.
from django.db import models
class Cartoon(models.Model):
name = models.CharField(max_length=200)
cover = models.ImageField()
description = models.TextField()
start_date = models.CharField(max_length=50)
end_date = models.CharField(max_length=50)
def __str__(self):
return self.name
class CartoonSeason(models.Model):
cartoon = models.ForeignKey(Cartoon, null=True, on_delete=models.SET_NULL)
number = models.IntegerField()
season_cover = models.ImageField(blank=True, null=False)
season_name = models.CharField(max_length=200, blank=True, null=True)
season_description = models.TextField(blank=True, null=False)
Here I have linked the Cartoon model with the CartoonSeason model using a Foreign Key so when a new season is to be added, it automatically gets linked with the corresponding Cartoon
from django.shortcuts import render
from django.http import HttpResponse
from django.views.generic import ListView, DetailView
from .models import CartoonSeason, Cartoon
class CartoonListView(ListView):
model = Cartoon
template_name = "index.html"
class CartoonSeasonView(DetailView):
queryset = CartoonSeason.objects.filter()
model = CartoonSeason
template_name = "season.html"
I am using a detail view to display the CartoonSeason model so that it displays the Cartoons details as well, but when I try to load the seasons, it only displays the season with the Primary Key of 1. I want it to display all of the seasons added to the cartoon.
Here's my seasons.html
{% extends 'base.html' %}
{% block title %}
test
{% endblock %}
{% block content %}
<main>
<section class="cartoon-description">
<div class="season_head">
<img src="{{object.cartoon.cover.url}}" width="260px" alt="">
<div class="cartoon-name">
<h1>{{object.cartoon.name}}</h1>
<small >{{object.cartoon.start_date}} - {{object.cartoon.end_date}}</small>
<br>
<div class="description">
<strong>Description:</strong>
<br>
<p>{{object.cartoon.description}}</p>
</div>
</div>
</div>
</section>
<hr>
</main>
{% endblock %}
Here is My urls.py
from .views import CartoonListView, CartoonSeasonView
urlpatterns = [
path('', CartoonListView.as_view(), name="home"),
path('cartoon/<int:pk>' , CartoonSeasonView.as_view(), name="cartoon"),
]
This is my main template
{% extends 'base.html'%}
{% block title %}
Home - CartoonsPalace
{% endblock %}
{% block content %}
<main>
<section class="cartoon-list">
<div class="select-text">
<h1>Pick Your Cartoon Series of Choice:-</h1>
</div>
{% for cartoon in object_list %}
<div class="list">
<a href="{% url 'cartoon' cartoon.pk %}"><div class="list-object">
<img src="{{cartoon.cover.url}}" alt="" width="184px">
<h3>{{cartoon.name}}</h3>
<span>{{cartoon.start_date}} - {{cartoon.end_date}}</span>
</div>
</a>
</div>
{% endfor %}
</section>
</main>
{% endblock %}
Any help would be appreciated.
Ok when you want to access all the objects related to another objects through foreign key , you have two simple options :
1.set query using the cartoon(reverse relation):
cartoon = Cartoon.objects.get(id = 'pk') # get the pk by passing in url
cartoon_season = cartoon.cartoonseason_set.all()
# object.(name of model CartoonSeason must be in lowercase )._set.all()
or set query using the CartoonSeason(recommended):
#before this you must have the id of the cartoon :
cartoon = Cartoon.objects.get(id = pk)
seasons = CartoonSeason.objects.filter(cartoon = cartoon)
I dont know about you cartoon template or urls, but I assume in you cartoon template where you show your cartoon detail you have a link to the season of the cartoon ,so there you should pass the id of the cartoon : {{cartoon.id}}
and in you urls you get this id to use in your season detail :
but note that when you are using DetailView and want to use that id passing by url you shoud define a get_queryset like this :
class CartoonSeasonView(DetailView):
model = CartoonSeason
template_name = "season.html"
def get_queryset(self, *args, **kwargs):
#before this you must have the id of the cartoon :
cartoon = Cartoon.objects.get(id = self.kwargs['pk'])
seasons = CartoonSeason.objects.filter(cartoon = cartoon)
and remember no need to user have query_set anymore.
by this you can show the name of the cartoon or the poster in the cartoonseason page.
and remember we user detail view in order to show detials of only one object not 7 ( like season of a cartoon ).You can use ListView or if you want to show different data in one template use TemplateView.

Accessing fields in a Queryset from a ManytoManyFIeld

Pretty new to Django and models and I am trying to make a wishlist where people can add to the wishlist an then view what is in their wishlist by clicking on the link to wishlist. I created a separate model for the wishlist that has a foreignfield of the user and then a many to many field for the items they want to add to the wish list. For right now i am trying to view the wishlist that i created for the user using the admin view in Django.
The problem that i am having is that when I try to print their wishlist to the template the below comes up on the page.
<QuerySet [<listings: item: Nimbus, description:this is the nimbus something at a price of 300 and url optional(https://www.google.com/ with a category of )>, <listings: item: broom, description:this is a broom stick at a price of 223 and url optional(www.youtube.com with a category of broom)>, <listings: item: wand, description:this is a wand at a price of 3020 and url optional(www.twitter.com with a category of sales)>]>
What i ideally want is the query set to be split such that the two listings and their information would be on seperate lines on the the html page when i iterate through then the items based on the user. I know it must be from the string representation that i have set up on the model itself but don't know how to manage to accomplish this. I trie .all,.values,.values_list,.prefetch_related, and i still get the same outcome when i go to page and or not iterable
if anything what would be nice is to have access to the the item,description, and price and print that onto the page for every item in the wishlist.
is this possible to do or is my approach wrong and should the wishlist be added to one of the other forms but i think this should work somehow. Don't know if i am close or there is something i am missing in one of my files or need to create a new separate view.
code below:
models.py
class User(AbstractUser):
pass
class listings(models.Model):
item = models.CharField(max_length=100)
description = models.CharField(max_length=100)
price = models.IntegerField()
url = models.CharField(max_length=100,blank=True)
category = models.CharField(max_length=100,blank=True)
def __str__(self):
return f"item: {self.item}, description:{self.description} at a price of {self.price} and url optional({self.url} with a category of {self.category})"
class bids(models.Model):
desired = models.ForeignKey(listings,on_delete=models.CASCADE,related_name="desired",null=True)
bid = models.IntegerField()
def __str__(self):
return f"{self.desired} Bid: {self.bid}"
class comments(models.Model):
information = models.ForeignKey(listings,on_delete=models.CASCADE, related_name ="Review",null=True)
title = models.CharField(max_length=100)
comment = models.CharField(max_length=100)
def __str__(self):
return f"title {self.title} Comment: {self.comment}"
class wl(models.Model):
user = models.ForeignKey(User ,on_delete=models.CASCADE, related_name="users")
product = models.ManyToManyField(listings, related_name="item_wished")
def __str__(self):
return f"{self.product.all()}"
views.py
def watch_list(request):
user = wl.objects.filter(user_id = request.user.id).prefetch_related('product')
return render(request, 'auctions/wishlist.html',{
'wishes': user
})
html template
{% extends "auctions/layout.html" %}
{% block body %}
<h2>Active Listings</h2>
{% for i in wishes.all %}
<li> {{ i }} <li>
{% endfor %}
{% endblock %}
Your code seems fine. Try tweaking your template a bit with structure, maybe an HTML table:
{% extends "auctions/layout.html" %}
{% block body %}
<h2>Active Listings</h2>
<table>
{% for w in wishes %}
<tr>
<td>{{ w.pk }}</td>
<td>{{ w.product.item }}</td>
<td>{{ w.product.description }}</td>
<td>{{ w.product.price }}</td>
</tr>
{% endfor %}
</table>
{% endblock %}
The query would return all wl objects. With:
{% for w in wishes %}
You iterate over all wl objects. Each "w" has "product" field which is a Many to many relation - it contains multiple objects and needs to be iterated again:
{% for each_wl in wishes %}
{% for each_product in each_wl %}
{{ each_product.item }}
Also, name your variables/Classes to something more verbose.

Access Many-to-Many field within Django template

I have the following blog project :
models.py:
from django.db import models
from django.utils import timezone
class Post(models.Model):
title = models.CharField(max_length=200)
body = models.TextField()
pub_date = models.DateTimeField(default=timezone.now)
categories = models.ManyToManyField('Category')
def __str__(self):
return self.title
class Category(models.Model):
title = models.CharField(max_length=200)
def __str__(self):
return self.title
# Change the name in Admin from categorys to categories
class Meta:
verbose_name_plural = "categories"
views.py:
from django.shortcuts import render
from .models import Post, Category, Comment
def getPosts(request):
posting = Post.objects.all().order_by('-pub_date')
categories = Category.objects.all()
context = {
'posting':posting,
'categories':categories,
}
return render(request, 'posts/getPosts.html', context)
getPosts.html template :
{% if posting %}
{% for article in posting %}
<h3>{{article.title}}</h3>
<ul>{{article.body}}</ul>
<ul>Posted : {{article.pub_date}}</ul>
<ul>
<em>Found in category : </em>
{{ article.categories }}
{{ article.categories.all }}
{% for category in categories %}
{{category.title}}
{% endfor %}
</ul>
{% endfor %}
{% endif %}
I have three posts, which all display properly, but
{{article.categories}} is giving me:
posts.Category.None
{{article.categories.all}} gives me
QuerySet [<Category: Diving>]
And the second loop outputs the list of all categories, which I expected as just a test run:
Kit & Packing Diving Places Tips Private
I am trying to simply pull through the category name for each post, which has been selected in the admin panel and saved through the admin panel.
I have tried what feels like a thousand different suggestions, such as changing the view to category = post.category_set.all(), and have been researching this for days now, but am getting no-where.
You already have the right answer; article.categories.all, which you should loop over.
{% for category in article.categories.all %}
{{category.title}}
{% endfor %}
You don't need the categories value in the view at all.

Django template doesn't show model items

I'm very new to Django and I'm currently trying to create a movie database for a few of my favorite directors. I've been following tutorial videos, and I'm currently trying to get my detail view to display all the added movies for each director. However when I go into the director, it does not display their films.
director/models.py
from django.db import models
class Director(models.Model):
photo = models.CharField(max_length=250, default='none')
name = models.CharField(max_length=250)
born = models.CharField(max_length=250)
birth_date = models.CharField(max_length=20)
married = models.CharField(max_length=1)
def __str__(self):
return self.name
class Films(models.Model):
director = models.ForeignKey(Director, on_delete=models.CASCADE)
title = models.CharField(max_length=50)
year = models.IntegerField(default=0)
rating = models.DecimalField(max_digits=2, decimal_places=1, default=0)
budget = models.CharField(max_length=20)
def __str__(self):
return self.title
director/urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^$', views.index, name='index'),
url(r'^(?P<name_id>[0-9]+)/$', views.detail, name='detail'),
]
director/views.py
from django.shortcuts import render
from django.http import HttpResponse
from .models import Director, Films
def index(request):
all_directors = Director.objects.all()
return render(request, 'director/index.html', {'all_directors': all_directors})
def detail(request, name_id):
try:
direct = Director.objects.get(pk=name_id)
except Director.DoesNotExist:
raise Http404("Director not found")
return render(request, 'director/detail.html', {'direct': direct})
director/detail.html
<h3 align="center"> {{ direct }} </h3><br>
<img src="{{ director.photo }}">
<h4>Film List</h4>
<ul>
{% for films in director.films_set.all %}
<li>{{ direct.title }} - {{ direct.rating }}</li>
{% endfor %}
</ul>
When I run the server and go to the page, I click on a director and all it says is the directors name, and "Film List". Please advise on how to fix this, any help is greatly appreciated!
This should solve it:
{% for film in director.films_set.all %}
<li>{{ film.title }} - {{ film.rating }}</li>
{% endfor %}
You want each movie's title and rating, so I guess using direct.title and direct.rating was the problem. Also, the variable you define in the loop is each individual film, so I replaced films with film.
In your view, you only pass one context object to the template, direct. This direct is a member of your director model: it makes sense that direct in your template displays the name of the director, since that is how you define the __str__ method for that model.
Beyond that, though, none of your other variables will display. Why?
You use director.photo instead of direct.photo. director is undefined in the template. (As a side note, director is IMO a better variable name.)
You use direct.rating and direct.title even though these are attributes of the Film model. You will need to modify as follows:
<ul>
{% for film in direct.films_set.all %}
<li>{{ film.title }} - {{ film.rating }}</li>
{% endfor %}
</ul>
(I also changed films to film since that more accurately reflects the variable's content.)

Categories

Resources