I'm new to Django, I repeat after the tutorial, but I just can not display comments even from the database in html.
urls.py
static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
settings
MEDIA_ROOT = os.path.join(BASE_DIR, 'media/')
models.py
from django.db import models
class Post(models.Model):
photo = models.ImageField(upload_to='media/photos/',null=True, blank=True)
name_barber = models.CharField(max_length=30)
description = models.TextField(blank=True, null=True)
def __str__(self):
return self.description[:10]
class Comment(models.Model):
post = models.ForeignKey(Post, related_name='comments', on_delete=models.CASCADE)
name = models.CharField(max_length=255)
body = models.TextField()
date_add = models.DateTimeField(auto_now_add=True)
def __str__(self):
return '%s - %s' % (self.post, self.name)
html file
} </style>
{% for post in posts %}
<img src="{{MEDIA_URL}}{{post.photo.url}}" width="800" />
<h3>{{ post.name_barber}}</h3>
<p>{{ post.description}}</p>
{% endfor %}
<h3> Comments.. </h3>
{% if not post.comments.all %}
no comments yet...Add one
{% else %}
{% for comment in post.comments.all %}
<strong>
{{ comment.name }}
{{ comment.date_add }}
</strong>
{{comment.body }}
{% endfor %}
{% endif %}
after adding a comment through the admin panel, the page displays: no comments yet..
What is the problem please tell me??
Remove the if/else condition and use the {% empty %} tag with your forloop.
{% for comment in post.comments.all %}
<strong>
{{ comment.name }}
{{ comment.date_add }}
</strong>
{{comment.body }}
{% empty %}
no comments yet...Add one
{% endfor %}
Related
I have Model Question and Answer.
What I want to accomplish is to be able to display it in the template in a way that shows like this. I would like to know a way to accomplish this. I'm trying my best to not let it loop the whole data in a model but rather one data at a time. I'm trying to make a qna data and make it display on a template. so having all the Questio data displayed before Answer data is not what I want. It has to be one by one for these two models. I'm getting kinda close...but I stil can't figure out how to accomplish this. Any help or advice would be greatly appreciated. Thank you in advance.
Q.title
Q.body
A.body
Q.title
Q.body
A.body
Q.title
Q.body
A.body
modesl.py
from django.db import models
from django.contrib.auth.models import User
from django.utils import timezone
class Question(models.Model):
title= models.CharField(max_length= 100)
body= models.TextField()
date_posted= models.DateTimeField(default=timezone.now)
author= models.ForeignKey(User, on_delete= models.CASCADE)
def __str__(self):
return self.title
class Answer(models.Model):
body= models.TextField()
question= models.ForeignKey(Question, on_delete= models.CASCADE)
date_posted= models.DateTimeField(default=timezone.now)
author= models.ForeignKey(User, on_delete= models.CASCADE)
def __str__(self):
return self.body
qna.html template
{% extends "info/base.html" %}
{% block content %}
{% for question in questions %}
<h1> Q</h1>
<h3> {{ question.title }} </h3>
{% for answer in answers %}
<h1> A </h1>
<h3> {{ answer.body }}</h3>
{% endfor %}
{% endfor %}
{% endblock content %}
views.py
from django.shortcuts import render
from .models import Question, Answer
def qna(request):
context= {
'questions': Question.objects.all(),
'answers': Answer.objects.all(),
}
return render(request, 'qna/qna.html', context)
As Answer model has relation of ForeignKey with question you can directly access question model fields in reverse.Replace your code in html like below and check if same works for you.
{% extends "info/base.html" %}
{% block content %}
{% for answer in answers %}
<h1> Question:</h1>
<h3> title: {{ answer.question.title }} </h3>
<h3> body: {{ answer.question.body }} </h3>
<h1> Answer: </h1><h3> {{ answer.body }} </h3>
{% endfor %}
{% endblock content %}
Add related_name to model Answer that has ForeignKey with Question:
question= models.ForeignKey(Question, on_delete= models.CASCADE, related_name='my_answes')
in HTML file replace the second loop with :
{% for answer in question.my_answes.all %}
<h1> A </h1>
<h3> {{ answer.body }}</h3>
<hr>
{% endfor %}
The 'Thumbnail' attribute has no file associated with it.
I have tried Django {% if %} {% else %} {% endif %} in my HTML list and it works on the page, but when I do the same for a detailview HTML it doesn't work and returns "The 'Thumbnail' attribute has no file associated with it."
** Models.py **
class Article(models.Model):
Title = models.CharField(max_length=150)
Thumbnail = models.ImageField(blank=True, null=True)
Author = models.ForeignKey(Author, on_delete=models.CASCADE)
Content = QuillField()
Date = models.DateField(auto_now_add=True)
slug = AutoSlugField(populate_from='Title')
** Views.py**
class ArticlesDetailView(DetailView):
model = Article
template_name = 'articles_app/articles_detail.html'
def get_context_data(self, **kwargs):
latest = Article.objects.order_by('-id')[0:3]
context = super().get_context_data(**kwargs)
context['latest'] = latest
return context
** HTML - List (articles_list.html) ** It works perfectly fine here!!!
<img src=" {% if articles.Thumbnail %}
{{ articles.Thumbnail.url }}
{% else %}
{% static 'img/add-ons/article_thumbnail_default.jpg' %}
{% endif %} " alt="..." class="card-img-top">
** HTML - Detail (articles_detail.html) ** It doesn't work here.
{% for obj in latest %}
<img src="{% if obj.Thumbnail %}
{{ obj.Thumbnail.url }}
{% else %}
{% static 'img/add-ons/article_thumbnail_default.jpg' %}
{% endif %} " alt="..." class="card-img-top">
{% endfor %}
What am I doing wrong? Please help!
try object.Thumbnail instead of obj.Thumbnail, I think that will solve your problem.
I am learning Django by building an application, called TravelBuddies. It will allow travelers to plan their trip and keep associated travel items (such as bookings, tickets, copy of passport, insurance information, etc), as well as create alerts for daily activities. The application will also able to update local information such as weather or daily news to the traveler. Travelers can also share the travel information with someone or have someone to collaborate with them to plan for the trip.
I am facing a problem. When I go to http://127.0.0.1:8000/triplist/, I see this page:
When I click on Trip Name: Kuala Lumpur and taken to activity.html through this link: http://127.0.0.1:8000/triplist/kuala-lumpur/:
"john" and "williams" are two separate user names. They need to be separated by a comma (,). So it will look like this: Co-traveller: john, williams. How can I do it?
Here are my codes in models.py:
from django.contrib.auth.models import User
from django.db import models
from django.template.defaultfilters import slugify
# Create your models here.
class Trip(models.Model):
trip_name = models.CharField(max_length=100)
date = models.DateField()
planner_name = models.CharField(max_length=100)
add_coplanner = models.ManyToManyField(User)
slug = models.SlugField(max_length=150, default='null')
def __str__(self):
return self.trip_name
def save(self, *args, **kwargs):
self.slug = slugify(self.trip_name)
super().save(*args, **kwargs)
class Activity(models.Model):
trip = models.ForeignKey(Trip, on_delete=models.CASCADE)
activity_name = models.CharField(max_length=100)
date = models.DateField(auto_now=True)
time = models.TimeField(auto_now= True)
location = models.CharField(max_length=100)
item_type = models.CharField(max_length=100)
item_number = models.CharField(max_length=100)
add_cotraveller = models.ManyToManyField(User)
slug = models.SlugField(max_length=150, default='null')
def __str__(self):
return self.activity_name
def save(self):
super(Activity, self).save()
self.slug = '%i-%s' % (
self.id, slugify(self.trip.trip_name)
)
super(Activity, self).save()
Here are my codes in views.py:
from django.views import generic
from .models import Trip, Activity
class TripListView(generic.ListView):
template_name = 'trips/triplist.html'
context_object_name = 'all_trips'
def get_queryset(self):
return Trip.objects.all()
class ActivityView(generic.DetailView):
model = Trip
template_name = 'trips/activity.html'
Here are my codes in urls.py:
from . import views
from django.urls import path
app_name = 'trips'
urlpatterns = [
path('triplist/', views.TripListView.as_view(), name='triplist'),
path('triplist/<slug:slug>/', views.ActivityView.as_view(), name='activity'),
]
Here are my codes in apps.py:
from django.apps import AppConfig
class TripsConfig(AppConfig):
name = 'trips'
Here are my codes in triplist.html:
<!DOCTYPE html>
{% extends 'trips/base.html' %}
{% load static %}
<html lang="en">
<link rel="stylesheet" type="text/css" href="{% static "css/style.css" %}">
<head>
<meta charset="UTF-8">
{% block title%}Trip list{% endblock %}
<title>Trip list</title>
</head>
<body>
{% block content %}
<!--Page content-->
<h1>This is Trip List Page</h1>
<ol>
{% for trip in all_trips %}
<ol>
<li>Trip name: {{ trip.trip_name }}</li>
Date: {{ trip.date }}<br>
Planner: {{ trip.planner_name }}<br>
Coplanners:
{% for user in trip.add_coplanner.all %}
{{user.username}}
{% endfor %}<br>
<!-- Co-planner: {{ trip.add_coplanner.all }}<br>-->
</ol>
{% endfor %}
</ol>
<img src="{% static "images/botanical-garden.jpg" %}" alt="Botanical Garden" />
<!-- New line -->
{% endblock %}
</body>
</html>
Here are my codes in activity.html:
{% extends 'trips/base.html' %}
{% block title%}
Detail
{% endblock %}
{% block content %}
<h3>Activities for {{trip.trip_name}} </h3>
{% for trip_item in trip.activity_set.all %}
<!--<p>Activity name: {{ trip_item.activity_name }}</p>-->
<ol>
<li>Activity name: {{ trip_item.activity_name }}</li>
Date: {{ trip_item.date }}<br>
Time: {{ trip_item.time }}<br>
Location: {{ trip_item.location }}<br>
Item Type: {{ trip_item.item_type }}<br>
Item No: {{ trip_item.item_number }}<br>
Co-traveller:
{% for user in trip_item.add_cotraveller.all %}
{{user.username}}
{% endfor %}<br>
<!-- Co-traveller: {{ trip_item.add_cotraveller.all }}-->
</ol>
{% endfor %}
{% endblock %}
Do I have to make any change in models.py?
Co-traveller:
{% for user in trip_item.add_cotraveller.all %}
{% if forloop.last %}
{{user.username}}
{% else %}
{{user.username}} ,
{% endif %}
{% endfor %}<br>
you can use this. do give a space after ,
You can separate user with comma like this:
Co-traveller:
{% for user in trip_item.add_cotraveller.all %}
{{user.username}}{% if not forloop.last %}, {% endif %}
{% endfor %}<br>
One more way is to create a instance method and return a string from your model.
For eg.
class Activity(models.Model):
#fields
add_cotraveller = models.ManyToManyField(User)
def __str__(self):
return self.activity_name
def get_cotravellers(self):
return ", ".join(u.username for u in self.add_coplanner.all())
and in template you can access it like:
Coplanners: {{ trip_item.get_cotravellers }}
this is models.py
class Post(models.Model):
author = models.ForeignKey('auth.User', on_delete=models.CASCADE)
title = models.CharField(max_length=100)
content = models.TextField()
date = models.DateTimeField(default=timezone.now)
def write(self):
self.date = timezone.now()
self.save()
def __str__(self):
return self.title
class Comment(models.Model):
post = models.ForeignKey('humorge.post', on_delete=models.CASCADE, related_name='comments')
author = models.CharField(max_length=100)
content = models.TextField()
date = models.DateTimeField(default=timezone.now)
def add_coment(self):
self.date = timezone.now()
self.save()
def __str__(self):
return self.content
and this is views.py
def mainpage(request):
return render(request, 'index.html')
def post(request):
datas = Post.objects.order_by('-date')
comments = Comment.objects.all()
return render(request, 'post.html', {'datas': datas, 'comments': comments})
and this is template
{% extends 'layout.html' %}
{% block main %}
<div class="container">
{% for data in datas %}
<div class="row">
<div class="col s12 m7">
<div class="card">
<div class="card-image">
<img src="#">
<span class="card-title">{{ data.title }}</span>
</div>
<div class="card-content">
<p>{{ data.content }}</p>
</div>
<div class="card-action">
<p>{{ data.date }}</p>
</div>
<div class="card-action">
{% for comment in comments %}
{% if comment.post == data.title %}
{{ comment.date }}<br>
<strong>{{ comment.author }}</strong>
<p>{{ comment.content }}</p>
{% endif %}
{% empty %}
<p>There is no comments</p>
{% endfor %}
</div>
</div>
</div>
</div>
{% empty %}
<p>there is no posts</p>
{% endfor %}
</div>
{% endblock %}
I want to display posts and comments
when I try to have two posts and each post has one comments
it shows like each posts has two comments
so I added {% if comment.post == data.title %} in the template
but it shows nothing
I tried to find answers on google, youtube, some tutorial page....
but what I found was just how to add comments on posts..
or displaying post and comment but actually one post one comment
You don't need to query list of comments in you views, you need just posts:
def post(request):
datas = Post.objects.order_by('-date')
return render(request, 'post.html', {'datas': datas})
And in template you can then do something like this:
{% block main %}
<div class="container">
{% for data in datas %}
...
<div class="card-action">
{% for comment in data.comments.all %} // Gives list of all comments for the current post ie. data
{{ comment.date }}<br>
<strong>{{ comment.author }}</strong>
<p>{{ comment.content }}</p>
{% empty %}
<p>There is no comments</p>
{% endfor %}
</div>
{% empty %}
<p>there is no posts</p>
{% endfor %}
</div>
...
{% endblock %}
Btw the thing that's wrong with the if condition in your template is that you are doing {% if comment.post == data.title %} but commpent.post is an object of model Post and post.title is string, so they are never equal. What you need to do is {% if comment.post == data %} or {% if comment.post.title == data.title %}
In your post view, instead of:
comment = Comment.objects.all()
which will fetch all the comments irrespective of the post it belongs to,
do this:
comment = datas.comments.all()
where the 'comments' is the related_name declared in the post field of the Comment model.
I'm building a site where I publish a notice and it appear in one webpage but my code dosen't return the objects. I post my code then:
Models:
from django.db import models
class Contenidos(models.Model):
title = models.CharField(max_length = 255)
content = models.TextField()
created = models.DateTimeField(auto_now_add=True)
published = models.BooleanField(default=True)
class Meta:
ordering = ['-created']
def __unicode__(self):
return u'%s' % self.title
Views:
from django.shortcuts import render
from granada.models import Contenidos
def contenidos(request):
contenido_list = Contenidos.objects.all()
return render(request, 'contenidos.html', {'contenido_list' : contenido_list})
contenidos.html
{% extends 'base.html' %}
{% block title %} Contenidos {% endblock %}
{% block content %}
<h2> contenidos </h2>
{% for contenido in contenido_list %}
<h3>
{{ contenido_list.title }}
</h3>
<p>{{ contenido_list.content }}</p>
{% endfor %}
{% endblock %}
You're accessing the wrong object in your loop, contenidos instead of contenido.
{% extends 'base.html' %}
{% block title %} Contenidos {% endblock %}
{% block content %}
<h2> contenidos </h2>
{% for contenido in contenidos %}
<h3>
{{ contenido.title }} {# was contenidos.title #}
</h3>
<p>{{ contenido.content }}</p>
{% endfor %}
{% endblock %}