Django - Filter objects from child class with parent class primary key passed in URL

Viewed 247

I'm trying to pass all the Posts made for each vehicle in a vehicle detail html page.

My vehicles/models.py:

*vehicles/models.py*

class Vehicle(models.Model):

     
    TESLA = 'TESLA'
    MAZDA = 'MAZDA'
    VOLVO = 'VOLVO'
    VEHICLE_CHOICES = (
        (TESLA, "Tesla"),
        (MAZDA, "Mazda"),
        (VOLVO, "Volvo"),
        )

    owner =  models.ForeignKey(User, on_delete=models.CASCADE) 
    
    model = models.CharField(max_length=9,
       
                    choices=VEHICLE_CHOICES,
                    default=TESLA)

    def __str__(self):
            return self.model

    class Meta:
        db_table = "vehicles"

My Posts models.py:

*blog/models.py*

from django.db import models
from django.contrib.auth.models import User


     
class Post(models.Model):
    date_posted = models.DateTimeField(default=timezone.now)
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    vehicle =  models.ForeignKey(Vehicle, on_delete=models.CASCADE, default=None )
    
    def get_absolute_url(self):

        return reverse('post-detail', kwargs ={'pk': self.pk} )
  
    class Meta:
        db_table = "chargehistory"

I am already passing in a html file all the Vehicles for each User and now i would like to get all the posts made for each User's vehicle.

*vehicles/views.py*

class UserVehicleListView(ListView):
    model = Vehicle
    template_name = 'vehicles/vehicles.html'  # <app>/<model>_<viewtype>.html
    context_object_name = 'vehicles'
    
    def get_queryset(self):
        return Vehicle.objects.filter(owner_id= self.request.user.id)

class UserVehicleDetailView(DetailView):
    model = Vehicle


*vehicles/urls.py*



urlpatterns = [
    path('vehicles', UserVehicleListView.as_view(), name='vehicle-list'),
    path('vehicles/<int:pk>',  UserVehicleDetailView.as_view() , name='vehicle-detail'),

]

urlpatterns += staticfiles_urlpatterns()


Since i'm passing the vehicle primary key in the path, is there any way for me to filter the posts based on that key and pass it to vehicle_detail.html? Should i pass it as a ListView in the same path as UserVehicleDetailView?

1 Answers

You can directly use DetailView[django-doc] as used by you. Your route for DetailView in urls.py is correct. You must have to pass its pk from from html part.

views.py

class UserVehicleDetailView(DetailView):
    model=Vehicle
    template_name="any_folder_name/any_file.html"
    context_object_name="single_vehicle"

Note: While using DetailView you should not run loop, as it is a single object.

anyfile.html


{% if "single_vehicle" %}
    <p>{{single_vehicle.owner.username}}</p>
{% endif %}

Here, you can access all his properties by chaining, and you can also change pk to another name say, id and then mentioned it in your UserVehicleDetailView as pk_url_kwarg="id", then also it will work.

But at first, you need to pass pk through ListView through loop and then access it as a single object through DetailView.

Note: Always give / at the end of every route in path function.




Here is minimal reproducible example:

Create, a simple project in which make an app called home, register it in INSTALLED_APPS in settings.py. After that see below example:

models.py

from django.db import models

class Subject(models.Model):
    name = models.CharField(max_length=200)

    def __str__(self):
        return f"{self.name}"

    class Meta:
        ordering = ['name']

class Student(models.Model):
    name = models.CharField(max_length=100)
    email = models.CharField(max_length=200)
    father_name = models.CharField(max_length=200)
    subject = models.ForeignKey(Subject, on_delete=models.CASCADE)

    def __str__(self):
        return f"{self.name}"

urls.py

from django.urls import path
from . import views
urlpatterns = [
    path('', views.AllStudentDetailView.as_view(), name='all_student_detail'),
    path('single_student/<int:id>/',
         views.SingleStudentView.as_view(), name='student_detail')
]

views.py

from msilib.schema import ListView
from django.shortcuts import render
from django.views.generic import DetailView, ListView
from .models import Student


class AllStudentDetailView(ListView):
    model = Student
    template_name = 'home/list_of_students.html'
    context_object_name = 'all_students'


class SingleStudentView(DetailView):
    model = Student
    template_name = 'home/single_student.html'
    context_object_name = 'student'
    pk_url_kwarg = 'id'

Note: In DetailView there is also use of pk_url_kwarg, this is used when we give something else than pk.

admin.py

from django.contrib import admin
from .models import Student, Subject


@admin.register(Subject)
class SubjectAdmin(admin.ModelAdmin):
    list_display = ['id', 'name']


@admin.register(Student)
class StudentAdmin(admin.ModelAdmin):
    list_display = ['id', 'name', 'email', 'father_name', 'subject']

list_of_students.html

<body>
    <h2>All Student Details</h2>
    <table border='1' style='text-align:center;' cellpadding='3px' cellspacing='3px'>
        <thead>
            <tr>
                <th>Name</th>
                <th>Email</th>
                <th>Father Name</th>
                
            </tr>
        </thead>
        <tbody>
            {% for student in all_students  %}
            <tr>
                <td><a href="{% url 'student_detail' student.id %}">{{student.name}}</a></td>
                <td>{{student.email}}</td>
                <td>{{student.father_name}}</td>

            </tr>
            {% endfor %}
        </tbody>

    </table>
</body>

single_student.html

<body>
    {% if student %}
    <h2>Detail of {{student.name}}</h2>
    <h3>All subject he/she had taken are:</h3>

    <p>Subject is -- {{student.subject}}</p>

    {% else %}
    <p>Student object does not come.</p>
    {% endif %}
</body>

When you click on single student's name, you are redirected to see its detail on detail page.

Related