12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576 |
- # -*- coding: utf-8 -*-
- from __future__ import unicode_literals
- from django import forms
- from django.core.exceptions import ObjectDoesNotExist
- import logging
- logger = logging.getLogger(__name__)
- class LimitedAdminInlineMixin(object):
- """
- InlineAdmin mixin limiting the selection of related items according to
- criteria which can depend on the current parent object being edited.
- A typical use case would be selecting a subset of related items from
- other inlines, ie. images, to have some relation to other inlines.
- Use as follows::
- class MyInline(LimitedAdminInlineMixin, admin.TabularInline):
- def get_filters(self, obj):
- return (('<field_name>', dict(<filters>)),)
- """
- @staticmethod
- def limit_inline_choices(formset, field, empty=False, **filters):
- """
- This function fetches the queryset with available choices for a given
- `field` and filters it based on the criteria specified in filters,
- unless `empty=True`. In this case, no choices will be made available.
- """
- try:
- assert formset.form.base_fields.has_key(field)
- qs = formset.form.base_fields[field].queryset
- if empty:
- logger.debug('Limiting the queryset to none')
- formset.form.base_fields[field].queryset = qs.none()
- else:
- qs = qs.filter(**filters)
- logger.debug('Limiting queryset for formset to: %s', qs)
- formset.form.base_fields[field].queryset = qs
- except:
- pass
- def get_formset(self, request, obj=None, **kwargs):
- """
- Make sure we can only select variations that relate to the current
- item.
- """
- formset = \
- super(LimitedAdminInlineMixin, self).get_formset(request,
- obj,
- **kwargs)
- for (field, filters) in self.get_filters(obj):
- if obj and filters:
- self.limit_inline_choices(formset, field, **filters)
- else:
- self.limit_inline_choices(formset, field, empty=True)
-
- return formset
- def get_filters(self, obj):
- """
- Return filters for the specified fields. Filters should be in the
- following format::
- (('field_name', {'categories': obj}), ...)
- For this to work, we should either override `get_filters` in a
- subclass or define a `filters` property with the same syntax as this
- one.
- """
- return getattr(self, 'filters', ())
|