alzea arafat
alzea arafat

Reputation: 37

How to pass multiple app's models in one views? [django]

Hei there,

I'm having difficulties passing two app models in one views. I have 2 apps :

What I expect is, I want to display Author's avatar in the Post views, so I can include it in posts loop.

Author models.py :

class Author(models.Model):
avatar      = models.ImageField(upload_to='images/%Y/%m/%d', verbose_name=u'Author Avatar', validators=[validate_image], blank=True, null=True)
user        = models.OneToOneField(User, on_delete=models.CASCADE)
location    = models.CharField(max_length=30, blank=True)

...

Post views.py :

from app_author.models import Author

class PostList(ListView):
    model = Post
    template_name = 'app_blog/blog_homepage.html'
    context_object_name = 'post_list'
    paginate_by = 9

    def get_context_data(self, **kwargs):
        context = super(PostList, self).get_context_data(**kwargs)
        context['post_hot'] = Post.objects.filter(misc_hot_post = True).order_by('-misc_created')[:1]
        context['post_list'] = Post.objects.filter(misc_published = True).order_by('-misc_created')
        context['author'] = Author.objects.all() # No need this line
        return context

When I called something like this in templates, it doesn't work. The {{ author.avatar }} not showing :

{% for post in post_list %}
 <ul>
    <li>{{ post.title }}</li> # This is works just fine
    <li>{{ author.avatar }}</li> # This does not work at all
 <ul>
{% endfor %}

My Posts app urls.py :

from . import views
from django.conf import settings
from app_blog.views import PostList, PostDetailView
from django.conf.urls import include, url
from django.conf.urls.static import static

urlpatterns = [
    url(r'^$', views.PostList.as_view(), name='post-list'),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

Any help would be greatly appreciated! Thank you in advance!

Regards

--- UPDATE ---

Here is my Post models.py

import datetime
from django import forms
from django.db import models
from django.conf import settings
from autoslug import AutoSlugField
from django.forms import ModelForm
from app_author.models import Author
from taggit.managers import TaggableManager
from django.contrib.auth.models import User
from django.core.exceptions import ValidationError
from django.template.defaultfilters import slugify

# CUSTOM FILE SIZE VALIDATOR
def validate_image(fieldfile_obj):
    filesize = fieldfile_obj.file.size
    megabyte_limit = 5
    if filesize > megabyte_limit*1024*1024:
        raise ValidationError("Max file size is %sMB" % str(megabyte_limit))

class Category(models.Model):
    # PRIMARY DATA
    id                      = models.AutoField(primary_key=True)
    category_name           = models.CharField(max_length=200, verbose_name=u'Category Name', blank=False, null=False)

    def __str__(self):
        return str(self.category_name)

class Post(models.Model):
    # PRIMARY DATA
    post_image              = models.ImageField(upload_to='images/%Y/%m/%d', verbose_name=u'Post Featured Image', validators=[validate_image], blank=True, null=True)
    post_author             = models.ForeignKey(Author, related_name="user_posts", null=True, blank=True)
    post_title              = models.CharField(max_length=200, verbose_name=u'Post Title', blank=False, null=False)
    post_sub_title          = models.CharField(max_length=200, verbose_name=u'Post Sub-Title', blank=False, null=False)
    post_category           = models.ForeignKey('Category', verbose_name=u'Post Category', on_delete=models.CASCADE)
    post_content            = models.TextField()
    post_tags               = TaggableManager()
    slug                    = AutoSlugField(populate_from='post_title')

    # MISC
    misc_created            = models.DateTimeField(default=datetime.datetime.now, null=True, blank=True)
    misc_modified           = models.DateTimeField(default=datetime.datetime.now, null=True, blank=True)
    misc_hot_post           = models.BooleanField(default=False)
    misc_published          = models.BooleanField(default=False)

    def __str__(self):
        return str(self.post_title)

    @models.permalink
    def get_absolute_url(self):
        return 'app_blog:post', (self.slug,)

Thank you

--- UPDATE 2 ---

SOLVED

@Gagik & @Daniel answer sloved my problem. I just have to use this tag instead :

{{ post.post_author.avatar }}

I did not change any code above. Except I dont need this line :

context['author'] = Author.objects.all()

Thank you

Upvotes: 1

Views: 149

Answers (2)

Gagik Sukiasyan
Gagik Sukiasyan

Reputation: 856

You need to related Author and Post models to each other by ForeignKey file, like:

class Post (models.Model):
    author = models.ForeignKey(Author)

Then when you can access to your avatar through post.author.

Updated:

Updating answer after question updated. I think you need to update your template as follows. use post.post_author.avatar to access the avatar you need:

{% for post in post_list %}
<ul>
   <li>{{ post.title }}</li> # This is works just fine
   <li>{{ post.post_author.avatar }}</li> # This does not work at all
<ul>

{% endfor %}

Considering this please note that you don't need to search Author's desperately in your view. So you don't need to have following line:

context['author'] = Author.objects.all() # This is where I expect the magic is

Because when you have ForeignKey then you already have access to Author through post object.

Upvotes: 1

Daniel Roseman
Daniel Roseman

Reputation: 599788

Gagik and JF's answers should have been enough for you to work out what to do. Your foreign key is called "post_author", so that's what you should use in the template:

{{ post.post_author.avatar }}

There's no need for you get all the authors and pass them to the template in your view as you are doing.

Upvotes: 1

Related Questions