Reputation: 738
I'm try to get all data from relationship manytomany, this is my model
class Product(models.Model):
name = models.CharField(max_length=100)
image = models.FileField(upload_to='products/', null=True)
price = models.FloatField(default=0)
stock = models.CharField(max_length=15)
categories = models.ManyToManyField(Categories)
def __str__(self):
return self.name
class Categories(models.Model):
name = models.CharField(max_length=100)
def __str__(self):
return self.name
for get the data from products try this:
class Products(ListView):
model = Product
template_name = "products.html"
on the template return similar to this:
_______________________________
# | name | price | Categories |
________________________________
1 | Pepsi | 1.25 | |
2 | Choco.| 2.50 | |
for generate this table i use a cycle for:
{% for product in object_list %}
<tr>
<td>{{ forloop.counter }}</td>
<td>{{ product.name }}</td>
<td>{{ product.price }}</td>
<td>{{ product.categories }}</td>
{% endfor %}
in this case return empty the categories selected on the product..please any suggest.. thanks !!
Upvotes: 1
Views: 90
Reputation: 15104
Notice that the categories
attribute of Product
is a many to many relation thus it resolves to another query with multiple objects. It is another queryset just line your object_list
, thus you need to explicitly tell the template how to print that.
Here's a sample solution:
{% for product in object_list %}
<tr>
<td>{{ forloop.counter }}</td>
<td>{{ product.name }}</td>
<td>{{ product.price }}</td>
<td>
{% for category in product.categories.all %}
{{ category }}
{% endfor %}
</td>
{% endfor %}
Or you could use the django join template tag (https://docs.djangoproject.com/en/2.1/ref/templates/builtins/#join):
{% for product in object_list %}
<tr>
<td>{{ forloop.counter }}</td>
<td>{{ product.name }}</td>
<td>{{ product.price }}</td>
<td>{{ product.categories.all|join:", " }}</td>
{% endfor %}
Some more quick comments to help you since you are starting Django:
class Categories
is not a very good name for your model. I propose naming it class Category
since each Category
instance will correlate to a single category.class Products
is a bad name for a view. I propose naming it class ProductListView
so you'll know that it is a ListView of your products. Also keep a similar naming scheme to all your views.FloatField
to save prices (monetary values) is always problematic. You'll have strange values when you try to do aggregates on that column (i.e adding or taking averages). This is because of how float numbers work (i.e some values cannot be represented exactly by a float but you'll get a very close approximation instead like instead of 1.3 you'll have 1.2999999999999 with the float). Use a DecimalField
instead to properly save monetary values.context_object_name
attribute to your ListView
so that you could use it instead of object_list
. Thus, if you'd defined your ProductListView
like this:class ProductListView(ListView): model = Product template_name = "products.html" context_object_name = 'products'
you'd be able to do {% for product in products %} ...
in your template.
template_name
attribute of your ListView since django generates one from the class and package name. Take a look at this portion of the docs: https://docs.djangoproject.com/en/2.1/topics/class-based-views/generic-display/#generic-views-of-objects and especially this paragraph: https://docs.djangoproject.com/en/2.1/topics/class-based-views/generic-display/#generic-views-of-objectsWe could explicitly tell the view which template to use by adding a template_name attribute to the view, but in the absence of an explicit template Django will infer one from the object’s name. In this case, the inferred template will be "books/publisher_list.html" – the “books” part comes from the name of the app that defines the model, while the “publisher” bit is just the lowercased version of the model’s name.
Use template_name
only if you intent to add a 2nd list view for a class to make it explicit that this is intentional.
Upvotes: 2