Andrej Vilenskij
Andrej Vilenskij

Reputation: 517

django, does not display the avatar in the comments

I extended standart django user model by one-to-one field. Made news block, and added comments there. In comments i cant display user avatar from UserProfile model, cause dont understand how correctly ask database for it D;. Here my code:

main/models.py

from django.db import models
from django.utils import timezone
from django.contrib import auth
from django.contrib.auth.forms import User
from django.shortcuts import render, redirect
from profiles.models import UserProfile

# Create your models here.
class News(models.Model):
news_title = models.CharField(max_length=250)
news_body =  models.TextField(max_length=2000, blank=True)
author = models.ForeignKey('auth.User', on_delete=models.CASCADE)
image = models.FileField()
published_date = models.DateTimeField(blank=True, null=True)

def publish(self, request):
    self.published_date = timezone.now()
    self.save()
    return redirect('index')

def __str__(self):
    return self.news_title

class Comment(models.Model):
    news = models.ForeignKey('main.News', related_name='comments', 
on_delete=models.CASCADE)
author = models.CharField(max_length=200)
text = models.TextField()
created_date = models.DateTimeField(default=timezone.now)
approved_comment = models.BooleanField(default=False)

def approve(self):
    self.approved_comment = True
    self.save()

def __str__(self):
    return self.text

profiles/models.py

class UserProfile(models.Model):
    JEW_CHOICE = (
        ('Да', 'Да'),
        ('Нет', 'Нет'),
    )
    MF_CHOICE = (
        ('М', 'М'),
        ('Ж', 'Ж')
    )

    user = models.OneToOneField(User, on_delete=models.CASCADE)
    country = models.CharField(max_length=100, default='', blank=True)
    city = models.CharField(max_length=100, default='', blank=True)
    description = models.CharField(max_length=500, default='', blank=True)
    website = models.URLField(default='', blank=True)
    avatar = models.ImageField(default='', blank=True)
    gender = models.CharField(max_length=100, choices = MF_CHOICE, default = 'М', blank=True)
    jew = models.CharField(max_length=100, choices = JEW_CHOICE, default = 'Да', blank=True)

    def __str__(self):
        return self.user.username

@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
    if created:
        UserProfile.objects.get_or_create(user=instance)

@receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
    instance.userprofile.save()

@property
def avatar_url(self):
    if self.avatar and hasattr(self.avatar, 'url'):
        return self.avatar.url

main/views.py (meme_detail is the view, where should be comments with user info)

def meme_detail(request, pk):
    news = get_object_or_404(News, pk=pk)
    if request.method == "POST":
        form = CommentForm(request.POST)
        if form.is_valid():
            comment = form.save(commit=False)
            comment.author = request.user
            comment.news = news
            comment.save()
            return redirect('main:meme_detail', pk=news.pk)
    else:
        form = CommentForm()
    return render(request, 'main/meme_detail.html', {'news': news, 'form': form,})

meme_detail.html (news template with comments)

{% extends 'main/base.html' %}

{% block body %}


    <h2>{{news.news_title}}</h2>
    <img src='{{news.image.url}}' name='image' width='500px;'><br>
    {{news.news_body}} <br><br>
    <div class="row">
    <div class="col">
        <b>{{news.author}}</b>
    </div>
    <div class="col">
        <i>{{news.published_date}}</i> 
    </div>
    </div>
    <div class="underline"></div>
<h3>Комментарии:</h3><br>
{% for comment in news.comments.all %}

    <div class="row">
        <div class="col-"><img src="{{ userprofile.avatar.url }}" alt="user-avatar" width="100px" height="100px"></div>
        <div class="col">{{ comment.text }}</div>
    </div>
    <div class="row">
        <div class="col"><strong>{{ comment.author }}</strong></div>
        <div class="col">{{ comment.created_date}}</div>
    </div>
    <div class="underline"></div>
    <br>

{% empty %}
    <p>Пока ещё нет комментариев :(</p>
{% endfor %}

{% if request.user.is_authenticated %}
<div class="row">
    <form method="POST">
        {% csrf_token %}
        {{form.text}}<br><br>
        <a class="btn btn-success" href="{% url 'main:meme_detail' pk=news.pk %}"><button class='btn btn-success'>Добавить коммент! </button></a>
    </form>
</div>
{% else %}

<i>Вы не можете писать комментарии, необходимо зарегистрироваться!</i>
{% endif %}


{% endblock %}

So, in this template, where "userprofile.avatar.url" should be object reference on User avatar. I tryed a lot of things, but it always the same:not displaying

Upvotes: 1

Views: 528

Answers (2)

Dalvtor
Dalvtor

Reputation: 3286

You should do:

<img src="{{ comment.author.userprofile.avatar.url }}" alt="user-avatar" width="100px" height="100px">

Your comment has a foreign key to User (author), and User has a one to one field to UserProfile, which is the one that has the avatar attribute.

Also another tip:

You shouldn't really reduce the image in CSS (width: 100px; height: 100px;), but instead use a tool that allows you to create thumbnails of images. I use sorl-thumbnail and can't recommend it enough.

The reason is that if every user uploads a 1000x1000 image, you are downloading those big images that you don't really need, hence your site will be slower.

Upvotes: 1

Ralf
Ralf

Reputation: 16515

Maybe you should try accesing the User object in the template, not the Userprofile.

<img src="{{ user.userprofile.avatar.url }}" ...

Upvotes: 0

Related Questions