Home > database >  Extending class-based generic views two have 2 models (SIMPLEST WAY) template
Extending class-based generic views two have 2 models (SIMPLEST WAY) template

Time:07-21

I need to extend the (generic.DetailView): to include my second class, PostImage. According to the documentation (https://docs.djangoproject.com/en/4.0/topics/class-based-views/generic-display/),

class PostDetail(generic.DetailView):
    model = Post
    template_name = 'post_detail.html'

should include something like this:

 def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['image_list'] = PostImage.objects.all()
        return context

models.py

from django.db import models
from django.contrib.auth.models import User
from django.forms import ImageField
from django.utils.safestring import mark_safe

STATUS = (          #tuple
    (0,"Draft"),
    (1,"Publish")
)

# Create your models here.

class Post(models.Model):
    title = models.CharField(max_length=200, unique=True)
    slug = models.SlugField(max_length=200, unique=True)
    author = models.ForeignKey(User, on_delete= models.CASCADE,related_name='blog_posts')
    updated_on = models.DateTimeField(auto_now= True)
    content = models.TextField()
    created_on = models.DateTimeField(auto_now_add=True)
    status = models.IntegerField(choices=STATUS, default=0)
    image = models.ImageField(upload_to='images', null=True, blank=True)   

    class Meta:
        ordering = ['-created_on']

    def __str__(self):
        return self.title

class PostImage(models.Model):
    post = models.ForeignKey(Post, default=None, on_delete=models.CASCADE)
    image = models.ImageField(upload_to='images', null=True, blank=True)
    
    def __str__(self):
        return self.post.title

views.py

from django.views import generic
from .models import Post, PostImage


# Create your views here.

class PostList(generic.ListView):
    queryset = Post.objects.filter(status=1).order_by('-created_on')
    template_name = 'index.html'

class PostDetail(generic.DetailView):
    model = Post
    template_name = 'post_detail.html'

urls.py

from . import views
from django.urls import path

urlpatterns = [
    path('', views.PostList.as_view(), name='home'),
    path('<slug:slug>/', views.PostDetail.as_view(), name='post_detail'),
]

Can I leave the urls unchanged?

post_detail.html

{% extends 'base.html' %} {% block content %}
{% load static %}

<div >
  <div >
    <div >
      <div >
        <h1>{% block title %} {{ object.title }} {% endblock title %}</h1>
        <p >{{ post.author }} | {{ post.created_on }}</p>
        <!-- <img  src= "{% url 'home' %}{{ post.image }}" alt="Card image cap"> -->
      
        <img src="{% get_media_prefix %}{{ post.image }}"  alt="Recipe Image Main">


        <p ><pre >{{ object.content }}</pre></p>
        {#  {% lorem 3 p %} #}
      </div>
    </div>

  {% block sidebar %} {% include 'sidebar.html' %} {% endblock sidebar %}
  </div>
</div>

{% endblock content %}

Right now post.image returns the image in the template, however, I need postimage.image (basically my second class in the models) to return as well.. (doesn't work). What am I missing?.. Reading a buncha docs.

CodePudding user response:

You pass image_list but don't call it. You should use a for loop in your template.

{% for img in image_list %}
    {{ img.post }}
    {{ img.image }}
{% endfor %}

CodePudding user response:

Accessing method calls¶

Most method calls attached to objects are also available from within templates. This means that templates have access to much more than just class attributes (like field names) and variables passed in from views. For example, the Django ORM provides the “entry_set” syntax for finding a collection of objects related on a foreign key.

Since your two models have a ForeignKey used to relate to each other. I think you can just utilize reverse lookup _set without adding the child model in the context. You can just call it in your templates something like this:

{% for post_image in post.postimage_set.all %}
    {{ post_image.image }}
{% endfor %}

Reference: Django Template: Accessing Method calls

  • Related