cssidy
cssidy

Reputation: 405

Django foreign key in template

On the home page of the site I am building I am trying to pull in data from two apps, Blog and Portfolio. Blog is working great, but Portfolio is not showing up. I assume it's because I have foreign keys in my model. I chose this project structure because the site is predominantly a blog, but I want the home page to show some recent portfolio work on the side bar. As you can see, the index.html template doesn't need all of the info from the Portfolio.portfolio model, hence I tried to import over only some of the fields. How do I include the foreign key relationship in my template so that the data can traverse the apps?

Template - index.html

{% for i in IndexPortfolio %}
    <div class="col-xs-12 col-sm-6 thumb">
        <a class="thumbnail" href="{{ IndexPortfolio.get_absolute_url }}">
            <img class="img-responsive" src="{{ IndexPortfolio.cover_image.url }}" alt="">
            <p>{{ portfolio.title }}/{{ portfolio.client_name }}</p>
        </a>
    </div>
{% endfor %}

Project structure

mysite/
blog/
   templates/
        blog/
            blog_list.html
            blog_detail.html
        index.html
        bio.html
        resume.html
   models.py
   views.py
portfolio/
    templates/
        portfolio_list.html
        portfolio_detail.html
    models.py
    views.py

blog/models.py

from django.db import models
from datetime import date
from django.urls import reverse  # Used to generate URLs by reversing the URL patterns

class IndexPortfolio(models.Model):
    title = models.ForeignKey('portfolio.Portfolio', related_name='ip_title')
    client_name = models.ForeignKey("portfolio.Portfolio", related_name='ip_client_name')
    post_date = models.ForeignKey("portfolio.Portfolio", related_name='ip_post_date')
    cover_image = models.ForeignKey("portfolio.Portfolio",  related_name='ip_cover_image')

    class Meta:
        ordering = ["post_date"]
        verbose_name_plural = "Homepage Highlights - Best Portfolio Pieces"

    def ip_get_absolute_url(self):
    """
    Returns the url to access a particular portfolio piece instance.
    """
        return reverse('portfolio-detail', args=[str(self.id)])

    def __str__(self):
    """
        String for representing the Model object.
    """
        return self.ip_title

blog/views.py

from django.shortcuts import render
from django.views import generic
from .models import Blog, IndexPortfolio


def index(request):
"""
View function for home page of site.
"""
# Generate most recent blog and portfolio post
    portfolio_list = IndexPortfolio.objects.all().order_by('-post_date')[0:6]
    blog_list = Blog.objects.all().order_by('-post_date')[0:15]
# Render the HTML template index.html with the data in the context variable.

    return render(
         request,
         'index.html',
         context={'portfolio_list': portfolio_list,
                  'blog_list': blog_list,
                  }
    )

portfolio/models.py

from django.db import models
from datetime import date
from django.urls import reverse  # Used to generate URLs by reversing the URL patterns


    class Portfolio(models.Model):
"""
Model representing a portfolio piece.
"""
    title = models.CharField(max_length=200)
    client_name = models.CharField(max_length=200, blank=True)
    content = models.TextField(max_length=4000)
    post_date = models.DateField(default=date.today)
    cover_image = models.ImageField(null=True, blank=True)
    image = models.ImageField(null=True, blank=True)

    CLIENT_TYPES = (
        ('a', 'agency'),
        ('p', 'personal project'),
        ('f', 'freelance'),
        ('n', 'nonprofit'),
   )

    client_type = models.CharField(max_length=1, choices=CLIENT_TYPES, blank=True, default='p', help_text='Client type')

    class Meta:
        ordering = ["post_date"]
        verbose_name_plural = "Portfolio Pieces"

    def get_absolute_url(self):
    """
    Returns the url to access a particular portfolio piece instance.
    """
        return reverse('portfolio-detail', args=[str(self.id)])

    def __str__(self):
    """
    String for representing the Model object.
    """
        return self.title

Upvotes: 2

Views: 2704

Answers (2)

Wilfried
Wilfried

Reputation: 1633

blog/views.py : Use Portfolio model, to init portfolio_list

from django.shortcuts import render
from django.views import generic
from .models import Blog
from portfolio.models import Portfolio


def index(request):
    """
    View function for home page of site.
    """
    # Generate most recent blog and portfolio post
    portfolio_list = Portfolio.objects.all().order_by('-post_date')[0:6]
    blog_list = Blog.objects.all().order_by('-post_date')[0:15]
    # Render the HTML template index.html with the data in the context variable.

    return render(
         request,
         'index.html',
         context={'portfolio_list': portfolio_list,
                  'blog_list': blog_list,
                  }
    )

Template - index.html : Know, use portfolio_list in your loop for

{% for p in portfolio_list %}
    <div class="col-xs-12 col-sm-6 thumb">
        <a class="thumbnail" href="{{ p.get_absolute_url }}">
            <img class="img-responsive" src="{{ p.cover_image.url }}" alt="">
            <p>{{ p.title }}/{{ p.client_name }}</p>
        </a>
    </div>
{% endfor %}

Upvotes: 1

cssidy
cssidy

Reputation: 405

Turns out, I had to add imports for 'portfolio.models', and change around some of the syntax. After that, it displayed data from cross-app models. As an effect, I was able to delete all the IndexPortfolio stuff I had going on in blog/models.py because it was unnecessary at that point after I figured out the correct way to import the other app's model.

blog/views.py

from django.shortcuts import render
from django.views import generic
from .models import Blog
from portfolio.models import Portfolio


def index(request):
    """
    View function for home page of site.
    """
    # Generate most recent blog and portfolio post
    portfolio_list = Portfolio.objects.all().order_by('-post_date')[0:6]
    blog_list = Blog.objects.all().order_by('-post_date')[0:15]
    # Render the HTML template index.html with the data in the context variable.

    return render(
         request,
        'index.html',
         context={'portfolio_list': portfolio_list,
                  'blog_list': blog_list,
                 }
    )

template - index.html

{% for portfolio in portfolio_list %}
    <div class="col-xs-12 col-sm-6 thumb">
        <a class="thumbnail" href="{{ portfolio.get_absolute_url }}">
            <img class="img-responsive" src="{{ portfolio.cover_image.url }}" alt="">
            <p>{{ portfolio.title }}/{{ portfolio.client_name }}</p>
        </a>
    </div>
{% endfor %}

Upvotes: 0

Related Questions