I'm new in django.
I has a django application where stores products categorized by 'X' and 'Y'.
views.py
...
class CartListView(ListView):
template_name = 'checkout/list.html'
context_object_name = 'product_list'
def get_queryset(self):
return Product.objects.filter(category__slug='X') | Product.objects.filter(category__slug='Y')
def get_context_data(self, **kwargs):
context = super(CartListView, self).get_context_data(**kwargs)
context['minicurso'] = get_object_or_404(Category, slug='X')
context['pacotes'] = get_object_or_404(Category, slug='Y')
return context
...
In my views.py I filter this products by your categories slug.
The problem is, I'm trying to render the products in category 'X' on top the page and the products in category 'Y' down with a text between them. How I can do this?
list.html
{% for category in product_list %}
{{ category.name }}
{% endfor %}
<p>
Any text
</p>
{% for category in product_list %}
{{ category.name }}
{% endfor %}
First off, you should use IN operator over | when populating the filtered queryset:
def get_queryset(self):
return Product.objects.filter(category__slug__in=["X", "Y"])
Secondly, you can't filter queryset by any field in the template unless you write a custom template tag which does that. However, it defeats the purpose of separation of presentation code from data logic. Filtering models is data logic, and outputting HTML is presentation. Thus, you need to override get_context_data and pass each queryset into the context:
def get_context_data(self, **kwargs):
context = super(CartListView, self).get_context_data(**kwargs)
context['minicurso'] = get_object_or_404(Category, slug='X')
context['pacotes'] = get_object_or_404(Category, slug='Y')
context["x_product_list"] = self.get_queryset().filter(category=context['minicurso'])
context["y_product_list"] = self.get_queryset().filter(category=context['pacotes'])
return context
Then you can use them in the template:
{% for category in x_product_list %}
{{ category.name }}
{% endfor %}
...
{% for category in y_product_list %}
{{ category.name }}
{% endfor %}
Related
I have two views in my views.py as following:
def table1(request):
template_name = 'tables.html'
queryset = one.objects.all()
context = {
"table1_list": queryset
}
return render(request, template_name, context)
def table2(request):
template_name = 'tables.html'
queryset = two.objects.all()
context = {
"table2_list": queryset
}
return render(request, template_name, context)
and the following models in models.py:
class one(models.Model):
title = models.CharField(max_length=100)
explanation = models.CharField(max_length=1000, blank=True, null=True)
class two(models.Model):
title = models.CharField(max_length=100)
explanation = models.CharField(max_length=1000, blank=True, null=True)
In my tables.html I want to show the contents from both of these models. I have:
<p>Table one content</p>
<ul>
{% for obj in table1_list %}
{{ obj.title }}, {{ obj.explanation }}
{% endfor %}
</ul>
<p>Table two content</p>
<ul>
{% for obj in table1_list %}
{{ obj.title }}, {{ obj.explanation }}
{% endfor %}
</ul>
But since I can just return one view from views.py in urls.py, I cannot return both of the tables. In urls.py I have to write either of the following:
urlpatterns = [
url(r'^$', home),
url(r'^tables/$', table1),
]
or
urlpatterns = [
url(r'^$', home),
url(r'^tables/$', table2),
]
I tried adding both of the tables from the query in views.py as:
def table1(request):
template_name = 'tables.html'
queryset_one = one.objects.all()
queryset_two = two.objects.all()
context = {
"table1_list": [queryset_one, queryset_two]
}
return render(request, template_name, context)
but just the latter table's content is shown.
I would appreciate any help.
You need to do like this to show the two models in your view.
def table1(request):
template_name = 'tables.html'
queryset_one = one.objects.all()
queryset_two = two.objects.all()
context = {
"table1_list": queryset_one,
"table2_list": queryset_two
}
return render(request, template_name, context)
then:
<p>Table one content</p>
<ul>
{% for obj in table1_list %}
{{ obj.title }}, {{ obj.explanation }}
{% endfor %}
</ul>
<p>Table two content</p>
<ul>
{% for obj in table2_list %}
{{ obj.title }}, {{ obj.explanation }}
{% endfor %}
</ul>
Do not forget to import the two models in your views.py
It may be because both classes in yout model have the same fields and django only takes the information of the latter. The way it could work is to pass both queries with different keys in a dictionary and modify your template accordigly.
So your views.py would look like:
def table1(request):
template_name = 'tables.html'
queryset_one = one.objects.all()
queryset_two = two.objects.all()
context = {
"t1": queryset_one, "t2":queryset_two
}
return render(request, template_name, context)
And your template tables.html woud look like
<p>Table one content</p>
<ul>
{% for obj in t1 %}
{{ obj.title }}, {{ obj.explanation }}
{% endfor %}
</ul>
<p>Table two content</p>
<ul>
{% for obj in t2 %}
{{ obj.title }}, {{ obj.explanation }}
{% endfor %}
</ul>
I have a category dropdown list in a template. I don't want to hard code it and write separate list views for each category. So is there a way to pass a value from <a href=""> to a view? I guess self.request.GET.get('category search') never works because there is no <form method="get"> tag. Therefor it always returns None due to the return queryset.none() statement.
home.html:
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
{% if all_categories %}
{% for category in all_categories %}
<a name="category search" href="{% url 'book:category_search' category.id %}"> {{ category }} </a>
{% endfor %}
{% endif %}
</div>
book.urls.py:
urlpatterns = [
.........
path('categories/<int:pk>', views.CategorySearchView.as_view(), name='category_search'),
]
book.views.py:
class CategorySearchView(generic.ListView):
template_name = 'book/search.html'
model = Book
context_object_name = 'book_list'
paginate_by = 100
def get_queryset(self):
queryset = super().get_queryset()
search = self.request.GET.get('category search')
if search:
queryset = Book.objects.filter(categories__id=search)
return queryset
else:
return queryset.none()
Since your URL has <int:pk>,
path('categories/<int:pk>', views.CategorySearchView.as_view(), name='category_search'),
you can access self.kwargs['pk'] in the view:
def get_queryset(self):
queryset = super().get_queryset()
search = self.kwargs.get('pk')
if search:
queryset = Book.objects.filter(categories__id=search)
return queryset
else:
return queryset.none()
As an aside, you would use self.request.GET if pk was in the querystring, e.g. /categories/?pk=1. When you submit a form with method=GET, the form fields will be included in the querystring. But you can also have a link with a querystring, e.g. my link.
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>
I have a profile model that is displaying various items.
One of those is the country attached to the profile.
Here is what happen in the view:
class ProfilePartnerListView(FormMixin, BaseProfilePartnerView, ListView):
model = ProfilePartner
context_object_name = 'profile_list'
view_url_name = 'djangocms_partner_profile:profile-list'
def get(self, request, *args, **kwargs):
context = {}
self.object_list = self.get_queryset().order_by('-date_created')
context.update(self.get_context_data(**kwargs))
context[self.context_object_name] = context['object_list']
country_for_articles = Country.objects.exclude(regions_partner_profile=None).order_by('name')
industries_qs = ProfilePartnerIndustry.objects.active_translations(
get_language()).order_by('translations__name')
budget_qs = ProfilePartner.objects.values_list('budget',
flat=True).distinct()
context['load_more_url'] = self.get_load_more_url(request, context)
context['regions_list'] = country_for_articles
context['industry_list'] = industries_qs
context['budget_list'] = budget_qs
return self.render_to_response(context)
I know, for example 'regions_list', how to return only 4 elements from it.
But the thing is, my main object 'profile_list' that I use in the template for the rendering, is displaying all the country of the item when I do:
{% for profile in profile_list %}
{% for country in profile.regions.all %}
<div class="col-xs-12">{{ country }}</div>
{% endfor %}
{% endfor %}
And some of the profiles got 5 or 6 country. I want to only display the first 4.
Is there a way of doing it?
Many thanks!
ps: region_list, industry_list and budget_list are use for categories, it has nothing to do with what I want here.
You could use slice filter for this:
{% for profile in profile_list %}
{% for country in profile.regions.all|slice:":4" %}
<div class="col-xs-12">{{ country }}</div>
{% endfor %}
{% endfor %}
I have 2 models:
class Category(models.Model):
title = models.CharField(max_length=250)
### other fields
class Album(models.Model):
category = models.ForeignKey(Category)
subject = models.CharField(max_length=200)
### other fields...
.
I just wrote a view for filtering albums by specefic category, also I want them all in home.html template:
#views.py
def commercial(request):
commercial_subjects = Album.objects.filter(category__title__contains="commercial" )
return render(request, 'gallery/index.html', {'commercial_subjects': commercial_subjects})
And it works fine for just commercial category. It seems just like hardcoding if I want to write multiple views for each category like this one. What I need is a view or filtering process which shows all categories and their related album.subject automaticly. So the final result must be like this:
Personal
ALBUM 1
ALBUM 2
Commercial
ALBUM 4
ALBUM5
How can I do that?
Its easy. First of all give a related_name to the foreign key:
class Album(models.Model):
category = models.ForeignKey(Category, related_name='albums')
From view pass all categories:
def myView(request):
categories = Category.objects.all()
return render(request, 'gallery/index.html', {'categories': categories})
Then in template:
<ul>
{% for category in categories %}
<li>{{ category.title }}</li>
{% with category.albums.all as albums %}
{% if albums %}
<ul>
{% for album in albums %}
<li>{{ album.subject }}</li>
{% endfor %}
<ul>
{% endif %}
{% endwith %}
{% endfor %}
</ul>
#views.py
def commercial(request):
commercial_subjects = Album.objects.filter(category__title="commercial")