Get_Absolute_URL обратные слизни по многим ко многим полям из другой модели в Django

#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. Спасибо