简体   繁体   中英

django subcategory slug filter

Getting my head around Django and followed the tango with Django book, but this last issue gets me after adding subcategories, which are not included in that tutorial.

I have the following:

models.py
class Category(models.Model):
"""Category"""
name = models.CharField(max_length=50)
slug = models.SlugField()


def save(self, *args, **kwargs):

                    #self.slug = slugify(self.name)
            self.slug = slugify(self.name)
            super(Category, self).save(*args, **kwargs)
def __unicode__(self):
    return self.name


class SubCategory(models.Model):
"""Sub Category"""
category = models.ForeignKey(Category)
name = models.CharField(max_length=50)
slug = models.SlugField()

def save(self, *args, **kwargs):

            self.slug = slugify(self.name)
            super(SubCategory, self).save(*args, **kwargs)

def __unicode__(self):
    return self.name

and

urls.py
(r'^links/$', 'rango.views.links'),
(r'^links/(?P<category_name_slug>[\w\-]+)/$', 'rango.views.category'),  
(r'^links/(?P<category_name_slug>[\w\-]+)/(?P<subcategory_name_slug>[\w\-]+)/$', 'rango.views.subcategory'),  

and

views.py
@require_GET
def links(request):
"""Linkdirectory Page"""
category_list = Category.objects.order_by('name')
context_dict = {'categories': category_list}
return render(request, 'links.html', context_dict)

@require_GET
def category(request, category_name_slug):
"""Category Page"""
category = Category.objects.get(slug=category_name_slug)
subcategory_list = SubCategory.objects.filter(category=category)
context_dict = {'subcategories': subcategory_list}
return render(request, 'category.html', context_dict)

@require_GET
def subcategory(request, subcategory_name_slug, category_name_slug):
"""SubCategory Page"""
context_dict = {}
try:
    subcategory = SubCategory.objects.get(slug=subcategory_name_slug)
    context_dict['subcategory_name'] = subcategory.name
    websites = Website.objects.filter(sub_categories=subcategory)
    context_dict['websites'] = websites
    context_dict['subcategory'] = subcategory
except SubCategory.DoesNotExist:
return render(request, 'subcategory.html', context_dict)

This all works nicely up to the point I add subcategories with the same name, eg the subcategory "other" for multiple categories.

I understand why, when I reach "def subcategory" my slug will return multiple subcategories so I need to limit these to the related category in some way, like a

"SELECT 
subcategory = SubCategory.objects.get(slug=subcategory_name_slug)
WHERE 
subcategory = SubCategory.objects.filter(category=subcategory)
CLAUSE" 

or something ;)

Not sure what's the best route to take on this and how to filter these

Given that you may have two different SubCategory objects with the same name for two different Category objects, as you suggested you can add the Category as an additional filter.

Filter by both SubCategory.slug and Category.slug

To achieve this I see you have a view that takes slugs for both SubCategory and Category , that you defined like this subcategory(request, subcategory_name_slug, category_name_slug) . Those are sufficient to filter:

subcategory = SubCategory.objects.get(
    slug=subcategory_name_slug,
    category__slug=category_name_slug
)
           ^
           |__ # This "double" underscore category__slug is a way to filter
               # a related object (SubCategory.category)
               # So effectively it's like filtering for SubCategory objects where
               # SubCategory.category.slug is category_name_slug

You see above I've used SubCateogry.objects.get(...) to get a single object instead of `SubCategory.objects.filter(...) which can return many objects.

Enforcing unicity of SubCategory.name per Category

To do this safely with get() , there needs to be a guarantee that for any given Category, there will no more than one Subcategory with the same name

You can enforce this condition with unique_together

class SubCategory(models.Model):
    class Meta:
        unique_together = (
            ('category', 'name'),          # since slug is based on name,
                                           # we are sure slug will be unique too
        )

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM