首页 > 解决方案 > Django 打开链接,它会做预设的事情(点击电子商务网站上的“男士”并让它自动过滤男士服装

问题描述

对不起,垃圾标题,我不知道该放什么,如果有人有任何改进,请发表评论,我会相应地更新。

问题

我目前正在做一个电子商务网站,并且已经完成了商店部分的设置(您可以在其中查看产品并根据您的需要进行过滤),现在在导航栏和其他位置,我有诸如“男士”之类的名称或“女性”,

我需要的是这些链接转到商店页面并根据链接自动过滤

所以如果我点击“男士”,它应该会进入商店页面,并返回已经过滤的显示男士产品的项目(最好男士类别内的所有选项都应该已经打勾,但这不是必需的)。然后您可以根据需要继续调整您的过滤器,就像您直接点击商店页面一样。

尝试过的解决方案

首先,我尝试建立一个系统,您可以在其中使用动态 URL 来查看来自例如“shop/women”的链接,但这需要与“shop/”完全相同,只是过滤,我试图像这样将它添加到我的 urls.py 文件中

    path('shop/<str:category>/', Shop.as_view(), name="shop"),

我肯定做错了什么,因为即使我尝试手动尝试它,它也不起作用,并引发 NoReverseMatch 发现错误。我试图在网上查看,但找不到解决方案。

我也很感谢过滤系统的一些帮助,但这不一定是答案,我需要的主要是某种能够获取信息并对其进行过滤的方法。我认为对于任何对 Django 有丰富经验的人来说,这应该是相对容易的,

非常感谢你

代码

我把我认为必要的所有相关代码都放了,但如果有人需要更多,请询问

models.py 产品类

# Product details
class Product(models.Model):
    # name
    name = models.CharField(max_length=256)
    # price
    price = models.DecimalField(max_digits=5, decimal_places=2)
    # date added, i can use this to figure out if the item is new
    date_added = models.DateTimeField(auto_now_add=True)
    # Whether the item is in stock
    in_stock = models.BooleanField(default=True)
    # If the product is on sale
    sale = models.BooleanField(default=False)
    # the price for sale, this can be blank since there won't always be a sale on
    sale_price = models.DecimalField(null=True, blank=True, max_digits=5, decimal_places=2)

    # times sold, use this for bestsellers, not sure how to do this though
    times_sold = models.PositiveIntegerField(default=0)

    # gender type, uses the GENDER_CHOICES, use this in search and homepage
    gender = models.CharField(max_length=256, choices=GENDER_CHOICES, default='women')
    # Items to show on homepage,  so bestseller will show up on bestseller
    home_page_show = models.CharField(max_length=256, choices=DOING_WELL_CHOICES, default='no')
    # Choices for the category to place the product into, we zip it to make it Django compliant
    # ('actual value','human readable value')
    category = models.CharField(max_length=256, choices=zip(CATEGORY_CHOICES, CATEGORY_CHOICES), default='women-coat')

    # Here are all the images
    thumbnail = models.ImageField()
    image_1 = models.ImageField(null=True, blank=True)
    image_2 = models.ImageField(null=True, blank=True)
    image_3 = models.ImageField(null=True, blank=True)
    image_4 = models.ImageField(null=True, blank=True)

    # PRODUCT DETAIL FIELDS
    LOREM_IPSUM = 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.'

    brand = models.CharField(max_length=1000, blank=True, default=LOREM_IPSUM)
    head_description = models.TextField(max_length=1000, blank=True, default=LOREM_IPSUM)
    description_1 = models.TextField(max_length=1000, blank=True, default=LOREM_IPSUM)
    description_2 = models.TextField(max_length=1000, blank=True, default=LOREM_IPSUM)
    specification_1 = models.TextField(max_length=1000, blank=True, default=LOREM_IPSUM)
    specification_2 = models.TextField(max_length=1000, blank=True, default=LOREM_IPSUM)

    # SIZES AVAILABLE
    xxs = models.BooleanField(default=True)
    xs = models.BooleanField(default=True)
    xss = models.BooleanField(default=True)
    s = models.BooleanField(default=True)
    m = models.BooleanField(default=True)
    ml = models.BooleanField(default=True)
    l = models.BooleanField(default=True)
    xl = models.BooleanField(default=True)

    # COLOURS AVAILABLE
    colour = models.CharField(default='red', choices=COLOUR_CHOICES, max_length=256)

    # String Representation
    def __str__(self):
        return self.name

    # This function just makes sure we don't get an error if we try to load an image
    # that doesn't exist, it tries to get the url, and if that fails, returns an empty string
    def thumbnailurl(self):
        try:
            url = self.thumbnail.url
        except:
            url = ''
        return url

    # We're going to do the same thing here, except iterate through all the images and try each one individually
    # this way, we can get as many working images as possible
    def imagesurl(self):
        # Set an empty string as images to store all the urls
        images = []
        # Iterate through each image
        for image in [self.image_1, self.image_2, self.image_3, self.image_4]:
            # Try except to catch any errors
            try:
                # Try to add the image url to the list
                images.append(image.url)
            # image doesn't exist
            except:
                # Add a blank
                images.append('')
        # Return the final product
        return images

商店的views.py

class Shop(ListView):
    # Set the model as Product, the rest is handled by Django
    model = Product
    # Name of HTML File to show
    template_name = 'store/shop.html'
    # What to refer to in the HTML file (injection)
    context_object_name = 'products'

    # If the request.method is POST (a filter request)
    def post(self, request, *args, **kwargs):
        # Function from utils.py
        min_price, max_price, products = filter_shop(request)
        print(min_price, max_price)

        # Function from utils.py
        data = cartData(self.request)
        # Assigning keys to keys in context which can then be referenced in the html
        # Pass is in the completed query as a option, plus cartitems for the cart
        context_dict = {'products': products, 'cartitems': data['cartItems'], 'min_price': min_price,
                        'max_price': max_price, 'categories':category_choices()}
        return render(request, 'store/shop.html', context_dict)

    def get_context_data(self, *args, object_list=None, **kwargs):
        # Call the base implementation first to get a context
        context = super().get_context_data(**kwargs)
        # Function from utils.py
        data = cartData(self.request)
        # Assigning keys to keys in context which can then be referenced in the html
        context['cartitems'] = data['cartItems']
        # Wishlist
        context['wishlistitems'] = data['wishlistitems']

        # Min and max for slider
        context['min_price'], context['max_price'] = 33, 99

        context['categories'] = category_choices()
        return context

用于商店应用的 urls.py

from django.urls import path
from .views import *

app_name = 'store'

urlpatterns = [
    # Index
    path('', Index.as_view(), name="index"),
    # Shop, like searching
    path('shop/', Shop.as_view(), name="shop"),
    # Detail view of product
    path('detail/<int:pk>', ProductDetail.as_view(), name="detail"),

    # Cart and wishlist view, they are basically both the same
    path('cart/', Cart.as_view(), name="cart"),
    path('wishlist/',WishListView.as_view(),name="wishlist"),
    # checkout view
    path('checkout/', Checkout.as_view(), name="checkout"),
    # contact page, STILL NEED TO ADD IN BLOG
    path('contact/',Contact.as_view(),name="contact"),
    # Function which runs to update the cart, look at views.py
    path('update_item/', updateItem, name="update_item"),
    # Function which runs to update the wishlist, very similar to above, look at views.py
    path('update_wishlist/',updateWishList,name="update_wishlist"),
]

标签: pythondjangohyperlinkdjango-views

解决方案


我认为您遇到的问题有一些解决方案。

让我们从网址开始。我认为您可能遇到的问题是,如果您将这两行放在一起:

path('shop/', Shop.as_view(), name="shop"),
path('shop/<str:category>/', Shop.as_view(), name="shop"),

这些名称必须是唯一的,因此您应该将第二个名称称为“shop_category”或类似名称。另一个潜在问题:不要忘记在你的网址末尾添加一个“/”。所以你有这个:

path('shop/<str:category>', Shop.as_view(), name="shop"),

但这需要是这样的:

path('shop/<str:category>/', Shop.as_view(), name="shop"),

如果您要开始使用包含不同视图的更复杂的商店结构,那么我建议您将 url 切换到应用程序结构。为此,请创建一个名为 urls 的文件夹并将您拥有的内容添加为init .py,但不要将 shop 作为视图添加,而是包含另一个 url 列表作为命名空间。

urls/__init__.py

from django.urls import path, include


app_name = 'store'
urlpatterns = [
    path('shop/', include('urls.shop', namespace='shop')),
    (everything else as you have it)
]

然后,您可以添加另一个名为 shop.py 的文件并将特定于该命名空间的内容放入其中。

urls/shop.py

from django.urls import path
from .views import *

app_name = 'store'

urlpatterns = [
    path('', Shop.as_view(), name="index"),
    path('mens/', Shop.as_view(), name="shop"),
]

对于您的具体情况,这可能是矫枉过正。如果您需要使用实际不同的视图,我主要推荐这种方法。使用这种方法,您可以使用 revers("shop:mens") 或任何您命名的模式链接到这些。

最后一点建议(也许这应该是第一点)如果你还没有的话,我要看看 django-tables2 和 django-filters。这极大地简化了从查询集生成表和使用查询字符串过滤数据的过程。因此,您不必只将类别传递给您的视图,而是可以传递一个长查询字符串,例如“http://www.example.com/shop/?category=mens&size=small&foo=bar”。这将告诉您的视图如何一次过滤这三个指标。即使您没有实现 django-filters,我也建议您以这种方式进行过滤。


推荐阅读