Django Categories v1.1 documentation

# Creating Custom Categories

- Table of Contents
- index
  next
  previous

# Creating Custom Categories

Django Categories isn’t just for using a single category model. It allows you to create your own custom category-like models with as little or much customization as you need.

## Name only

For many cases, you want a simple user-managed lookup table. You can do this with just a little bit of code. The resulting model will include name, slug and active fields and a hierarchical admin.

1. Create a model that subclasses `CategoryBase`

       1
       2
       3
       4
       5
       6
       7
       8
       9

       from categories.models import CategoryBase

       class SimpleCategory(CategoryBase):
           """
           A simple of catgorizing example
           """

           class Meta:
               verbose_name_plural = 'simple categories'

2. Create a subclass of CategoryBaseAdmin.

        1
        2
        3
        4
        5
        6
        7
        8
        9
       10

       from django.contrib import admin

       from categories.admin import CategoryBaseAdmin

       from .models import SimpleCategory

       class SimpleCategoryAdmin(CategoryBaseAdmin):
           pass

       admin.site.register(SimpleCategory, SimpleCategoryAdmin)

3. Register your model and custom model admin class.

## Name and other data

Sometimes you need more functionality, such as extra metadata and custom functions. The `Category` model in this package does this.

1. Create a model that subclasses `CategoryBase` as above.

2. Add new fields to the model. The `Category` model adds these extra fields.

        1
        2
        3
        4
        5
        6
        7
        8
        9
       10
       11
       12
       13
       14
       15
       16
       17
       18
       19
       20
       21
       22
       23
       24
       25
       26
       27
       28
       29

       class Category(CategoryBase):
           thumbnail = models.FileField(
               upload_to=THUMBNAIL_UPLOAD_PATH,
               null=True, blank=True,
               storage=STORAGE(),)
           thumbnail_width = models.IntegerField(blank=True, null=True)
           thumbnail_height = models.IntegerField(blank=True, null=True)
           order = models.IntegerField(default=0)
           alternate_title = models.CharField(
               blank=True,
               default="",
               max_length=100,
               help_text="An alternative title to use on pages with this category.")
           alternate_url = models.CharField(
               blank=True,
               max_length=200,
               help_text="An alternative URL to use instead of the one derived from "
                         "the category hierarchy.")
           description = models.TextField(blank=True, null=True)
           meta_keywords = models.CharField(
               blank=True,
               default="",
               max_length=255,
               help_text="Comma-separated keywords for search engines.")
           meta_extra = models.TextField(
               blank=True,
               default="",
               help_text="(Advanced) Any additional HTML to be placed verbatim "
                         "in the &lt;head&gt;")

3. Add new methods to the model. For example, the `Category` model adds several new methods, including overriding the `save()` method.

        1
        2
        3
        4
        5
        6
        7
        8
        9
       10
       11
       12
       13
       14
       15

       def save(self, *args, **kwargs):
           if self.thumbnail:
               from django.core.files.images import get_image_dimensions
               import django
               if django.VERSION[1] < 2:
                   width, height = get_image_dimensions(self.thumbnail.file)
               else:
                   width, height = get_image_dimensions(self.thumbnail.file, close=True)
           else:
               width, height = None, None

           self.thumbnail_width = width
           self.thumbnail_height = height

           super(Category, self).save(*args, **kwargs)

4. Alter `Meta` or `MPTTMeta` class. Either of these inner classes can be overridden, however your `Meta` class should inherit `CategoryBase.Meta`. Options for `Meta` are in the Django-MPTT docs.

       1
       2
       3
       4
       5

       class Meta(CategoryBase.Meta):
           verbose_name_plural = 'categories'

       class MPTTMeta:
           order_insertion_by = ('order', 'name')

5. For the admin, you must create a form that subclasses `CategoryBaseAdminForm` and at least sets the `Meta.model` attribute. You can also alter the form fields and cleaning methods, as `Category` does.

       1
       2
       3
       4
       5
       6
       7
       8
       9

       class CategoryAdminForm(CategoryBaseAdminForm):
           class Meta:
               model = Category

           def clean_alternate_title(self):
               if self.instance is None or not self.cleaned_data['alternate_title']:
                   return self.cleaned_data['name']
               else:
                   return self.cleaned_data['alternate_title']

6. Next you must subclass `CategoryBaseAdmin` and assign the `form` attribute the form class created above. You can alter any other attributes as necessary.

        1
        2
        3
        4
        5
        6
        7
        8
        9
       10
       11
       12
       13
       14
       15
       16
       17

       class CategoryAdmin(CategoryBaseAdmin):
           form = CategoryAdminForm
           list_display = ('name', 'alternate_title', 'active')
           fieldsets = (
               (None, {
                   'fields': ('parent', 'name', 'thumbnail', 'active')
               }),
               ('Meta Data', {
                   'fields': ('alternate_title', 'alternate_url', 'description',
                               'meta_keywords', 'meta_extra'),
                   'classes': ('collapse',),
               }),
               ('Advanced', {
                   'fields': ('order', 'slug'),
                   'classes': ('collapse',),
               }),
           )