Same Dynamic Data coming in every column of webpage - python

I am doing CRUD using serializers, foreignkeys and I am trying to dynamically list the categories, sub_categories. For example category = 9-6 wear and its subcategories are kurta, skirtset, dress, kurtaset. I want these subcategories below only 9-6wear
The issue is that other subcategories are also mentioning kurta,skirtset,dress and kurtaset which I dont want as shown below
I have tried for hours but without much success
below are my models
class Products(models.Model):
categories = models.ForeignKey(Categories,on_delete=models.CASCADE)
sub_categories = models.ForeignKey(SUBCategories,on_delete=models.CASCADE)
color = models.ForeignKey(Colors,on_delete=models.CASCADE)
size = models.ForeignKey(Size,on_delete=models.CASCADE)
image = models.ImageField(upload_to = 'media/',width_field=None,height_field=None,null=True)
title = models.CharField(max_length=70)
price = models.CharField(max_length=10)
sku_number = models.CharField(max_length=10)
product_details = models.CharField(max_length=1000)
quantity = models.IntegerField(default=0)
isactive = models.BooleanField(default=True)
class Category(models.Model):
#made changes to category_name for null and blank
category_name = models.CharField(max_length=30)
category_description = models.CharField(max_length=30)
isactive = models.BooleanField(default=True)
class SUBCategories(models.Model):
category_name = models.ForeignKey(Categories, on_delete=models.CASCADE)
sub_categories_name = models.CharField(max_length=30)
sub_categories_description = models.CharField(max_length=30)
isactive = models.BooleanField(default=True)
below are the serializer
class CategoriesSerializer(serializers.ModelSerializer):
class Meta:
model = Categories
fields = "__all__"
extra_kwargs = {'category_name': {'required': False}}
class POLLSerializer(serializers.ModelSerializer):
class Meta:
model = Products
fields = "__all__"
below is my shoppingpage function
def shoppingpage(request):
cat = Categories.objects.filter(isactive=True)
category = CategoriesSerializer(cat,many=True)
subcat = SUBCategories.objects.filter(isactive=True)
subcategory = SUBCategoriesSerializer(subcat,many=True)
return render(request,'polls/shoppingpage.html',{'category':category.data,'subcategory':subcategory.data})
below is my shoppingpage.html for loop part
{% for result in category %}
<div class="col-md-3">
<div class="lynessa-listitem style-01">
<div class="listitem-inner">
<a href="/9-6wear" target="_self">
<h4 class="title">{{result.category_name}}</h4>
</a>
{% for ans in result.subcategory_set.all %}
<ul class="listitem-list">
<li>
{{ans.sub_categories_name}}
</li>
</ul>
{% endfor %}
</div>
</div>
</div>
{% endfor %}
help is greatly appreciated, thanks!

It's because you are just looping through all the subcategories for all of the categories in your template:
{% for result in category %}
...
{% for ans in subcategory %}
You should change the second loop so that it only refers to related subcategories:
{% for ans in result.subcategory_set.all %}
Edit
Serializers aren't necessary in this example, nor is the subcategory queryset. The view can look like this:
def shoppingpage(request):
categories = Categories.objects.filter(isactive=True)
context = {'categories': categories}
return render(request,'polls/shoppingpage.html', context)
Edit
A lot of the errors came down to context/variable misalignment:
# models.py
model Category
...
model Subcategory
...
# views.py
context = {'categories': Category.objects.all()}
# template
{% for category in categories %}
{% for subcategory in category.subcategory_set.all %}
...

Related

When selecting category, display both elements of category and elements of all subcategories

I am new to Django and Python. I am practicing creating an online store. I'm facing this problem: When choosing a category, it would be logical to also display products from all its subcategories.
Unfortunately, Google did not help. I think that you need to somehow correctly filter the product in the views, but how? My skills are not enough to understand. I'm using Django-mptt for the category tree (fewer database queries).
For example, there are such categories:
Clothing
Jackets
Hats
If the product is in the "Jackets" category and we go into this category, everything is fine, but if we go to "Clothes" then it will be empty, but you need to have all the products from both the "Jackets" category and from the "Hats".
Now the sorting of products is obtained only by the category that was selected when adding the product.
models.py
class Category(MPTTModel):
name = models.CharField(max_length=200, db_index=True)
slug = models.SlugField(max_length=200, db_index=True, unique=True)
parent = TreeForeignKey('self', on_delete=models.CASCADE, null=True, blank=True, related_name='children')
class MPTTMeta:
order_insertion_by = ['name']
class Meta:
ordering = ('name',)
verbose_name = 'Категория'
verbose_name_plural = 'Категории'
def get_absolute_url(self):
return reverse('shop:product_list_by_category', args=[self.slug])
def __str__(self):
return self.name
views.py
def product_list(request, category_slug=None):
category = None
categories = Category.objects.all()
products = Product.objects.filter(available=True).order_by('-created')
if category_slug:
category = get_object_or_404(Category, slug=category_slug)
products = products.filter(category=category)
return render(request,
'shop/shop.html',
{'category': category,
'categories': categories,
'products': products})
html
<div class="category_conteiner">
{% recursetree categories %}
<div class="sub_menu_category">
{{ node.name }}
{% if not node.is_leaf_node %}
<div class="subcat_content">
<div class="subcat_column">
{{ children }}
</div>
</div>
{% endif %}
</div>
{% endrecursetree %}
You can do it in an extra step. You need to get child categories and then filter products by them.
Example code:
category = Category.objects.get(category_slug=category_slug)
sub_categories = category.get_descendants(include_self=True)
Product.objects.filter(category__in=sub_categories)
And here is the full code for your case.
def product_list(request, category_slug=None):
category = None
categories = Category.objects.all()
products = Product.objects.filter(available=True).order_by('-created')
if category_slug:
category = get_object_or_404(Category, slug=category_slug)
sub_categories = category.get_descendants(include_self=True)
products = products.filter(category__in=sub_categories)
return render(request,
'shop/shop.html',
{'category': category,
'categories': categories,
'products': products})

Group and display products by category and brand in Django

I'm new to Django and I'm currently having troubles creating a very simple list of products, grouped by categories and brands.
Here's the expected result:
- Category 1
+ Brand A
* Product 1
* Product 2
+ Brand B
* Product 3
* Product 4
- Category 2
+ Brand A
* Product 5
* Product 6
+ Brand C
* Product 7
* Product 8
Here's my models.py
from django.db import models
class Brand(models.Model):
brand = models.CharField(max_length=200)
country = models.CharField(max_length=200, blank=True, null=True)
email = models.EmailField(max_length=200, blank=True, null=True)
url = models.URLField(max_length=300)
def __str__(self):
return self.brand
class Category(models.Model):
category_id = models.CharField(max_length=200, default="cat")
name = models.CharField(max_length=200)
def __str__(self):
return self.category_id
class Product(models.Model):
category = models.ForeignKey(Category, on_delete=models.CASCADE)
name = models.CharField(max_length=200)
brand = models.ForeignKey(Brand, on_delete=models.CASCADE)
desc = models.CharField(max_length=200, blank=True, null=True)
img = models.CharField(max_length=200)
url = models.URLField(max_length=300, blank=True, null=True)
def __str__(self):
return f"{self.brand} - {self.name} - {self.category}"
My views.py
def product_list(request):
products = Product.objects.all()
categories = Category.objects.all()
brands = Brand.objects.all()
context = {
'products': products,
'categories': categories,
'brands': brands
}
return render(request, "product/product-list.html", context)
And here's the closest I could get to achieve the expected result in my product-list.html
<ul>
{% for category in categories %}
<li>{{ category }}</li>
<ul>
{% for brand in brands %}
<li> {{ brand }}</li>
<ul>
{% for product in products %}
{% if product.category == category and product.brand == brand %}
<li> {{ product }}</li>
{% endif %}
{% endfor %}
</ul>
{% endfor %}
</ul>
{% endfor %}
</ul>
One of the problems is that even if a brand has no product associated to that category, it is still shown and that lead me to think that this is not the best way to do it for sure.
I'd really appreciate if you could point me to the right direction!
Thanks
Stefano
You have a many-to-one relationship from Product to Brand, you need to add another one for Brand to Category. Afterwards you can use the related objects reference. Please check this documentation: https://docs.djangoproject.com/en/3.2/ref/models/relations/

How to properly use get_context_data with ListView to fetch related instances in Django

I am trying to use ListView and ContextMixin to create a view but I'm not sure if this is a right way to do it. The goal is to get all the fields in CourseImplementation and the teacherid that connects to it in TeacherCourseImplementation.
The problem is I don't see the part implement.teacherid when the template is opened on the browser. I don't know how should I do it if I want to get the teacher ID.
class ImplementView(generic.ListView):
template_name = 'schedule/implement.html'
context_object_name = 'all_implements'
def get_queryset(self):
return CourseImplementation.objects.all()
def get_context_data(self, **kwargs):
context = super(ImplementView, self).get_context_data(**kwargs)
context['teacherid'] = TeacherCourseImplementation.objects.all()
return context
This is my models.py
class CourseImplementation(models.Model):
courseid = models.ForeignKey(Course, on_delete=models.CASCADE, db_column='courseid', )
roomid = models.ForeignKey('Room', models.DO_NOTHING, db_column='roomid', blank=True, null=True)
note = models.CharField(max_length=10, blank=True, null=True)
class Meta:
managed = False
db_table = 'course_implementation'
def __str__(self):
return self.pk + ' - ' + self.courseid
class TeacherCourseImplementation(models.Model):
teacherid = models.ForeignKey(Teacher, on_delete=models.CASCADE, db_column='teacherid', primary_key=True)
course_impleid = models.ForeignKey(CourseImplementation, on_delete=models.CASCADE, db_column='course_impleid')
p1 = models.IntegerField(blank=True, null=True)
p2 = models.IntegerField(blank=True, null=True)
p3 = models.IntegerField(blank=True, null=True)
p4 = models.IntegerField(blank=True, null=True)
p5 = models.IntegerField(blank=True, null=True)
class Meta:
managed = False
db_table = 'teacher_course_implementation'
unique_together = (('teacherid', 'course_impleid'),)
def __str__(self):
return self.pk + ' - ' + self.teacherid
This is my template:
<ul>
{% for implement in all_implements %}
<div class="col-sm-5 col-lg-5">
<div class="thumbnail">
<p>{{ implement.teacherid }} - {{ implement.courseid }}</p>
</div>
</div>
{% endfor %}
</ul>
Can anyone help me on this. Thank you.
You can access the related TeacherCourseImplementation items for a TeacherCourseImplementation item implement with implement.teachercourseimplementation_set.all() (don't use parentheses in the template):
{% for implement in all_implements %}
<div class="col-sm-5 col-lg-5">
<div class="thumbnail">
<p>{{ implement.courseid }}</p>
{% for teacher_course_implementation in implement. teachercourseimplementation_set.all %}
{{ teacher_course_implementation.teacherid }}
...
{% endfor %}
</div>
</div>
{% endfor %}
See the docs on following relationships backwards for more info.
This will generate an extra query for every item in the queryset. You can avoid this by using prefetch_related.
def get_queryset(self):
return CourseImplementation.objects.all().prefetch_related('teachercourseimplementation_set')
Since you are accessing all the TeacherCourseImplementation instances via the CourseImplementation instances, you don't need to override get_context_data.

How to loop within a loop in django while passing multiple context

I having trouble trying to access the foreign key element from my template. I am trying to pass multiple contexts using class view like this:
class HomeView(ListView):
template_name = "homepage/home.html"
queryset = Author.objects.all()
def get_context_data(self, **kwargs):
context = super(HomeView, self).get_context_data(**kwargs)
context['author_links'] = Author_link.objects.all()
context['categories'] = Category.objects.all()
context['extra_links'] = Extra_link.objects.all()
context['poems'] = Poem.objects.all()
return context
my models.py file:
class Author(models.Model):
name = models.CharField(max_length=30)
def __str__(self):
return self.name
class Author_link(models.Model):
url_text = models.CharField(max_length=100)
url = models.CharField(max_length=200)
author = models.ForeignKey(Author)
def __str__(self):
return self.url_text
class Category(models.Model):
name = models.CharField(max_length=100)
description = models.TextField()
class Meta:
verbose_name_plural = 'categories'
def __str__(self):
return self.name
class Extra_link(models.Model):
url_text = models.CharField(max_length=100)
url = models.CharField(max_length=200)
category = models.ForeignKey(Category)
def __str__(self):
return self.url_text
however when I am trying to loop through the context I can't seem to access the foreign key of each item:
{% for author in object_list %}
<li class = "collection-item">
<ul class="collapsible" data-collapsible="accordion">
<li>
<div class="collapsible-header">{{author.name}}</div>
<div class="collapsible-body">
{% for item in author.item_set.all %}
<p>{{item.url}}</p>
{% endfor %}
</div>
</li>
</ul>
</li>
{% endfor %}
what I am trying to do is loop through the authors and at the same time under each author loop through the urls that are associated with each author.
where you have
{% for item in author.item_set.all %}
<p>{{item.url}}</p>
{% endfor %}
you should have something like
{% for item in author.author_link_set.all %}
<p>{{item.url}}</p>
{% endfor %}
This manager (author.author_link_set) is added to each author because there is a foreign key from Author_link to Author.
side note: the convention for class names in python is Pascal Case, e.g., AuthorLink not Author_link. I mention this because I'm not 100% sure if I have correctly guessed the name of the reverse relation on author (it might be author.authorlink_set, I've never seen an underscore in a model name - django may do something special in that case)

Can I use filter() in django template?

What I'd like to do is using filter() in django template like belows:
models.py
from django.db import models
From Django. utils import Timezone
class Category(models.Model):
url = models.CharField(max_length=200)
site_name = models.CharField(max_length=50)
board_name = models.CharField(max_length=50)
class Post(models.Model):
title = models.CharField(max_length=200)
content = models.TextField(blank=True)
category = models.ForeignKey(Category)
created_date = models.DateField(blank=True, null=True)
crawl_date = models.DateTimeField()
num_of_comments = models.PositiveSmallIntegerField(default=0, blank=True, null=True)
notice = models.BooleanField(default=False)
views.py
def post_list(request, site_name=None, page=1):
categories = Category.objects.filter(site_name=site_name.upper()).order_by('board_name')
return render(request, 'SNU/post_list.html', {'site_name':site_name.upper(), 'categories':categories})
post_list.html
{% for category in categories %}
<p> {{category}} </p>
{% for post in category.post_set.filter(notice=True) %}
<li>{{ post.title }}</li>
{% endfor %}
{% endfor %}
In post_list.html, {% for post in category.post_set.filter(notice=True) %} occurs error. Only category.post_set.all is the one that I can use in template?
You can do it on view level by
def post_list(request, site_name=None, page=1):
categories = Category.objects.filter(site_name=site_name.upper(),
notice=True).order_by('board_name')
return render(request, 'SNU/post_list.html',{'site_name':site_name.upper(),
'categories':categories})
If for some reason you need all categories, not just those having notice = True,
add one more query without notice=True in filter and pass it in the dictionary.
Alternatively, you can create custom tag and provide filter - see https://docs.djangoproject.com/en/1.9/howto/custom-template-tags/

Categories