I want to show my articles but
My article doesn't display on article_details.html
This is what my site looks like. You can see only my article's title works.
My models.py:
class Article(models.Model):
title = models.CharField(max_length=50, verbose_name="Title")
mini_description = models.TextField(max_length=100, default='', verbose_name='Mini_description')
content = models.TextField(blank=True, verbose_name="Content")
created_at = models.DateTimeField(auto_now_add=True, verbose_name="Date of add")
updated_at = models.DateTimeField(auto_now=True, verbose_name="Update date")
photo = models.ImageField(upload_to='photos/', verbose_name="Photo")
is_published = models.BooleanField(default=True, verbose_name="Is published")
category = models.ForeignKey(Category, on_delete=models.CASCADE, verbose_name="Category")
def get_absolute_url(self):
return reverse("article_details", kwargs={'pk': self.pk})
def __str__(self):
return self.title
def __repr__(self):
return f"Article(pk={self.pk}, title='{self.title}')"
class Meta:
verbose_name = "Article"
verbose_name_plural = "Articles"
ordering = ['-created_at']
My views.py:
class ArticleListByCategory(ListView):
model = Article
context_object_name = 'articles'
template_name = 'blog/details.html'
def get_queryset(self):
sort_filed = self.request.GET.get('sorter')
articles = Article.objects.filter(category_id=self.kwargs['pk'])
if sort_filed:
articles = articles.order_by(sort_filed)
return articles
class ArticleDetails(ArticleListByCategory):
model = Article
context_object_name = 'article'
template_name = 'blog/article_details.html'
def get_queryset(self):
article = Article.objects.filter(pk=self.kwargs['pk'], is_published=True).select_related('category')
return article
def get_context_data(self, **kwargs):
context = super().get_context_data()
article = Article.objects.get(pk=self.kwargs['pk'])
context['title'] = f"Article: {article.title}"
return context
My article_details.html:
{% extends "base.html" %}
{% load static %}
{% block style %}
<link href="{% static 'blog/css/main.css' %}" rel="stylesheet">
{% endblock style %}
{% block title %}
{{ title }}
{% endblock %}
{% block main %}
<section class="articles" id="articles">
<div class="card_details">
<h1>{{ article.title }}</h1>
<p><em>{{ article.mini_description }}
</em>
</p>
<img src="">
<div class="description">
<p>
{{ article.content }}
</p>
</div>
<div class="card-footer text-muted">
{{ article.created_at| timesince }} ago
</div>
</div>
</section>
{% endblock main %}
I don't know why my article doesn't display.
What I'd suggest here is using the Django Generic View called DetailView. For example, you could do the following:
from django.views.generic import DetailView
class ArticleDetails(DetailView):
context_object_name = 'article'
template_name = 'blog/article_details.html'
# Using the get_object method here, not get_queryset.
def get_object(self, queryset=None):
article = Article.objects.filter(pk=self.kwargs['pk'], is_published=True).select_related('category')
return article
Ideally, that should work.
Related
I have a category model and list of posts related to those category also some post with same category name but when i wanted to make list of category section in template,
it showing duplicate name of category as it related to posts like:
food,
food,
desert,
style,
desert,
but I want like:
food,
desert,
style,
here is my code:
views.py
class ListCategory(ListView):
model = Post
paginate_by = 2
template_name = 'shit.html'
context_object_name = 'queryset'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
cate = Post.objects.all()
context['cate'] = cate
return context
models.py
class Category(models.Model):
title = models.CharField(max_length=20)
thumbnail = models.ImageField()
detail = models.TextField()
featured = models.BooleanField(default=True)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('post-category', kwargs={
'pk': self.pk
})
class Post(models.Model):
title = models.CharField(max_length=100)
overview = models.TextField()
featured = models.BooleanField(default=True)
timestamp = models.DateTimeField(auto_now_add=True)
user = models.ForeignKey(Author,on_delete=models.CASCADE)
thumbnail = models.ImageField()
category = models.ForeignKey(Category, on_delete=models.CASCADE)
tags = TaggableManager()
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('post-detail', kwargs={
'pk': self.pk
})
templates
{% extends "base.html" %}
{% load static %}
{% block content %}
<div class="sidebar-box ftco-animate">
<ul class="categories">
<h3 class="heading mb-4">Categories</h3>
{% for cat in cate %}
<li>{{cat.category}}<span>(12)</span></li>
{% endfor %}
</ul>
</div>
{% endblock content %}
Thank you so much!
Seems like you want to group your Posts, based on their category; so you can achieve that by iterating over the Category (instead of Post), and use the backward relationship to find out the related Post objects.
views.py
class ListCategory(ListView):
model = Category
paginate_by = 2
template_name = 'shit.html' # :)
context_object_name = 'queryset'
template:
{% extends "base.html" %}
{% load static %}
{% block content %}
<div class="sidebar-box ftco-animate">
<ul class="categories">
<h3 class="heading mb-4">Categories</h3>
{% for category in queryset %}
<li>{{category}}<span>{{ category.posts_set.count }}</span></li>
<ul>
{% for post in category.post_set.all %}
<li>{{ post }}</li>
{% endfor %}
</ul>
{% endfor %}
</ul>
</div>
{% endblock content %}
I also use {{ category.post_set.count }} instead of 12, since I think you are looking for the number of Post objects within each category.
You can use unique=True in desired field, to make every value unique. If you'll try to add new record with same value of unique field, a django.db.IntegrityError will be raised.
More about unique
More about model's fields options
I have a list that is generated by a method on one of my models. On the home page it works wonderfully, however when I go to a detail view of one project I can access all the parts of that project as they are direct fields of the Model, but I can't access the items in the list.
Model:
class Project(models.Model):
date_published = models.DateTimeField(auto_now_add=True)
user = models.ForeignKey(User, null=True, on_delete=models.SET_NULL)
area = models.ForeignKey(Area, on_delete=models.PROTECT)
title = models.CharField(max_length=128, unique=True)
slug = models.SlugField(max_length=64)
summary = models.CharField(max_length=256)
others = models.CharField(max_length=128, blank=True)
deadline = models.DateField(null=True, blank=True)
priority = models.ForeignKey(Priority, on_delete=models.PROTECT)
closed = models.DateTimeField(null=True, blank=True)
def save(self, *args, **kwargs):
if not self.id:
self.slug = slugify(self.title)
super(Project, self).save(*args, **kwargs)
#property
def updates(self):
updates = []
sequence_id = 1
categories = set(self.update_set.all().values_list(
'category__id', flat=True))
for cat_id in categories:
a = Update.objects.filter(
project=self, category__id=cat_id).order_by('added').last()
if cat_id == sequence_id:
updates.append(a)
else:
for i in range(cat_id - sequence_id):
updates.append('null')
updates.append(a)
sequence_id = cat_id
sequence_id += 1
return updates
class Update(models.Model):
project = models.ForeignKey(Project, on_delete=models.CASCADE)
category = models.ForeignKey(UpdateCategory, on_delete=models.PROTECT)
update = models.TextField(max_length=240, blank=True)
added = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.update
The view is simple:
class ProjectDetailView(DetailView):
template_name = 'project_portal/project_detail.html'
queryset = Project.objects.all()
and here is the dynamic url that I am using:
path('project/<int:pk>/',
ProjectDetailView.as_view(), name='project_detail'),
As for the template, I'm lost, here is one of the things I have tried:
<!DOCTYPE html>
{% extends "project_portal/base.html" %}
{% block home %}
<div id="main">
<div id="content">
<div>
<h1>{{ object.title }}</h1>
<h1>hello</h1>
{% if object_list %}
{% for item in updates %}
<p>{{ item }}</p>
{% endfor %}
{% else %}
<h2>No records found for this project</h2>
{% endif %}
</div>
</div>
</div>
{% endblock %}
What do I need to do to access the "updates" list that gets generated?
update is a property of the model instance, you need to access it from there like any other attribute. Also note, there is no object_list in a detail view.
<div>
<h1>{{ object.title }}</h1>
<h1>hello</h1>
{% for item in object.updates %}
<p>{{ item }}</p>
{% endfor %}
</div>
I can't solve this problem. When you try to load the page, list_of_post_by_subcategory.html throws TemplatesDoesNotExist, Please help.
models.py
class Category(models.Model):
category = models.CharField(max_length=250)
slug = models.SlugField()
def __str__(self):
return self.category
def get_absolute_url(self):
return reverse('list_of_post_by_category', args=[self.slug])
class SubCategory(models.Model):
category = models.ForeignKey(Category, on_delete=models.SET_NULL, null=True, blank=True, related_name="subcategories")
subcategory = models.CharField(max_length=250)
slug = models.SlugField()
def __str__(self):
return self.subcategory
def get_absolute_url(self):
return reverse('list_of_post_by_subcategory', args=[self.slug])
urls.py
url(r'^category/(?P<slug>[-\w]+)/$', views.list_of_post_by_category, name= 'list_of_post_by_category'),
url(r'^subcategory/(?P<slug>[-\w]+)/$', views.list_of_post_by_subcategory, name= 'list_of_post_by_subcategory'),
views.py
def list_of_post_by_category(request, slug):
categories = Category.objects.all()
category=get_object_or_404(Category, slug = slug)
subcategories = SubCategory.objects.filter(category=category)
posts = Post.objects.filter(category=category)
return render(request, "account/list_of_post_by_category.html", {'categories': categories, 'posts': posts, 'category': category, 'subcategories': subcategories})
def list_of_post_by_subcategory(request, slug):
subcategory=get_object_or_404(SubCategory, slug=slug)
posts = Post.objects.filter(subcategory=subcategory)
return render(request, "account/list_of_post_by_subcategory.html", {'posts': posts, 'subcategory': subcategory})
list_of_post_by_subcategory.html
{% extends "base.html" %}
{% block title %}{{ subcategory.subcategory }}{% endblock %}
{% block content %}
<h1>{{ subcategory.subcategory }}</h1>
{% for post in posts %}
<div class="single_post">
{{ post.title }}
<br/>
<br/>
<div>
{{ post.publish }}
{{ post.subcategory }}
</div>
</div>
{% endfor %}
<br/>
{% endblock %}
Similar template list_of_post_by_category.html loads correctly. But list_of_post_by_subcategory.html throws TemplateDoesNotExist.
The filenames don't match here. You posted your error as account/list_of_post_by_subactegory.html TemplateDoesNotExist Look at the name of html file you mentioned(subactegory). And the one you are calling has this name account/list_of_post_by_subcategory.html
I have a this models
class Project(models.Model):
name = models.CharField(max_length=20)
description = models.CharField(max_length=200, null=True, blank=True)
creation_date = models.DateTimeField(auto_now_add=True, auto_now=False)
group_owner = models.ForeignKey(User)
def __str__(self, y):
return smart_str(self.name)
class Note(models.Model):
title = models.CharField(max_length=50, null=True, blank=True)
content = models.CharField(max_length=1000)
creation_date = models.DateTimeField(auto_now_add=True, auto_now=False)
updated_date = models.DateTimeField(auto_now_add=False, auto_now=True)
projectId = models.ForeignKey(Project, on_delete=models.CASCADE)
userid = models.ForeignKey(User, on_delete=models.CASCADE)
def __str__(self):
return smart_str(self.title)
which i would like to join them in one view, which would be shown when someone enters to this url http://localhost.com:8000/project/ID.
obviously the ID will depend in Project.id and it will have to get all the Notes that are related to it.
Meanwhile my views.py looks like this
class ProjectDetail(generic.DetailView):
model = Project
template_name = 'scribere/project/detail.html'
def get_queryset(self):
return Project.objects.filter(group_owner__exact=self.request.user.id)
class ProjectNoteList(generic.ListView):
context_object_name = 'project_note_list'
template_name = 'scribere/note/index.html'
def get_queryset(self):
return Note.objects.filter(userid__exact=self.request.user.id, projectId__exact=self.kwargs['pk'])
and the template
{% extends "base/adminsNavBar.html" %}
{% load i18n %}
{% block head_title %}{% trans 'Projects Details' %}{% endblock %}
{% block breadcrumbs %}
<div class="breadcrumb"><p>{% trans 'Project Details' %}</p></div>
{% endblock %}
{% block content %}
<div class='row'>
{% trans 'Back' %}
{% trans 'Notes' %}
</div>
<div>
{{project.name}}
</div>
<div class = "note-list">
<ul>
{% for note in project_note_list %}
<li>
{{note}}
</li>
{% endfor %}
</ul>
</div>
{% endblock %}
which doesn't load any information about the note. What am i missing?
Unless you are populating project_note_list with some information, there will be nothing to iterate over.
By virtue of the ForeignKeys, and having a Many to one relation the project object will have a set of notes associated with it, without having to look them up.
You should be able to query them using project.note_set.all() or in your template by using:
{% for note in project.note_set %}
I seem to have a problem with calling a method from a django template. Given the model:
class Gallery(models.Model):
class Meta:
verbose_name_plural = "Galerie"
def photo_count(self):
return self.photo_set.count()
def random_image(self):
return self.photo_set.get(id=random.randint(1,self.photo_count()))
title = models.CharField(max_length=50)
imgur_id = models.CharField(max_length=15)
date_created = models.DateTimeField('Data utworzenia', auto_now=True)
is_active = models.BooleanField()
def __unicode__(self):
return self.title
where Gallery is foreignKey for Photo
views.py:
def index(request):
galleries = Gallery.objects.get(is_active=True)
if galleries.count() is 0:
messages.warning(request, "Niestety, żadna galeria nie jest aktywna, zaglądnij niebawem!")
return redirect(reverse(home))
elif galleries.count() is 1:
return render(request, 'gallery/home.html', {'gallery': galleries})
else:
return render(request, 'gallery/index.html', {'galleries': galleries})
I want to do this in template:
{% for gallery in galleries %}
{{ gallery.random_image }} <br />
{% endfor %}
The result I get is:
[ Photo object ]
[]
[]
[]
But when i call
{% for gallery in galleries %}
{{ gallery.photo_count }} <br />
{% endfor %}
The result is correct.
Why does this not work?
In my opinion you are complicated a little bit.
class Gallery(models.Model):
class Meta:
verbose_name_plural = "Galerie"
def random_image(self):
return self.photo_set.order_by('?')[0] if self.photo_set.count() else None
title = models.CharField(max_length=50)
imgur_id = models.CharField(max_length=15)
date_created = models.DateTimeField('Data utworzenia', auto_now=True)
is_active = models.BooleanField()
def __unicode__(self):
return self.title
and in the template,
{% for gallery in galleries %}
{% if gallery.random_image %}
{{ gallery.random_image }} <br />
{% else %}
No images found.
{% endif %}
{% endfor %}
Read more on order_by here
Note that ? could prove slightly heavy. If so, get thelist of ids of the photo_set associated with this gallery object, and get a random id from this list, rather than doing a
random.randint(1,self.photo_count())
Add #property to your fonction.
#property
def photo_count(self):
return self.photo_set.count()