В Django я пытаюсь вывести список объектов из разных моделей в детальном представлении, основанном на классах.
У меня есть две модели Vendors и Products. У Products есть внешний ключ vendors. Я пытаюсь сделать так: когда вы переходите к детальному представлению поставщика, он показывает информацию о модели поставщика, а затем список товаров этого поставщика.
В настоящее время я только тестирую поток и знакомлюсь с django, поэтому многое в этом коде очень общее, и я знаю, что мне нужно его очистить.
Вот мои модели
class Vendor(models.Model):
name = models.CharField(max_length=126, unique=True, blank=True, null=True)
contact_number = models.CharField(max_length=126, blank=True, null=True)
address = models.CharField(max_length=126, blank=True, null=True)
email = models.EmailField(max_length=126, blank=True, null=True)
is_active = models.BooleanField(default=True)
def __str__(self):
return self.name
def productFilepath(instance, filename):
year = datetime.now().strftime("%Y/")
return os.path.join(instance.vendors.name, year, filename)
class Product(models.Model):
vendors = models.ForeignKey(Vendor, on_delete=models.CASCADE)
collection = models.CharField(max_length=126, unique=True, blank=True, null=True)
product = models.CharField(max_length=126, blank=True, null=True)
size = models.CharField(max_length=126, blank=True, null=True)
vendor_price = models.DecimalField(max_digits=7, decimal_places=2, blank=True, null=True)
retail_price = models.DecimalField(max_digits=7, decimal_places=2, blank=True, null=True)
sku = models.CharField(max_length=126, unique=True, blank=True, null=True)
year = models.PositiveSmallIntegerField(blank=True, null=True)
quarters_in_year = {
'q1': 'Q1',
'q2': 'Q2',
'q3': 'Q3',
'q4': 'Q4',
}
quarter = models.CharField(max_length=2, choices=quarters_in_year.items(), blank=True, null=True)
image = models.FileField(upload_to=productFilepath, blank=True, null=True)
вот мои взгляды
class VendorDetailView(DetailView):
model = Vendor
template_name = 'deliveries/vendor_detail.html'
class Productlist(ListView):
model = Product
template_name = 'deliveries/vendor_detail.html'
def get(self, request, *args, **kwargs):
return super().get(request, *args, **kwargs)
URL
path('vendordetail/<int:pk>/', views.VendorDetailView.as_view(), name='vendordetail'),
HTML
{% extends "base.html" %}
{% block style_block %}
<style>
#title {
padding: 20px;
}
.add-button {
background-color: #04AA6D;
border: none;
color: white;
padding: 15px 32px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
margin: 4px 2px;
cursor: pointer;
float: right;
}
</style>
{% endblock %}
{% block body_block %}
<h1 id="title">{{ vendor.name }}</h1>
<a href="{% url "deliveries:addproduct" %}"><button class="button add-button" type="button">Add Product</button></a>
<ul>
<li>{{ vendor.name }}</li>
<li>{{ vendor.contact_number }}</li>
<li>{{ vendor.email }}</li>
<li>{{ vendor.address }}</li>
</ul>
<a href="{% url "deliveries:uploadproduct" %}"><button class="button add-button" type="button">Upload</button></a>
<div>
<h1>Products</h1>
{# <form >#}
{# {% csrf_token %}#}
{# {{ form.as_p }}#}
{# <input type="submit" value="submit">#}
{#</form>#}
<table style="width:100%">
<tr>
<th>SKU</th>
<th>Collection</th>
<th>Product Name</th>
<th>Size</th>
<th>Vendor Price</th>
<th>Retail Price</th>
</tr>
{% for product in products %}
<tr>
<td>{{ product.sku }}</td>
<td>{{ product.collection }}</td>
<td>{{ product.product }}</td>
<td>{{ product.size }}</td>
<td>${{ product.retail_price }}</td>
<td>${{ product.vendor_price }}</td>
</tr>
{% empty %}
<li>No articles yet.</li>
{% endfor %}
</table>
</div>
{% endblock %}
Итак, я решил создать представление списка, которое указывает на шаблон детального представления. Я попробовал это и думаю, что не работает то, что мне нужно передать PK от продавца, чтобы получить только товары от этого продавца. PK уже находится в URL из детального представления.
Я думал, что это поможет получить PK, но не получилось.
def get(self, request, *args, **kwargs):
return super().get(request, *args, **kwargs)
Я также попробовал сделать что-то подобное. Это было то, что я тестировал для фильтрованного поиска и подумал, что это может сработать.
class ProductList(ListView):
model = Product
template_name = 'deliveries/vendor_detail.html'
context_object_name = 'products'
def get_queryset(self):
pk = self.kwargs['pk']
queryset = super().get_queryset()
self.filterset = ProductFilter(self.request.GET, queryset=queryset)
return self.filterset.qs
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['form'] = self.filterset.form
return context
Я не уверен, что лучший способ сделать это. Если создание двух представлений, указывающих на один шаблон и пытающихся передать PK из url, является правильным способом.
Чтобы получить все продукты от поставщика, необходимо добавить "related_name" в модель продукта
class Product(models.Model):
vendors = models.ForeignKey(
Vendor,
on_delete=models.CASCADE,
related_name="products",
)
...
А в html просто добавьте vendor.products.all
<h4>Products:</h4>
<ul>
{% for product in vendor.products.all %}
<li>{{product.name}}</li>
{% endfor %}
</ul>