I have to let the "comment" show in the report_detail.html
I an using Django 2.2 , I have tried to add some code to views.py but failed. The Report need to show the comment below, however, I try add some code in views.py and report_detail.html but it can not work, how can I do ? thank you
models.py
class Report(models.Model):
done = models.TextField('what done')
willDo = models.TextField('will do')
date = models.DateTimeField(auto_now_add=True)
author = models.ForeignKey(
get_user_model(),
on_delete=models.CASCADE,
)
def __str__(self):
return self.done
def get_absolute_url(self):
return reverse('report_detail', args=[str(self.id)])
class Comment(models.Model):
report = models.ForeignKey(
Report,
on_delete=models.CASCADE,
related_name='comments',
)
comment = models.CharField(max_length=140)
author = models.ForeignKey(
get_user_model(),
on_delete=models.CASCADE,
)
def __str__(self):
return self.comment
def get_absolute_url(self):
return reverse('report_list')
views.py
class ReportDetailView(LoginRequiredMixin, DetailView):
model = Report
template_name = 'report_detail.html'
login_url = 'login'
report_detail.html
<div class="article-entry">
<h2>{{ object.done }}</h2>
<p>by {{ object.author }} | {{ object.date }}</p>
<p>{{ object.willDo }}</p>
</div>
I think that what you want to do is just this:
<div class="article-entry">
<h2>{{ object.done }}</h2>
<p>by {{ object.author }} | {{ object.date }}</p>
<p>{{ object.willDo }}</p>
{% for comment in object.comments.all %}
<p>{{ comment.comment }}</p>
{% endfor %}
</div>
Related
I am working on a To-do app. The individual to-dos reference a to-do list via a foreign key and the to-do lists reference a project via a foreign key.
I want the to-do's status to be set to true when clicked. I have seen some tutorials where this is done but I haven't been able to get this to work yet.
Here are the models:
class Project(models.Model):
title = models.CharField(max_length= 200)
description = tinymce_models.HTMLField()
status = models.CharField(max_length=20, choices=PROJECT_CHOICES, default="active")
date = models.DateTimeField(auto_now_add=True, null=True)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse ('project_detail', args=[str(self.id)])
class ProjectTodoGroup(models.Model):
title = models.CharField(max_length=250)
description = tinymce_models.HTMLField()
project = models.ForeignKey(Project, blank=True, on_delete=models.CASCADE, related_name='todo_group')
date = models.DateTimeField(auto_now_add=True, null=True)
def __str__(self):
return self.title
class ProjectTodo(models.Model):
title = models.CharField(max_length= 250)
notes = tinymce_models.HTMLField()
status = models.BooleanField(default=False)
projectgroup = models.ForeignKey(ProjectTodoGroup, blank=True, null=True, on_delete=models.CASCADE, related_name='todo_set')
date = models.DateTimeField(auto_now_add=True, null=True)
def __str__(self):
return self.title
The view:
model = ProjectTodo
fields = ['status']
def get_context_data(self, **kwargs):
# Call the base implementation first to get a context
context = super().get_context_data(**kwargs)
context['project'] = get_object_or_404(Project, id=self.kwargs.get('pk'))
return context
def get_success_url(self):
return reverse('company_project:todo_group_detail', args=[self.kwargs.get('pk'), (self.object.id)])
Everything I have tried to far with the view hasn't worked.
The template:
{% extends 'base.html' %}
{% load crispy_forms_tags %}
{% block content %}
<div class="section-container container">
<div class="todo-group">
<h2>{{ projecttodogroup.title }}</h2>
<p>{{ projecttodogroup.description | safe }}</p>
</div>
<div><b>Todos</b></div>
{% if projecttodogroup.todo_set.all %}
{% for todo in projecttodogroup.todo_set.all %}
<div class="todos" style="padding: 10px;">
{{ todo.title }}
</div>
{% endfor %}
{% else %}
<p>No Todos have been have been added yet.</p>
{% endif %}
<h1>Add Todo</h1>
<form action="" method="post">
{% csrf_token %}
{{ form.media }}
{{ form|crispy }}
<input type="submit" value="save">
</form>
</div>
{% endblock content %}
my models:
class Company(models.Model):
name = models.CharField(max_length=250)
def __str__(self):
return str(self.name)
class Products(models.Model):
company = models.ForeignKey(Company, on_delete=models.CASCADE, related_name="display")
engine = models.CharField(max_length=250, blank=True)
cyl = models.CharField(max_length=250, blank=True)
bore = models.CharField(max_length=250, blank=True)
def __str__(self):
return str(self.engine) + " (ref:" + str(self.ref) + ")"
my views.py:
def Companies(request):
context = {
'categories': Company.objects.all()
}
return render(request, 'product_list.html', context)
HTML :
{% for category in categories %}
<h2>{{ category.name }}</h2>
{% for item in category.item_set.all %}
{{ item_engine }}
{% endfor %}
{% endfor %}
how do i display every objects of Products(engine,cyl,bore) following its name
If you want to get related field using ForeignKey try with prefetch_related() method like this
add this in your views.py file
def Companies(request):
context = {
'categories': Products.objects.prefetch_related('company')
}
return render(request, 'product_list.html', context)
this will return object when you try to access your Company object in template like this {{ category.company }} it will give you output like this Company object (1) and you can access all attributes from your Company model.
add this in your template
{% for category in categories %}
<h2>{{ category.company.name }}</h2>
<p>{{ category.engine }}</p>
<p>{{ category.cyl }}</p>
<p>{{ category.bore }}</p>
{% endfor %}
if you delete any Company it will be not displayed on template.
I am creating a blog in which I need a comment section(first project ever, 3 weeks into Python/Django). So far I've created 2 models(Blog which is the main and Comment which is linked with a foreign key to the Blog) but for some reason, I can't find the proper way to display the information from the Comment model into my HTML section.
I've tried with dictionaries, rewrote the models and the views multiple times(due to different youtube videos that I found) but nothing seems to work properly.
These are my models :
class Blog(models.Model):
title = models.CharField('Blog\'s title', max_length=100, blank=False)
slug = models.SlugField('Enter your blog\'s url', blank=False)
date = models.DateTimeField('Date and time on publication',
blank=False)
content = models.TextField(blank=False)
thumb = models.ImageField(blank=True, null=True,
default='default_blog_icon.jpg')
def __str__(self):
return self.title
def snippet(self):
return self.content[:50] + ' ' +'...'
class Comment(models.Model):
post = models.ForeignKey(Blog, on_delete=models.CASCADE,
related_name='comments')
user = models.CharField(max_length=200)
body = models.TextField(max_length=200)
created = models.DateTimeField(auto_now_add=True)
approved = models.BooleanField(default=False)
def approved(self):
self.approved = True
self.save()
def __str__(self):
return self.user
The views :
def index(request):
blogs = Blog.objects.all().order_by('-date')
comments = Comment.objects.all()
args = {'blogs': blogs, 'comments': comments}
return render(request, "blog/index.html", args)
def blog_details(request, slug):
slug_url = Blog.objects.get(slug=slug)
return render(request, 'blog/blog_details.html', {'blog_info': slug_url})
And the HTML :
{% for blog in blogs %}
<div class="bloggy">
<h3><a href="{% url 'blog_details' slug=blog.slug %}">{{
blog.title }}</a></h3>
<img src ="/media/{{ blog.thumb }}">
<p>{{ blog.snippet }}</p>
<p>Posted on {{ blog.date }}</p>
<p>{{ comments }}</p>
<p>{{ Comments.Blog.get_user }}</p>
<p>{{ comment.user }}</p>
<p>{{ comment.created }}</p>
<p>{{ comment.approved }}</p>
</div>
{% endfor %}
So far the only thing that I am getting on the front end is the {{ comments }} which is giving me the username that I set. Apart from that nothing else is showing.
I need somehow to display the username, the body of the comment(the content itself) and the date.
Any help, feedback or guidance will be greatly appreciated.
Cheers
You can access the comment for each blog this way:
In your views.py:
def index(request):
blogs = Blog.objects.all().prefetch_related('comments').order_by('-date')
args = {'blogs': blogs}
return render(request, "blog/index.html", args)
Then in your template, you can change the HTML to this:
{% for blog in blogs %}
<div class="bloggy">
<h3>{{blog.title}}</h3>
<img src ="/media/{{ blog.thumb }}">
<p>{{ blog.snippet }}</p>
<p>Posted on {{ blog.date }}</p>
{% for comment in blog.comments.all %}
<p>{{ comment.blog.get_user }}</p>
<p>{{ comment.user }}</p>
<p>{{ comment.created }}</p>
<p>{{ comment.approved }}</p>
{% endfor %}
</div>
{% endfor %}
Models
class Category(models.Model):
class Meta():
verbose_name_plural = "Categories"
cat_name = models.CharField(max_length=50)
description = models.TextField()
def get_forums(self):
get_forum = Forum.objects.filter(category=self)
return get_forum
def __str__(self):
return f"{self.cat_name}"
class Forum(models.Model):
class Meta():
verbose_name_plural = "Forums"
category = models.ForeignKey(Category, on_delete=models.CASCADE, related_name="forums")
parent = models.ForeignKey('self', blank=True, null=True, on_delete=models.CASCADE)
forum_name = models.CharField(max_length=50)
description = models.TextField()
def __str__(self):
return f"{self.forum_name}"
class Thread(models.Model):
class Meta():
verbose_name_plural = "Threads"
get_latest_by = "date_posted"
forum = models.ForeignKey(Forum, on_delete=models.CASCADE, related_name="threads")
author = models.ForeignKey(User, on_delete=models.CASCADE)
title = models.CharField(max_length=50)
content = models.TextField()
date_posted = models.DateTimeField(default=timezone.now)
def __str__(self):
return f"{self.title} by: {self.author}"
View
class Home(ListView):
model = Category
template_name = 'forums/index.html'
context_object_name = 'category'
def get_context_data(self, **kwargs):
# Call the base implementation first to get a context
context = super().get_context_data(**kwargs)
# Add in a QuerySet of all the Cat
context['category'] = Category.objects.all()
return context
HTML
{% block content %}
{% for cat in category %}
<div style="padding-top: 20px;">
<div class="row">
<div class="bg-success rounded-top border border-dark" style="width:100%; padding-left:8px;">
{{ cat.cat_name }}
</div>
</div>
{% for forum in cat.forums.all %}
<div class="row">
<div class="bg-secondary border border-dark" style="width:100%; padding-left:16px;">
{{ forum.forum_name }}
{% for threads in forum.threads.all %}
<div class="float-right" id="latest-post">
<p>{{ threads.title }}</p>
<p> {{ threads.author.username }} </p>
</div>
{% endfor %}
</div>
</div>
{% endfor%}
</div>
{% endfor %}
{% endblock content %}
Problem
I am building a forums and am trying to get my homepage to show the last post in a forum.
I have got it to work to show all threads, but i just want the latest one to show on the latest post div.
I setup the get_latest_by on the Thread model so that it gets the latest one by the time created.
How would i be able to get this to display the latest thread?
You can set a property on the Form model, and then call it in the template.
views.py
class Form(models.Model):
...
#property
def get_newest_thread(self):
return self.threads.all().order_by('date_posted').first()
html
{% with threads=forum.get_newest_thread %}
<div class="float-right" id="latest-post">
<p>{{ threads.title }}</p>
<p> {{ threads.author.username }} </p>
</div>
{% endwith %}
I have two models in my blog app:
class Tag(models.Model):
tag_name = models.CharField(max_length=20,
null=True)
def __str__(self):
return self.tag_name
class Post(models.Model):
tag = models.ManyToManyField(Tag, related_name="blog_tag",
blank=True)
In views i have:
tags = Tag.objects.all()
And
post = get_object_or_404(Post,
status="published",
publish__year=year,
publish__month=month,
publish__day=day,
slug=post)
So my question is - how can i filter tags by post ? I mean that i want to show only tags what i add to my post. I tried to do than in template , but something dosen't work :
{% for tag in tags %}
{% if tag in post %}
<div>
{{ tag.tag_name }}
</div>
{% endif %}
{% endfor %}
Post model:
class Post(models.Model):
STATUS_CHOICES = (
("draft", "Draft"),
("published", "Published"),
)
title = models.CharField(max_length=250)
slug = models.SlugField(max_length=250,
unique_for_date="publish")
author = models.ForeignKey(User,
related_name="blog_posts",
on_delete=models.CASCADE)
tag = models.ManyToManyField(Tag, related_name="blog_tag",
blank=True)
body = models.TextField()
publish = models.DateTimeField(default=timezone.now)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
status = models.CharField(max_length=10,
choices=STATUS_CHOICES,
default="draft")
image = models.ImageField(upload_to="blog/%Y/%m/%d",
blank=True)
class Meta:
ordering = ("-publish",)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse("blog:post_detail",
args=[self.publish.year,
self.publish.strftime("%m"),
self.publish.strftime("%d"),
self.slug])
The answer is:
{% for tag in post.tag.all %}
<div class="fa fa-plus-square">
{{ tag.tag_name }}
</div>
{% endfor %}
Since you're using a ManyToManyField in the Post class, it would be clearer if that field was called tags rather than tag, since it is referring to more than one thing.
class Post(models.Model):
tags = models.ManyToManyField(Tag, related_name="blog_tag",
blank=True)
So once you have looked up a post with:
post = get_object_or_404(Post,
status="published",
publish__year=year,
publish__month=month,
publish__day=day,
slug=post)
You pass it to the template with:
return render(request, 'post_detail.html', {'post': post})
And then in the post_detail.html you can render the tags associated with the post:
{% for tag in post.tags.all %}
<div>
{{ tag.tag_name }}
</div>
{% endfor %}
No need to explicitly filter the tags as the ManyToManyField handles that for you.
You can do this :
{%for tag in tags %}
{% if tag.id == post.tag.id%}
<div>
{{ tag.tag_name }}
</div>
{%endif%}
{%endfor%}