Paginate detailview django - python

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 %}

Related

Django add to wishlist

I have to do wishlist, I have done wishlist page, model and html.bBut when I click on the button bellow my post, I'm redirected to wishlist page and post didnt saved in my wishlist.So thats my code:
models.py
class Wishlist(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL,
on_delete=models.CASCADE)
wished_item = models.ForeignKey(Posts, on_delete=models.CASCADE)
def __str__(self):
return self.wished_item.title
class Posts(models.Model):
TYPE = Choices(
('private', _('private')),
('business', _('business')),
)
STATUS = Choices(
('active', _('active')),
('deactivated', _('deactivated'))
)
owner = models.ForeignKey(settings.AUTH_USER_MODEL, blank=True, null=True, related_name='posts',
on_delete=models.CASCADE, verbose_name='owner')
phone_number = PhoneNumberField(verbose_name=_('Phone_number'), null=False, blank=False, unique=True)
title = models.CharField(verbose_name=_('Title'), max_length=100)
text = RichTextField(verbose_name=_('Text'))
image = models.ImageField(upload_to='images/%Y/%m/%d/', null=True, blank=True, validators=[file_size])
price = models.DecimalField(verbose_name=_('Price'), decimal_places=2, max_digits=9)
status = models.CharField(choices=STATUS, max_length=50)
created = models.DateTimeField(auto_now=True)
type = models.CharField(choices=TYPE, max_length=50)
def __str__(self):
return self.title
views.py
class WishListView(generic.View):
def get(self, *args, **kwargs):
wish_items = Wishlist.objects.filter(user=self.request.user)
context = {
'wish_items': wish_items
}
return render(self.request, 'wishlist/wishlist.html', context=context)
def addToWishList(request):
if request.method == 'POST':
post_var_id = request.POST.get('object-id')
post_var = Posts.objects.get(id=post_var_id)
print(post_var)
try:
wish_item = Wishlist.objects.get(user=request.user, post=post_var)
if wish_item:
wish_item.save()
except:
Wishlist.objects.create(user=request.user, post=post_var)
finally:
return HttpResponseRedirect(reverse('wishlist'))
wishlist.html
{% extends 'posts/base.html' %}
{% load thumbnail %}
{% block content %}
<div>
{% for item in wish_items %}
{% if item.wished_item.image1 %}
<img src="{{item.wished_item.image.url}}" alt="">
{% endif %}
</div>
<div>
<li>{{item.wished_item.title}}</li>
<li>{{item.wished_item.text}}</li>
<li>{{item.wished_item.price}}</li>
<li>{{item.wished_item.phone_number}}</li>
{% if item.wished_item.image %}
<img src="{% thumbnail item.wished_item.image 200x200 crop %}" alt="" />
<p></p>
{% endif %}
</div>
{% endfor %}
{% endblock %}
urls.py
urlpatterns = [
path("wishlist/", WishListView.as_view(), name='wishlist'),
path("add-to-wishlist", addToWishList, name='add-to-wishlist'),
]
and all posts template with add to wishlist button.
<ul>
{% for object in object_list %}
<li>Owner: {{ object.owner }}</li>
<li>Phone: {{ object.phone_number }}</li>
<li>Title: {{ object.title }}</li>
<li>Text: {{ object.text }}</li>
<li>Type: {{ object.type }}</li>
<li>Price: {{ object.price }}</li>
<li>Date: {{ object.created }}</li>
<p>
{% if object.image %}
<img src="{% thumbnail object.image 200x200 crop %}" alt="" />
{% endif %}
</p>
<form action="{% url 'add-to-wishlist' %}" method="POST">
{%csrf_token%}
<input type="hidden" name="object-id" value="{{object.id}}">
<input type="submit" value="Add to Wishlist">
</form>
<hr/>
Probably problem with posts Id, but I'm not sure in that.
You can use get_or_create instead of the if else statement for if exist or not. And use get_object_or_404 to make code more clear.
from django.shortcuts import get_object_or_404
def addToWishList(request):
if request.method == 'POST':
post_obj = get_object_or_404(Post, pk=request.POST.get('object-id'))
Wishlist.objects.get_or_create(user=request.user, post=post_obj)
return HttpResponseRedirect(reverse('wishlist'))
In your views.py try to replace these lines:
try:
wish_item = Wishlist.objects.get(user=request.user, post=post_var)
if wish_item:
wish_item.save()
except:
Wishlist.objects.create(user=request.user, post=post_var)
with
wish_item, was_created = Wishlist.objects.get_or_create(user=request.user, post=post_var)
# for debugging
if was_created:
print(f"{wish_item} was created")
else:
print(f"{wish_item} already exists")
what is the output?
The code looks OK for me. You might add a trailing / in your urls.py after the path("add-to-wishlist/" ... but I can't spot anything wrong in the first place.

how can I build a query that retrieve lesson modules strictly that matches to the lesson?

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.

Displaying all Django-taggit tags for each given object

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 %}

How do I search a database and print results?

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

object is not shown in CategoryView

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>

Categories

Resources