Skip to content

Instantly share code, notes, and snippets.

@dokterbob
Created February 15, 2011 20:00
Show Gist options
  • Select an option

  • Save dokterbob/828117 to your computer and use it in GitHub Desktop.

Select an option

Save dokterbob/828117 to your computer and use it in GitHub Desktop.

Revisions

  1. Mathijs de Bruin renamed this gist Feb 15, 2011. 1 changed file with 0 additions and 0 deletions.
    File renamed without changes.
  2. Mathijs de Bruin created this gist Feb 15, 2011.
    65 changes: 65 additions & 0 deletions snippet.sc
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,65 @@
    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.
    """
    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

    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:
    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', ())