I have two applications (blog and category). On the post list template I would like to get the category blog name and description.
I have tried to put the import category model in the blog view, but nothing show up. So I have made two views rendering the same template, but it does not work.
Blog models:
from django.db import models
from django.utils import timezone
from autoslug import AutoSlugField
from category.models import Category
class Post(models.Model):
author = models.ForeignKey('auth.User', on_delete=models.CASCADE)
category = models.ForeignKey(Category, on_delete=models.CASCADE,
default = '')
title = models.CharField(max_length=200)
...
class Meta:
verbose_name = "Post"
verbose_name_plural = "Posts"
ordering = ['created_date']
def publish(self):
self.published_date = timezone.now()
self.save()
def __str__(self):
return self.title
category models:
class Category(models.Model):
name = models.CharField(max_length=200)
slug = AutoSlugField(populate_from='name', default='')
parent = models.ForeignKey('self', blank=True, null=True, related_name='children', on_delete=models.CASCADE)
description = models.TextField(max_length=200)
class Meta:
unique_together = ('slug', 'parent',) # Enforcing that there can not be two
verbose_name_plural = "categories" # categories under a parent with same
# slug
def __str__(self): # __str__ method elaborated later in
full_path = [self.name] # post. use __unicode__ in place of
# __str__ if you are using python 2
k = self.parent
while k is not None:
full_path.append(k.name)
k = k.parent
return ' -> '.join(full_path[::-1])
Blog view:
def post_list(request):
posts = Post.objects.all()
cat_blog = Category.objects.get(pk=1)
context = {
'posts': posts,
'cat_blog': cat_blog
}
return render(request, 'blog/post_list.html', context)
Category view:
def cat_blog(request):
cat_blog = Category.objects.get(pk=1)
return render(request, 'blog/post_list.html', {'cat_blog': cat_blog})
post_list.html:
<div class="section-header text-center">
{% for category in cat_blog %}
<h1>{{ category.name }}</h1>
<p class="tag">{{ category.description }}</p>
{% endfor %}
</div>
<div class="row py-5">
{% for post in posts %}
// This part is fine
{% endfor%}
The post loop is fine. How can't I get the category name and description in my section header?
One URL gives one View gives one template.
You use the View to give context to the template to render.
def post_list(request):
posts = Post.objects.all()
cat_blog = Category.objects.get(pk=1)
context = {
'posts': posts,
'cat_blog': cat_blog
}
return render(request, 'blog/post_list.html', context)
Your url.py file should point to the post_list view.
Related
I am following this tutorial
I have gone back and written the code to match exactly. I have another form that works called category_add which is exactly the same as this form. But for the life of me I cannot figure out why bookmark_add doesn't update the database with the form entries.
Models.py
from django.db import models
from django.contrib.auth.models import User
class Category(models.Model):
title = models.CharField(max_length=255)
description = models.TextField(blank=True, null=True)
created_by = models.ForeignKey(User, related_name='categories', on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
verbose_name_plural = 'Categories'
def __str__(self):
return self.title
class Bookmark(models.Model):
category = models.ForeignKey(Category, related_name='bookmarks', on_delete=models.CASCADE)
title = models.CharField(max_length=255)
description = models.TextField(blank=True, null=True)
url = models.CharField(max_length=255, blank=True)
created_by = models.ForeignKey(User, related_name='bookmarks', on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.title
View.py
from django.shortcuts import render, redirect
from django.contrib.auth.decorators import login_required
from .forms import BookmarkForm
#login_required
def bookmark_add(request, category_id):
if request.method == 'POST':
form = BookmarkForm(request.POST)
if form.is_valid():
bookmark = form.save(commit=False)
bookmark.created_by = request.user
bookmark.category_id = category_id
bookmark.save()
return redirect('category', category_id=category_id)
else:
form = BookmarkForm()
context = {
'form': form
}
return render(request, 'bookmark/bookmark_add.html', context)
Forms.py
from django.forms import ModelForm
from .models import Bookmark
class BookmarkForm(ModelForm):
class Meta:
model = Bookmark
fields = ['title', 'description', 'url']
Urls.py
path('', dashboard, name='dashboard'),
path('categories/', categories, name='categories'),
path('categories/add/', category_add, name='category_add'),
path('categories/<int:category_id>/', category, name='category'),
path('categories/<int:category_id>/add_bookmark', bookmark_add, name='bookmark_add')
]
bookmark_add.html
{% extends 'core/base.html' %}
{% block content %}
<div class="container">
<h1 class="title">Add link</h1>
<form method="post" action=".">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="button is-primary">Submit</button>
</form>
</div>
{% endblock %}
Solved this!
This was a dumb issue and an oversight on my end. Thanks to the content creator on youtube. I just needed to append "/" to the url path for add_bookmark.
Problem:
path('categories/<int:category_id>/add_bookmark', bookmark_add, name='bookmark_add')
The Fix:
path('categories/<int:category_id>/add_bookmark/', bookmark_add, name='bookmark_add')
This is my code,
I use django v3 and want convert the category functions in views.py to a list class(ListView) for use pagination.
How can do it?
Thank you alot
urls.py
from django.urls import path from .views import posts_category
urlpatterns = [
path('<slug:slug>/', posts_category, name="posts_category"),
]
model.py
class Category(models.Model):
parent = models.ForeignKey('self', blank=True, null=True, related_name='children', on_delete=models.CASCADE)
title = models.CharField(max_length=70, unique=True)
slug = models.SlugField(max_length=90, unique=True)
description = RichTextUploadingField(blank=True, null=True)
image = models.ImageField(blank=True, upload_to="imgs")
def __str__(self):
return self.title
class MPTTMeta:
order_insertion_by = ['title']
views.py
def posts_category(request, slug):
category = Category.objects.all()
post = Posts.objects.filter(category__slug=slug, status="p")
context = {
'category': category,
'post': post,
}
return render(request, 'posts_category.html', context)
I don't know if this is a good idea to show categories and products in the same page (because of the performance point of view) but you can use following code to convert your FBV to CBV:
from django.views.generic import ListView
class PostCategoryView(ListView):
template_name = 'posts_category.html'
def get_queryset(self):
slug = self.kwargs.get('slug')
return Posts.objects.filter(category__slug=slug, status="p")
def get_context_data(self, **kwargs):
context = super().get_context_data()
context['categories'] = Category.objects.all()
return context
And also change your urls to:
from django.urls import path
from .views import PostCategoryView
urlpatterns = [
path('<slug:slug>/', PostCategoryView.as_view(), name="posts_category"),
]
And finally you can use the context data in your template like the following code:
{% for obj in object_list %}
{{ obj.id }} - {{ obj.name }}</a><br>
{% endfor %}
Note that object_list is a list of your Post objects and you should change obj.name to other fields of your Post model. Finally you can use something like object_list (here we used categories) and loop through it to show the data of your categories or other things.
I want to fetch all the foreignkey table's attribute and show it in my HTML template. Here is my code in models, views and in the template:
models.py:
class OrderDashboard(models.Model):
title = models.CharField(max_length=100,default=None)
single_slug = models.SlugField(max_length=100, default=1)
description = models.TextField(max_length=1000)
thumb = models.ImageField()
date = models.DateField()
def __str__(self):
return self.title
class OrderScenario(models.Model):
webshop = models.CharField(max_length=100)
title = models.ForeignKey(OrderDashboard, default=None, on_delete=models.SET_DEFAULT)
order_qty = models.TextField(max_length=10)
order_date = models.DateField()
current_status = models.CharField(max_length=100)
ticket = models.CharField(max_length=200)
remark = models.TextField()
class Meta:
verbose_name_plural = "Scenario"
def __str__(self):
return self.webshop
Views.py:
def single_slug(request, single_slug):
report = OrderDashboard.objects.get(single_slug=single_slug)
return render(request, 'order_dashboard/report.html', {'report': report,
'OrderScenario': OrderScenario.objects.all})
I only want to view all the scenarios added in OrderScenario with respect to Title in OrderDashboard.
You should use backward relationship here; if you are passing the slug through the url, you can use:
views.py:
def single_slug(request, slug): # why you have self as the first argument?
report = OrderDashboard.objects.get(single_slug=slug)
return render(request, 'order_dashboard/report.html', {'report': report}
report.html:
{{ report.title }}
</p>Order Scenarios:</p>
{% for scenario in report.orderscenario_set.all %}
{{ scenario }}
{% endfor %}
Alright so I want to order my topics by the category in Django. What's the best way of doing this?
views.py:
from django.shortcuts import render
from .models import Category
from .models import Topic
# Create your views here.
def forums(request):
categorys = Category.objects.all()
topics = Topic.objects.all()
return render(request, 'forums.html', {'categorys': categorys, 'topics': topics})
models.py:
from django.db import models
# Create your models here.
class Attachment(models.Model):
file = models.FileField()
def __str__(self):
return self.file
class Category(models.Model):
title = models.CharField(max_length=150)
def __str__(self):
return self.title
class Topic(models.Model):
title = models.CharField(max_length=150)
description = models.TextField()
category = models.ForeignKey('Category', on_delete=models.CASCADE)
def __str__(self):
return self.title
class Post(models.Model):
title = models.CharField(max_length=150)
body = models.TextField()
forum = models.ForeignKey('Topic', on_delete=models.CASCADE)
def __str__(self):
return self.title
Also, yes I know that categories is spelled wrong, I still need to add the Meta.
You can get all the topics inside categories in following way:
{% for category in categorys %}
<h1>{{category.title}}</h1>
<ul>
{% for topic in category.topic_set.all %}
<li>{{topic.title}}</li>
{% endfor %}
</ul>
{% endfor %}
I'm trying to return all posts associated with a tag using Django. I have searched for a solution but can't find one. I tried to code something but it didn't work. Heres my code
models.py
class Tag(models.Model):
title = models.CharField(max_length=250)
slug = models.SlugField(max_length=200, unique=True)
timestamp = models.DateTimeField(auto_now=False, auto_now_add=True)
updated = models.DateTimeField(auto_now=True, auto_now_add=False)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse("posts:tag_index", kwargs={"slug": self.slug})
class Meta:
ordering = ["-timestamp"]
class Post(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, default=1)
slug = models.SlugField(unique=True)
title = models.CharField(max_length=120)
image = models.ImageField(upload_to=upload_location, null=True, blank=True,
width_field="width_field",
height_field="height_field")
height_field = models.IntegerField(default=0)
width_field = models.IntegerField(default=0)
content = models.TextField()
draft = models.BooleanField(default=False)
publish = models.DateField(auto_now=False, auto_now_add=False)
timestamp = models.DateTimeField(auto_now=False, auto_now_add=True)
updated = models.DateTimeField(auto_now=True, auto_now_add=False)
tags = models.ManyToManyField(Tag)
objects = PostManager()
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse("posts:detail", kwargs={"slug": self.slug})
class Meta:
ordering = ["-timestamp"]
posts/urls.py
from .views import post_list, post_create, post_detail, post_update, post_delete, sewp, tag_detail
urlpatterns = [
url(r'^$', post_list, name='list'),
url(r'^tag/(?P<slug>[\w-]+)/$', tag_detail, name="tag_index"),
url(r'^create/$', post_create, name='create'),
url(r'^sewp$', sewp, name='sewp'),
url(r'^(?P<slug>[\w-]+)/$', post_detail, name='detail'),
url(r'^(?P<slug>[\w-]+)/edit/$', post_update, name='update'),
url(r'^(?P<id>\d+)/delete/$', post_delete, name='delete'),
]
views.py
def tag_detail(request, slug=None):
query = slug
queryset_list = Post.objects.active()
tags_list = queryset_list.filter(tags__icontains=query).distinct()
instance = get_object_or_404(Tag, slug=slug)
context = {
"instance": instance,
"tags_list": tags_list
}
return render(request, "posts/tag_index.html", context)
tag_index.html
{% extends 'posts/base.html' %}
{% block content %}
{{ instance }}
{{ tags_list }}
{% endblock content %}
I just want to return all the tags and paginate it.
and can I modify the following code to paginate my results :
paginator = Paginator(queryset_list, 2) # Show 25 contacts per page
page_request_var = "page"
page = request.GET.get(page_request_var)
try:
queryset = paginator.page(page)
except PageNotAnInteger:
# If page is not an integer, deliver first page.
queryset = paginator.page(1)
except EmptyPage:
# If page is out of range (e.g. 9999), deliver last page of results.
queryset = paginator.page(paginator.num_pages)
context = {
"queryset": queryset,
"title": "Posts",
"page_request_var": page_request_var,
"today": today,
"queryset_list": queryset_list,
"paginator": paginator,
}
any guidance or help on this will be appreciated
If you want to find all Posts associated with a tag, simply use:
posts = Post.objects.filter(tag__title = query)
This will return all posts with the tag specified by the query string.
Read more about making queries here: https://docs.djangoproject.com/en/1.9/topics/db/queries/
I would use a generic ListView like so:
from django.views.generic.list import ListView
from django.shortcuts import get_object_or_404
class TagView(ListView):
template_name = 'posts/tag_index.html'
def get_queryset(self):
""" get the Tag object or return 404 """
self.tag = get_object_or_404(Tag, slug=self.kwargs['slug'])
return Post.objects.filter(tag=self.tag)
def get_context_data(self, **kwargs):
""" add a posts variable to context to use in template """
context = super(TagView, self).get_context_data(**kwargs)
context['posts'] = Post.objects.filter(tag=self.tag)
This is the syntax based on views.py structure
views.py:
def tag_index(request, slug=None):
instance = get_object_or_404(Tag, slug=slug)
ins = instance.post_set.all()
context = {
"instance": ins,
}
return render(request, "posts/tag_list.html", context)
then in the tags_list.html
{% for i in instance %}
{{ i.title }}
{{ i.content }}
{% endfor %}
hope this helps somebody