Django select_related FK model - django

I'm trying to list all the objects that are in Movie model that are Genre ForeignKey related say comedy genre list all Movie objects related to comedy
# models.py
class Genre(models.Model):
name = models.CharField(max_length=80, unique=True)
slug = models.SlugField(unique=True)
def __unicode__(self):
return self.name
def get_absolute_url(self):
return reverse("genres:list", kwargs={"slug": self.slug})
class Movie(models.Model):
title = models.CharField(max_length=80)
genre = models.ForeignKey(Genre)
# views.py
def genre_list(request, slug):
instance = get_object_or_404(Genre, slug=slug)
movies = Movie.objects.select_related('genre').all()
context = {
"objects_list": movies,
}
return render(request, 'genres/genres_list.html', context)
template view genres/genres_list.html
{% for obj in objects_list %}
<div class="box">
<b>{{ obj.title }}</b>
</div>
{% endfor %}
nothing turns up what am I doing wrong?

Your variable name in the context, object_list, doesn't match the variable name in the template, objects_list.
context = {
"object_list": shows,
}
{% for obj in objects_list %}
You need to use the same variable name in both places. I would recommend object_list because it is more common in Django, however something descriptive like movies would be even better.
Finally, if you want to select all the movies in a particular genre, then you should use filter.
instance = get_object_or_404(Genre, slug=slug)
movies = Movie.objects.filter(genre=instance)
You are currently using select_related, which does something different.

Related

Displaying get_context_data in template Django

I am trying to display the get_context_data on the template. I have a method on the model class that I need to call from ProfileView which has two different models. For the Profile View I have Profile Model and for the shippingaddress view I have ShippingAddress Model. And these models are from two different app. I tried the function below and it does not show any error, but when I tried to call it in the Template, It does not show the method.
Views.py
class ProfileView(LoginRequiredMixin, DetailView):
model = Profile
template_name = "account/profile.html"
success_url = "/"
def get_context_data(self, *args, **kwargs):
context = super(ProfileView, self).get_context_data(**kwargs)
context['shipping'] = ShippingAddress.objects.filter(user=self.request.user)
return context
Template code
{{object.get_full_address}}
Models.py
class ShippingAddress(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL,
on_delete=models.CASCADE)
phone_number = PhoneNumberField(null=True, blank=True)
street_address = models.CharField(max_length=300)
province = models.CharField(max_length=300)
city = models.CharField(max_length=50)
country = models.CharField(max_length=50)
zip_code = models.CharField(max_length=10)
def __str__(self):
return str(self.user)
def get_phone_number(self):
return self.phone_number
#property
def get_full_address(self):
return f"{self.street_address}, {self.province}, {self.city}, {self.country}, {self.zip_code}"
object is the context variable that DetailView will add to the context. For your view this would be an instance of Profile. You pass a queryset into the context with the name shipping so you can loop over that:
{% for shipping_address in shipping %}
{{ shipping_address.get_full_address }}
{% endfor %}
Note: You need to loop because one user has multiple Shipping Addresses according to your models.
Note: Also you didn't need to override get_context_data you could simply have written:
{% for shipping_address in request.user.shippingaddress_set %}
{{ shipping_address.get_full_address }}
{% endfor %}
Where shippingaddress_set is the related model name with _set
appended. You can change that by setting related_name on your
foreign key.

how to get subjects from course using foreign key in django with the help of one to many relationship

I am working on website having different courses each course have some no of subjects basically i am using one to many relationship i am having problem in getting output in desired way
(assume i have 2 subjects i.e. cse and mechanical engineering, cse have 2 subjects html and css similarly mech engineering have 2 subjects thermo and fluid mechanics) i want output like this
CSE
html
css
mechanical engineering
thermo
fluid mechanics
kindly suggest me what is wrong in my code thats why i cant get desired output`
def course(request):
courses = Course.objects.prefetch_related('subjects_set')
context = {'courses': courses}
return render(request, 'test.html', context)
def subjects(request, course_id):
subjects = Subjects.objects.filter(course_id=course_id)
return render(request, 'test.html', {'subjects': subjects})
this is my view.py
{% for course in courses %}
{{course.title}}
{% for subjects in course.subject_set.all %}
{{subject.title}}
{% endfor %}
<br/>
{% endfor %}
this my html file
class Course(models.Model):
image = models.ImageField(upload_to='course/', blank=True)
title = models.TextField(blank=True)
def __str__(self):
return self.title
class Subjects(models.Model):
course = models.ForeignKey(Course, on_delete=models.CASCADE)
image = models.ImageField(upload_to='subject/', blank=True)
title = models.CharField(max_length=255)
def __str__(self):
return self.title
this is my model
`
You can not pass the subjects to the template, sinced it iterates over the courses.
What you can do is filter the Courses in the def subjects and then render it with in the test.html as well:
def subjects(request, course_id):
courses = Course.objects.prefetch_related('subjects_set').filter(pk=course_id)
return render(request, 'test.html', {'courses': courses})

Problem in displaying related objects in template for detail view

I want to render every {{ episode.object }} in single video.html page where it works fine for {{ video.object }}. But it isn't showing anything for episode object.. The final template video.html that I want to render episode objects can be seen here https://ibb.co/K9NMXtS
I tried
{% for episode in episodes %}
{{ episode.title }}
{% endfor %}
But that didn't worked. Here is the other configurations:-
#models.py
class Video(models.Model):
title = models.CharField(max_length=100, unique=True)
slug = models.SlugField(max_length=200, unique=True)
year = models.CharField(max_length=4)
category = models.CharField(max_length=3)
trailer = models.URLField(default='')
def __str__(self):
return self.title
def get_absolute_url(self):
from django.urls import reverse
return reverse("video.html", kwargs={"slug": str(self.slug)})
class Episode(models.Model):
video = models.ForeignKey(Video, related_name='episodes', on_delete=models.CASCADE)
title = models.CharField(max_length=512)
air_date = models.DateField()
videolink = models.URLField(default='')
def __str__(self):
return self.title
# urls.py
urlpatterns = [
path('video/<slug>/', views.VideoDetail.as_view(), name='videos'),
]
# view.py
class VideoDetail(DetailView):
model = Video
template_name = 'video/video.html'
def get_context_data(self, *args, **kwargs):
context = super().get_context_data(*args,**kwargs)
context['Episodes'] = Episode.objects.all()
return context
Python and Django templates are case sensitive. You use Episodes in the view, which doesn't match episodes in the template. Change one of them so that it matches (episodes is recommended for model instances in Python/Django).
Next, you are using Episode.objects.all() at the moment, which will display all episodes. If you only want the episodes for that video, then filter the queryset:
context['episodes'] = Episode.objects.filter(video=self.object)
Or you can get the same result by following the foreign key backwards:
context['episodes'] = self.object.episodes.all()
add VideoDetail, self in super tag
and while calling in template {{ episode.video.slug }}
and slug enough in url
path('video/<slug>/', views.VideoDetail.as_view(), name='videos'),
class VideoDetail(DetailView):
model = Episode
template_name = 'video/video.html'
def get_context_data(self, *args, **kwargs):
context = super(VideoDetail, self).get_context_data(*args,**kwargs)
context['Episodes'] = Episode.objects.all()
return context

Django and aggregating grand-child records

I am new to Django but have been around RdB for a while. I am finally getting the hang of model-view-template. I am struggling a little on "aggregate" and "annotate" especially when my model has grand-child records and I want aggregate.
I use Django 3 on Python 3.
Here is my example setup, I need help straightening it out. I am all sorts of wrong.
There are stores, each that served many pizzas, each pizza has many toppings, each topping used a different qty of items. I want to know the total topping qty for each pizza made and for total topping qty for each store.
models.py
class Parlor(models.Model):
name = models.CharField(max_length=64)
class Pizza(models.Model):
name = models.CharField(max_length=64)
store = models.ForeignKey(Parlor, on_delete=models.CASCADE)
class Topping(models.Model):
name = models.CharField(max_length=64)
pizza = models.ForeignKey(Pizza, on_delete=models.CASCADE)
qty = models.IntegerField(default=0)
views.py
class ParlorDetail(generic.DetailView):
model = Parlor
template_name = 'pizza/parlor_detail.html'
context_object_name = 'parlor'
def get_context_data(self, **kwargs):
context = super(ParlorDetail, self).get_context_data(**kwargs)
id = self.kwargs['pk']
topping_qty = Pizza.objects.filter(parlor=id).annotate(sum=Sum('qty')).aggregate(sum=Sum('qty'))
return context
class PizzaDetail(generic.DetailView):
model = Pizza
template_name = 'pizza/pizza_detail.html'
context_object_name = 'pizza'
def get_context_data(self, **kwargs):
context = super(PizzaDetail, self).get_context_data(**kwargs)
id = self.kwargs['pk']
topping_qty = Topping.objects.filter(pizza=id).annotate(sum=Sum('qty'))
return context
parlor_detail.html
{% extends "pizza/my_base.html" %}
{% block content %}
<div>Parlor: {{ name }}</div>
<div>Pizzas Made at Parlor</div>
{% for pizza in pizzas.all %}
<div>Pizza: {{ pizza.name }}</div>
<div>Toppings: {{ pizza.topping_qty.sum }}</div>
{% endfor %}
<div> Total Qty of Toppings For Parlor: pizzas.topping_qty </div>
{% end block content %}

What is the best way to display data in a template in Django?

Given the below model and view, for any given club I am trying to display that club's available courts ("court") and available times ("avail_time") in the template. I am having trouble doing this.
Model:
from django.db import models
class Club(models.Model):
establishment = models.CharField(max_length=200)
address = models.CharField(max_length=200)
def __unicode__(self):
return self.establishment
class Available(models.Model):
club = models.ForeignKey(Club)
court = models.CharField(max_length=200)
avail_time = models.DateTimeField('available time')
def __unicode__(self):
return self.court
class Taken(models.Model):
club = models.ForeignKey(Club)
court = models.ForeignKey(Available)
taken_time = models.DateTimeField('taken time')
userid = models.EmailField(max_length = 75)
View:
def avail_times(request, club_id):
p = get_object_or_404(Club,pk=club_id)
return render_to_response('reserve/templates/avail_times.html', {'club':p})
Template:
{% for court in club.court_set.all %}
{{court.court }}
{% endfor %}
Well, you don't seem to have a Court model, so I'm not sure why you're trying to call court_set.all. You could use club.available_set.all to show the list of Available instances for that club, which might be what you mean.
First step would be to set up your models appropriately. Clubs have Courts and Courts have Available Times. Clubs don't have Available Times, which is how you have it set up now. Further, "taken" is a status of an available time; it shouldn't be a model itself. Try something like:
class Club(models.Model):
establishment = models.CharField(max_length=200)
address = models.CharField(max_length=200)
def __unicode__(self):
return self.establishment
class Court(models.Model):
club = models.ForeignKey(Club, related_name='courts')
name = models.CharField(max_length=200)
class CourtTime(models.Model):
AVAILABLE = 0
TAKEN = 1
STATUS_CHOICES = (
(AVAILABLE, 'Available'),
(TAKEN, 'Taken'),
)
court = models.ForeignKey(Club, related_name='times')
time = models.DateTimeField('available time')
status = models.PositiveSmallIntegerField(choices=STATUS_CHOICES, default=STATUS_CHOICES[AVAILABLE])
def __unicode__(self):
return self.court
Then, I would suggest a custom manager on CourtTime to return available/taken querysets:
class CourtTimeQuerySet(models.query.QuerySet):
def available(self):
return self.filter(status=CourtTime.STATUS_CHOICES[CourtTime.AVAILABLE])
def taken(self):
return self.filter(status=CourtTime.STATUS_CHOICES[CourtTime.TAKEN])
class CourtTimeManager(models.Manager):
use_for_related_fields = True
def get_query_set(self, *args, **kwargs):
return CourtTimeQuerySet(self.model)
def available(self, *args, **kwargs):
return self.get_query_set().available(*args, **kwargs)
def taken(self, *args, **kwargs):
return self.get_query_set().taken(*args, **kwargs)
Then, add it to your model:
class CourtTime(models.Model):
...
objects = CourtTimeManager()
With all that in place, you can just do the following in your template:
{% for court in club.courts.all %}
<h2>{{ court.name }}</h2>
<ul>
{% for time in court.times.available %}
<li>{{ time|date:"m/d/Y g:i A" }}</li>
{% endfor %}
</ul>
{% endfor %}