I wrote in top.html
<div>
<a href="#">
Category
</a>
<div>
{% for category in category_content %}
<a href="{% url 'category' category.name %}">
{{ category.name }}
</a>
{% endfor %}
</div>
</div>
in category.html like
<div>
{% for content in queryset %}
<h2>{{ content.title }}</h2>
SHOW DETAIL
{% endfor %}
</div>
When I put in top.html,no error happens and page is shown but no <h2>{{ content.title }}</h2> is shown here.
I wrote in views.py
class CategoryView(ListView):
model = Category
template_name = 'category.html'
def get_queryset(self):
category_name = self.kwargs['category']
self.category = Category.objects.get(name=category_name)
queryset = super().get_queryset().filter(name=self.category)
return queryset
def get_context_data(self, *args, **kwargs):
context = super().get_context_data(*args, **kwargs)
context['categories'] = Category.objects.all()
return context
def category(self,pk):
queryset = self.base_queryset()
category = self.kwargs.get("category")
queryset = queryset.filter(category__name=category)
return queryset
in urls.py
urlpatterns = [
path('top/', views.top, name='top'),
path('category/<str:category>/',views.CategoryView.as_view(), name='category'),
]
in models.py
class Category(models.Model):
name = models.CharField(max_length=100)
created_at = models.DateTimeField(auto_now_add=True)
class Index(models.Model):
title = models.CharField(max_length=100)
text = models.TextField()
category = models.ForeignKey(Category, on_delete=models.CASCADE)
I want to show list of Index data that are by filtered Category in my db in category.html .For example, it is my ideal system ,when I put Python link in top.html,content.title which is related with Python is shown in category.html .But now no content.title is shown.What is wrong in my code?How should I fix this?
You shoud add filtered Index list to the context first:
def get_context_data(self, *args, **kwargs):
context = super().get_context_data(*args, **kwargs)
context['categories'] = Category.objects.all()
context['index_list'] = Index.objects.filter(category=self.category)
return context
Now index_list will be available inside template and you can do this:
<div>
{% for content in index_list %}
<h2>{{ content.title }}</h2>
SHOW DETAIL
{% endfor %}
</div>
Related
i need to paginate my category_detail page,but this view doesnt have list_objects.I have class for DetailView,where i need to add Paginator.Or maybe i can do it only in html template,and thats all?
class Category(models.Model):
name = models.CharField(_('Name'), max_length=200)
slug = models.SlugField(_('Slug'), unique=True)
PARAMS = Choices(
('following', 'following'),
('price_to', 'price_to'),
('price_from', 'price_from'),
)
def count_of_products(self):
return self.pk.count()
def __str__(self):
return self.slug
def get_absolute_url(self, **kwargs):
return reverse('products:category_detail', kwargs={'category_slug': self.slug})
this is my views.py
class CategoryListView(ActiveTabMixin, ListView):
model = Category
active_tab = 'category_list'
template_name = 'products/category_list.html'
def get_ordered_grade_info(self):
return []
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['grade_info'] = self.get_ordered_grade_info()
return context
class CategoryDetailView(DetailView):
model = Category
slug_url_kwarg = 'category_slug'
PARAM_FOLLOWING = 'following'
PARAM_PRICE_FROM = 'price_from'
PARAM_PRICE_TO = 'price_to'
slug_field = 'slug'
In my opinion,i need to do paginate def in CategoryDetailView, isnt it?
template
{% extends "base.html" %}
{% block content %}
<h2>{{ category.name }}</h2>
<div class="list-group">
{% for product in category.products.all %}
<a href="{{ product.get_absolute_url }}" class="list-group-item">
<h4 class="list-group-item-heading">{{ product.name }}</h4>
<p class="list-group-item-text">{{ product.price }}$</p>
<p class="list-group-item-text">Likes {{ product.likes.count }}</p>
<p>
<img class='img-article' src="{{product.image.url}}">
</p>
</a>
{% endfor %}
</div>
{% endblock content %}
how can I retrieve the lesson modules by its parent lesson strictly? e.g if I change to the next lesson where at the same contains a lessonmodule /lesson1/task1 this one shouldn't display since it doesn't belong to lesson2? how can I fix this by only retrieve slugs, content by the lesson attach to?
views
class LessonDetailView(LoginRequiredMixin, View):
login_url = "/account/login/"
def get(self, request, course_slug, lesson_slug, *args, **kwargs):
lesson = get_object_or_404(Lesson.objects.select_related('course'), slug=lesson_slug, course__slug=course_slug)
lessonmodule = get_object_or_404(LessonModule.objects.select_related('lesson'), slug='hello_world')
context = {
'object': lessonmodule,
'previous_lesson': lesson.get_previous_by_created_at,
'next_lesson': lesson.get_next_by_created_at,
}
return render(request, "courses/lesson_detail.html", context)
models
class Lesson(models.Model):
title = models.CharField(max_length=120)
slug = models.SlugField(max_length=25,unique=True)
course = models.ForeignKey(Course, on_delete=models.CASCADE)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('lesson-detail',
kwargs={
'course_slug': self.course.slug,
'lesson_slug': self.slug
})
class LessonModule(models.Model):
slug = models.SlugField(unique=True, blank=True, null=True)
content = models.TextField()
lesson = models.ForeignKey(Lesson, on_delete=models.CASCADE)
allowed_memberships = models.ManyToManyField(Membership)
created_at = models.DateTimeField(auto_now_add=True, blank=True)
updated_at = models.DateTimeField(auto_now=True, blank=True)
def __str__(self):
return self.slug
template
{% block content %}
<div class='container'>
<h1>Lesson Detail View</h1>
<div class='row'>
<div class='col-sm-6 col-md-6'>
{% if object is not None %}
<h3>{{ object.title }}</h3>
<p>{{ object.course.description }}</p>
{{object}}
{% if previous_lesson %}
Back
{% endif %}
{% if next_lesson %}
Next
{% endif %}
{% else %}
<h3>Upgrade membership</h3>
<p>To view this course you'll need to upgrade your membership</p>
<br>
<hr>
{% endif %}
</div>
</div>
</div>
{% endblock content %}
As I can see here, you can have multiple LessonModule for a single Lesson due to one-to-many relation between Lesson and LessonModule(ForeignKey relation basically). You can fetch all the LessonModules like this(using reverse query):
# view
def get(self, request, course_slug, lesson_slug, *args, **kwargs):
lesson = get_object_or_404(Lesson.objects.select_related('course').prefetch_related('lessonmodule_set'), slug=lesson_slug, course__slug=course_slug)
context = {
'object': lesson,
'previous_lesson': lesson.get_previous_by_created_at,
'next_lesson': lesson.get_next_by_created_at,
}
return render(request, "courses/lesson_detail.html", context)
# template
{% for lesson_module in object.lessonmodule_set.all %}
{{ lesson_module.slug }}
{% endfor %}
I am just sending the Lesson object to template, and using reverse query in template to get LessonModule objects.
How do I go about displaying the category name and short description from the category model onto the categories.html page? I ask this because I can't figure it out and I go the code from the internet so a little unclear how it works. So the code right now takes you to a page like example.com/cat-slug and then shows all the post under that category but how do I display the current category's name on that page (categories.html) as along with the category description too?
models.py:
class Category(models.Model):
name = models.CharField(max_length=100)
short_desc = models.CharField(max_length=160)
slug = models.SlugField()
parent = models.ForeignKey('self',blank=True, null=True ,related_name='children', on_delete=models.CASCADE)
class Meta:
unique_together = ('slug', 'parent',)
verbose_name_plural = "categories"
def __str__(self):
full_path = [self.name]
k = self.parent
while k is not None:
full_path.append(k.name)
k = k.parent
return ' -> '.join(full_path[::-1])
class Post(models.Model):
user = models.CharField(max_length=50, default=1)
title = models.CharField(max_length=120)
short_desc = models.CharField(max_length=50)
category = models.ForeignKey('Category', null=True, blank=True, on_delete=models.CASCADE)
tags = TaggableManager()
content = models.CharField(max_length=1000)
publish = models.DateField(auto_now=False, auto_now_add=False,)
slug = models.SlugField(unique=True)
def __str__(self):
return self.title
def get_cat_list(self):
k = self.category
breadcrumb = ["dummy"]
while k is not None:
breadcrumb.append(k.slug)
k = k.parent
for i in range(len(breadcrumb)-1):
breadcrumb[i] = '/'.join(breadcrumb[-1:i-1:-1])
return breadcrumb[-1:0:-1]
views.py:
def show_category(request, hierarchy=None):
category_slug = hierarchy.split('/')
category_queryset = list(Category.objects.all())
all_slugs = [ x.slug for x in category_queryset ]
parent = None
for slug in category_slug:
if slug in all_slugs:
parent = get_object_or_404(Category, slug=slug, parent=parent)
else:
post = get_object_or_404(Post, slug=slug)
post_related = post.tags.similar_objects()
comments = post.comments.filter(active=True)
instance = get_object_or_404(Post, slug=slug)
breadcrumbs_link = instance.get_cat_list()
category_name = [' '.join(i.split('/')[-1].split('-')) for i in breadcrumbs_link]
breadcrumbs = zip(breadcrumbs_link, category_name)
if request.method == 'POST':
comment_form = CommentForm(data=request.POST)
if comment_form.is_valid():
new_comment = comment_form.save(commit=False)
new_comment.post = post
new_comment.save()
else:
comment_form = CommentForm()
context = {
'post': post,
'post_related': post_related,
'comments': comments,
'comment_form': comment_form,
'instance': instance,
'breadcrumbs': breadcrumbs,
}
return render(request, "blog/post_detail.html", context)
context = {
'post_set': parent.post_set.all(),
'sub_categories': parent.children.all(),
}
return render(request, "blog/categories.html", context)
categories.html:
{% extends 'base.html' %}
{% block content %}
Viewing: {{ name }} Category
{{ short_desc }}
<div class="container">
<div class="row">
{% if post_set %}
{% for post in post_set %}
<div class="col-lg-8 col-md-10 mx-auto">
<div class="post-preview">
<a href="/blog/{{ post.slug }}">
<h2 class="post-title">
{{ post.title }}
</h2>
<h3 class="post-subtitle">
{{ post.short_desc }}
</h3>
</a>
<p class="post-meta">Posted by
{{ post.user }} at {{ post.publish }} in {{ post.category }}
<br />
{% for tag in post.tags.all %}
<font class="trigger blue lighten-4" size="3rem">{{ tag.name }}</font>
{% endfor %}
</p>
</div>
<hr>
</div>
{% endfor %}
{% else %}
<p>No post found in this category.</p>
{% endif %}
</div>
</div>
{% endblock %}
I think the implementation of the parent is not right, because in each iteration of loop, the parent will be updated.
for slug in category_slug:
if slug in all_slugs:
parent = get_object_or_404(Category, slug=slug, parent=parent) # <-- with each iteration, value of parent will be updated.
Rather than that, you can define the parent like this:
parent = Category.objects.filter(slug__in=category_slug, parent=None).first()
context = {
'category': parent, # send the category explicitly through the context
'post_set': parent.post_set.all(),
'sub_categories': parent.children.all(),
}
And update the template:
Viewing: {{ category.name }} Category
{{ category.short_desc }}
I'm trying to display all the django-taggit tags related to the given object when I'm querying.
I've tried adding this function within my search_result.html template like this but no tags are being displayed:
{% if page_obj.object_list %}
<ol class="row top20">
{% for result in page_obj.object_list %}
<div class="showcase col-sm-6 col-md-4">
<a href="{{ result.object.get_absolute_url }}">
<h3>{{result.object.title}}</h3>
<img src="{{ result.object.image }}" class="img-responsive">
</a>
<!-- I want to display them in the span below -->
<div class="text-center">
<span class="label label-info">{{ result.object.ptags.name }}</span>
</div>
</div>
{% endfor %}
</ol>
</div>
{% endif %}
My Models:
class Product(models.Model):
title = models.CharField(max_length=255, default='')
slug = models.SlugField(null=True, blank=True, unique=True, max_length=255, default='')
description = models.TextField(default='')
ptags = TaggableManager()
timestamp = models.DateTimeField(auto_now=True)
def _ptags(self):
return [t.name for t in self.ptags.all()]
def get_absolute_url(self):
return reverse('product',
kwargs={'slug': self.slug})
def __str__(self):
return self.title
My custom forms.py function:
from haystack.forms import FacetedSearchForm
class FacetedProductSearchForm(FacetedSearchForm):
def __init__(self, *args, **kwargs):
data = dict(kwargs.get("data", []))
self.ptag = data.get('ptags', [])
super(FacetedProductSearchForm, self).__init__(*args, **kwargs)
def search(self):
sqs = super(FacetedProductSearchForm, self).search()
if self.ptag:
query = None
for ptags in self.ptag:
if query:
query += u' OR '
else:
query = u''
query += u'"%s"' % sqs.query.clean(ptags)
sqs = sqs.narrow(u'ptags_exact:%s' % query)
return sqs
And I'm passing the forms into the views like this:
class FacetedSearchView(BaseFacetedSearchView):
form_class = FacetedProductSearchForm
facet_fields = ['ptags']
template_name = 'search_result.html'
paginate_by = 6
context_object_name = 'object_list'
How can I do this?
Can you try this instead
<span class="label label-info">{{ result.object.ptags.names }}</span>
You can loop over the ptags.names queryset to display individual tags, like this:
{% for tag in result.object.ptags.names %}
{{ tag }}
{% endfor %}
What I'm looking to do is make it to where I can search the database directly without having the entire database visible on search page. The search page should be empty. You do a search and it goes straight to the detail page of the db entry which matches your search criteria. If there is no match it shows "No matches found". How can I do this?
This is what I have so far. This prints/lists every entry in the database on the same page as my search box and when a search is done the list gets cut down to however many entries match the search criteria. Every db entry has a link you can click on which will take you to a detail page which pulls up that entry's info.
I'm using Django 2.0.
Manage.py
class PostManager(models.Manager):
def active(self, *args, **kwargs):
return super(PostManager, self).filter(draft=False).filter(publish__lte=timezone.now())
def upload_location(instance, filename):
return "%s/%s" %(instance.slug, filename)
class Remote(models.Model):
brand = models.CharField(max_length=20)
model = models.CharField(max_length=25)
type = models.CharField(max_length=50)
orig = models.TextField()
comp = models.TextField(blank=True)
image = models.ImageField(upload_to=upload_location,
null=True, blank=True, default=0,
timestamp = models.DateTimeField(auto_now=False, auto_now_add=True)
user = models.ForeignKey(settings.AUTH_USER_MODEL,on_delete=models.CASCADE, default=1)
slug = models.SlugField(unique=True)
objects = PostManager()
def __str__(self):
return self.model
def get_absolute_url(self):
return reverse("mainapp:detail", kwargs={"slug": self.slug})
def create_slug(instance, new_slug=None):
slug = slugify(instance.model) #slugify title
if new_slug is not None:
slug = new_slug
qs = Remote.objects.filter(slug=slug).order_by("-id")
exists = qs.exists()
if exists:
new_slug = "%s-%s" %(slug, qs.first().id)
return create_slug(instance, new_slug=new_slug)
return slug
def pre_save_post_receiver(sender, instance, *args, **kwargs):
if not instance.slug:
instance.slug = create_slug(instance)
pre_save.connect(pre_save_post_receiver, sender=Remote)
Views.py
def detail(request, slug=None):
instance = get_object_or_404(Remote, slug=slug)
share_string = quote_plus(instance.orig)
context={
"model": instance.model,
"instance": instance,
"share_string": share_string,
}
return render(request, 'mainapp/remote_detail.html', context)
def remote_list(request):
today = timezone.now().date()
queryset_posts = Remote.objects.all()
if request.user.is_staff or request_user_is_superuser:
queryset_posts = Remote.objects.all()
query = request.GET.get("q") # search stuff
if query:
queryset_posts = queryset_posts.filter(
Q(model__icontains=query)|
Q(orig__icontains=query)
).distinct() #.distinct() doesn't allow duplicates to show up
paginator = Paginator(queryset_posts,10) # Show 25 contacts per page
page_request_var = "pagina" #this changes "Page name in pagination
page = request.GET.get(page_request_var)
queryset = paginator.get_page(page)
context={
"object_list": queryset,
"title": "List",
"page_request_var": page_request_var,
"today": today,
}
return render(request, 'mainapp/remote_list.html', context)
HTML for Remote_list view
<form class='mb-2' method='GET' action=''>
<input type='text' name='q' placeholder='Search posts' value='{{ request.GET.q }}'/>
<input href='{{ obj.get_absolute_url }}' type='submit' value='Search'/>
</form>
{% for obj in object_list %}
{% if obj.image %}
<img class="card-img-top" src="{{ obj.image.url }}" alt="Image" style="max-width:100px;">
{% endif %}
<h5 class="card-title"><a href='{{ obj.get_absolute_url }}'>{{ obj.model }}</a></h5>
{% if obj.user.get_full_name %}
<p>Author: {{ obj.user.get_full_name }}</p>
{% endif %}
<p class="card-text">{{ obj.orig|truncatechars:120 }}</p>
View
{% endfor %}
HTML for Detail view
{% if instance.image %}
<img src='{{ instance.image.url }}' class='img-responsive' style='max-width:300px;' />
{% endif %}
<h3>{{ instance.brand}} {{ model }}</h3>
{% if instance.user.get_full_name %}
<p>Author: {{ instance.user.get_full_name }}</p>
{% endif %}
<h5>Originally Supplied With: </h5> {{ instance.orig }}
{% if instance.comp %}
<h5>Compatible With: </h5>{{ instance.comp }}
{% endif %}
you need to add some codes to your qs but now it's okey
you need to learn more about filtering query and passing them to your views if your models contains title field you can do {{ your_data.title }} in your template with your_data is the filtered passed query