#python #python-3.x #django #django-models #reverse
#python #python-3.x #django #django-модели #обратный
Вопрос:
Я использую слизни для адреса URL. Все это работает, но когда я хочу показать детали продукта. Я не знаю, как я могу получить два слизней из другой модели и поместить его рядом с подробным слизнем.
(категория находится в основном URL-адресе)
(покажите мне все продукты Samsung mobile)
Работает: site.com/category/mobile/samsung /
(Я хочу, когда я хочу щелкнуть по одному из них, показать мне детали, но это не работает)
Не работает: site.com/category/mobile/samsung/s10
Модель:
from Django.db import models
from Django.shortcuts import reverse
class Category(models.Model):
name = models.CharField(max_length=150)
slug = models.SlugField(unique=True, max_length=200)
child_category = models.ForeignKey('self', max_length=150, null=True, blank=True, on_delete=models.CASCADE)
is_child = models.BooleanField(default=False)
def get_absolute_url(self):
return reverse('shop:brands', args=[self.slug])
def get_absolute_url_product(self):
return reverse('shop:products', args=[self.child_category.slug, self.slug])
class Product(models.Model):
category = models.ManyToManyField(to=Category, related_name='products')
name = models.CharField(max_length=150)
slug = models.SlugField(unique=True, max_length=200)
description = models.TextField()
# Here I did what I knew, but It didn't work.
===============================================
def get_absolute_url_details(self):
return reverse('shop:product_details',
self.category.model.slug,
self.category.model.child_category.slug,
self.slug)
Когда я использую этот обратный способ, он выдает мне следующую ошибку:
объект ‘ForwardManyToOneDescriptor’ не имеет атрибута ‘slug’
URL:
from Django.urls import path
from Shop import views
app_name = 'shop'
urlpatterns = [
path('<slug:brands_slug>/', views.brands, name='brands'),
path('<slug:brands_slug>/<slug:product_slug>/', views.products, name='products'),
path('<slug:brands_slug>/<slug:product_slug>/<slug:product_details>/', views.details_products, name='product_details'),
]
Вид:
def products(request, brands_slug, product_slug):
product = Product.objects.filter(category__slug=product_slug, category__child_category__slug=brands_slug)
context = {'product': product}
return render(request, 'shop/products.html', context=context)
def details_products(request, brands_slug, product_slug, product_details):
details = Product.objects.filter(category__child_category__slug=brands_slug, category__slug=product_slug, slug=product_details)
context = {'details': details}
return render(request, 'shop/product_details.html', context=context)
Комментарии:
1.
self.category.model.*
это не то, что вы думаете. Удалите.model
часть, напримерself.category.slug
.2. @Selcuk: когда я удаляю из них модель, это выдает мне следующую ошибку: «Объект’ManyRelatedManager’ не имеет атрибута ‘slug'»
3. О, у вас есть отношение ManyToMany от продукта к категории. В этом случае
self.category.slug
не имеет смысла. Какая категория?
Ответ №1:
У меня была аналогичная проблема с возвратом абсолютного URL-адреса из двух пуль отношения «многие ко многим», и мое решение состоит в том, чтобы вернуть набор URL-адресов для объекта следующим образом. Возможно, это поможет другим людям.
class Category(models.Model):
...
slug = models.SlugField(max_length=255, blank=True, unique=True)
...
class Product(models.Model):
...
slug = models.SlugField(max_length=255, blank=True, unique=True)
categories = models.ManyToManyField(Category,
related_name="categories",
blank=True,
)
...
def get_absolute_urls(self):
urls = []
for category in self.categories.all():
urls.append(f'/categories/{category.slug}/products/{self.slug}/')
return urls
Ответ №2:
У вас проблема с вашей структурой данных.
Ваша модель продукта имеет несколько категорий (M2M). Итак, когда вы запрашиваете product.category, вы получаете не одну категорию, а все категории, которыми является этот продукт. Product.category — это набор запросов.
Вы хотите получить один единственный слизнь из набора нескольких категорий, каждая из которых имеет свой слизнь. Это не может работать.
У вас есть два решения, в зависимости от того, что вы пытаетесь сделать.
Первый — изменить отношение M2M от продукта к категории на внешний ключ frmo product to category. Таким образом, product.category предоставит вам экземпляр модели категории вместо набора запросов.
В этом случае вам следует переименовать поле Product.category в Product.categories, чтобы было ясно, что у вас может быть более одной категории.
Второе решение: вы должны выбрать одну категорию из своего набора категорий. Например:
slug = product.category.first().slug
Осторожно: first() может вернуть None, если с этим продуктом не связаны категории.
Комментарии:
1. Спасибо, мой друг, за твой ответ, я использовал второй способ, потому что мне не нужно было менять модель, плюс слишком много деталей, и сейчас она работает. но у меня есть один вопрос, если бы у нас было более двух слизней, и мне нужно было использовать средний, что еще я мог бы использовать? Я имею в виду, что мы не можем использовать first() и last(), потому что нам нужен средний.
2. Кроме того, не могли бы вы объяснить первое решение, как с помощью ForeignKey мы можем использовать две категории, которые связаны друг с другом? Я имею в виду, например, iPhone7 — это мобильный телефон, а также для бренда Apple. Две категории. Итак, как мы можем использовать внешний ключ, чтобы связать эти два с iPhone7. Спасибо