Django template doesn't show model items - python

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.)

Related

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.

Django: Cannot Add Clickable Link in the Template

I am a beginner in Django. I am building a Django app, named PhoneReview. It will store reviews related to the latest mobile phone. It will also display phone brands, along with the associated phone models. I have already created models for:
Brand – details on brand, such as, name, origin, manufacturing since, etc
Model – details on model, such as, model name, launch date, platform, etc
Review – review article on the mobile phone and date published, etc
Many-to-many relationship between Review and Model.
I also have created views for the following:
a. An index page that display all Brands available for mobile phone in the database
b. A phone model page that display model when a brand is selected.
c. A detail page when a model is selected that contain reviews and newslink
Now, I am facing a problem. I cannot put any clickable link that will redirect the phone brands, like Apple and Samsung, of brandlist.html web page, to their respective phone model page (phonemodel.html). Here is the screenshot:
Here are the codes of models.py inside "PhoneReview" folder.
from django.db import models
from django.template.defaultfilters import slugify
# Create your models here.
class Brand(models.Model):
brand_name = models.CharField(max_length=100)
origin = models.CharField(max_length=100)
manufacturing_since = models.CharField(max_length=100, null=True, blank=True)
def __str__(self):
return self.brand_name
def save(self, *args, **kwargs):
self.slug = slugify(self.title)
super().save(*args, **kwargs)
class PhoneModel(models.Model):
brand = models.ForeignKey(Brand, on_delete=models.CASCADE)
model_name = models.CharField(max_length=100)
launch_date = models.CharField(max_length=100)
platform = models.CharField(max_length=100)
def __str__(self):
return self.model_name
class Review(models.Model):
phone_model = models.ManyToManyField(PhoneModel, related_name='reviews')
review_article = models.TextField()
date_published = models.DateField(auto_now=True)
slug = models.SlugField(max_length=150, null=True, blank=True)
def __str__(self):
return self.review_article
Here are the codes of urls.py inside "PhoneReview" folder.
from . import views
from django.urls import path
urlpatterns = [
path('index', views.BrandListView.as_view(), name='brandlist'),
path('phonemodel/<int:pk>/', views.ModelView.as_view(), name='modellist'),
path('details/<int:pk>/', views.ReviewView.as_view(), name='details'),
]
Here are the codes of views.py inside "PhoneReview" folder:
from django.views import generic
from .models import Brand, PhoneModel, Review
class BrandListView(generic.ListView):
template_name = 'PhoneReview/brandlist.html'
context_object_name = 'all_brands'
def get_queryset(self):
return Brand.objects.all()
class ModelView(generic.DetailView):
model = PhoneModel
template_name = 'PhoneReview/phonemodel.html'
class ReviewView(generic.DetailView):
model = Review
template_name = 'PhoneReview/details.html'
Here are the codes of apps.py inside "PhoneReview" folder:
from django.apps import AppConfig
class PhonereviewConfig(AppConfig):
name = 'PhoneReview'
Here are the codes of phonemodel.html. The page can be accessed by going through http://127.0.0.1:8000/phonemodel/1/ in the browser.
{% extends 'PhoneReview/base.html' %}
{% load static %}
{% block title%}
Phone Model Page
{% endblock %}
{% block content %}
<!--Page content-->
<h1>This is Phone Model Page</h1>
<h2>Here is the phone model</h2>
<ul>
<li>{{ phonemodel.model_name }}</li>
</ul>
<img src="{% static "images/brandlist.jpg" %}" alt="Super Mario Odyssey" /> <!-- New line -->
{% endblock %}
Here are the codes of brandlist.html. The web page can be accessed by going to http://127.0.0.1:8000/index in the browser.
{% extends 'PhoneReview/base.html' %}
{% load static %}
{% block title%}
Brand List
{% endblock %}
{% block content %}
<!--Page content-->
<h1>This is Brand List Page</h1>
<h2>Here is the list of the brands</h2>
<ul>
{% for brand in all_brands %}
<li>{{ brand.brand_name }}</li>
{% endfor %}
</ul>
<img src="{% static "images/brandlist.jpg" %}" alt="Super Mario Odyssey" /> <!-- New line -->
{% endblock %}
I tried modifying <li>{{ brand.brand_name }}</li>to <li>{{ phonemodel.model_name }}</li> . But the code doesn't work.
What should I do?
Update 1: I can't view the brandlist.html page when I add <li>{{ phonemodel.model_name }}</li>. I get an error on http://127.0.0.1:8000/index. It says 'phonemodel' is not a registered namespace
Update 2: I have managed to fix the issue. I changed the code to <li>{{ brand.brand_name }}</li>. Thanks to #LinhNguyen for giving me the idea.
You forgot to close your a tag and since you already declared your url name in urls.py so no need to add the app name before the url
{{ brand.brand_name }}

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 queryset for list item

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>

To determine the user's role in the project

In my django website I have pages like 'project_list' and 'project_detail'. Every project has members with different roles (developer, manager, e.t.c.). I want to show different buttons depending on the current user's role in the project in template. I need ideas how to realise it. Lets say something like that in template:
{% if request.user.role_in_the_current_project = 'manager' %}
SOW SOMETHING
{% endif %}
models.py
class Project(models.Model):
name = models.CharField(max_length=250,)
slug = models.SlugField(max_length=250, unique_for_date='publication_date',)
*Other fields*
def get_absolute_url(self):
return reverse('project:project_detail', args=[self.slug])
class Membership (models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
project = models.ForeignKey(Project, on_delete=models.CASCADE)
ROLE_CHOICES = (
('manager', 'Manager'),
('developer', 'Developer'),
('business_analyst', 'Business analyst'),
('system_analysts', 'System analysts'),
)
role = models.CharField(max_length=20, choices=ROLE_CHOICES,)
view.py
def project_detail(request, slug):
project = get_object_or_404(Project, slug=slug, status='public')
return render(request, 'project/project_detail.html', {'project': project,})
project_detail.html
{% block content %}
<h1>{{ project.name }}</h1>
<p>{{ project.description|linebreaks }}</p>
{%endblock %}
urls.py
urlpatterns = [
url(r'^project/(?P<slug>[-\w]+)/$', project_detail, name='project_detail'),
]
You can use the concept of choices inside a model field and then by using these you can make decisions inside your templates (or to your views) to show appropriate content.
Let me know if you need more info on this.
[EDIT]: So, what you want is to check each time the value of role. Right?
In your views.py write:
project = get_object_or_404(Project, slug=slug, status='public')
memberships = project.membership_set.all()
Then because one project can have many Membership records you should iterate over the memberships to get each time the role.
So, in your template:
{% for membership in memberships %}
{% if membership.role == 'Manager' %} Do stuff here {% endif %}
{% endfor %}
Note that .role will give you back the second value of the ROLE_CHOICES sub-tuple which is capitalized, while the first one is that will be shown in the user if you use the function get_role_display()
Well, after all I found solusion. In view I add:
is_manager = project.membership_set.filter(user=request.user, role='Manager').exists()
Then in template I add:
{% if is_manager %}
<button>Create</button>
{% endif %}

Categories

Resources