GenericForeignKey support

Generic foreign keys are supported since 0.4.

GenericChannelBase

Example

import autocomplete_light

from models import Contact, Address

class MyGenericChannel(autocomplete_light.GenericChannelBase):
    def get_querysets(self):
        return {
            Contact: Contact.objects.all(),
            Address: Address.objects.all(),
        }

    def order_results(self, results):
        if results.model == Address:
            return results.order_by('street')
        elif results.model == Contact:
            return results.order_by('name')

    def query_filter(self, results):
        q = self.request.GET.get('q', None)

        if q:
            if results.model == Address:
                results = results.filter(street__icontains=q)
            elif results.model == Contact:
                results = results.filter(name__icontains=q)

        return results

autocomplete_light.register(MyGenericChannel)

API

class autocomplete_light.channel.generic.GenericChannelBase[source]

Wraps around multiple querysets, from multiple model classes, rather than just one.

This is also interresting as it overrides all the default model logic from ChannelBase. Hell, you could even copy it and make your CSVChannelBase, a channel that uses a CSV file as backend. But only if you’re really bored or for a milion dollars.

Set result_template and autocomplete_template if necessary.

are_valid(values)[source]

Return True if it can find all the models refered by values.

get_results(values=None)[source]

Return results for each queryset returned by get_querysets().

Note that it limits each queryset’s to self.limit_result. If you want a maximum of 12 suggestions and have a total of 4 querysets, then self.limit_results should be set to 3.

order_results(results)[source]

Return results, without doing any ordering.

In most cases, you would not have to override this method as querysets should be ordered by default, based on model.Meta.ordering.

result_as_value(result)[source]

Rely on GenericForeignKeyField to return a string containing the content type id and object id of the result.

Because this channel is made for that field, and to avoid code duplication.

values_filter(results, values)[source]

Filter out any result from results that is not refered to by values.

GenericForeignKeyField

Example

import autocomplete_light

from models import TaggedItem


class TaggedItemForm(autocomplete_light.GenericModelForm):
    content_object = autocomplete_light.GenericForeignKeyField(
        widget=autocomplete_light.AutocompleteWidget(
            'MyGenericChannel', max_items=1))

    class Meta:
        model = TaggedItem
        widgets = autocomplete_light.get_widgets_dict(TaggedItem)
        exclude = (
            'content_type',
            'object_id',
        )

API

class autocomplete_light.generic.GenericModelForm(*args, **kwargs)[source]

This simple subclass of ModelForm fixes a couple of issues with django’s ModelForm.

  • treat virtual fields like GenericForeignKey as normal fields, Django should already do that but it doesn’t,
  • when setting a GenericForeignKey value, also set the object id and content type id fields, again Django could probably afford to do that.

What ModelForm does, but also add virtual field values to self.initial.

save(commit=True)[source]

What ModelForm does, but also set GFK.ct_field and GFK.fk_field if such a virtual field has a value.

This should probably be done in the GFK field itself, but it’s here for convenience until Django fixes that.

class autocomplete_light.generic.GenericForeignKeyField(required=True, widget=None, label=None, initial=None, help_text=None, error_messages=None, show_hidden_initial=False, validators=[], localize=False)[source]

Simple form field that converts strings to models.

prepare_value(value)[source]

Given a model instance as value, with content type id of 3 and pk of 5, return such a string ‘3-5’.

to_python(value)[source]

Given a string like ‘3-5’, return the model of content type id 3 and pk 5.

GenericManyToMany

Example

Example model with related:

from django.db import models
from django.db.models import signals
from django.contrib.contenttypes import generic

from genericm2m.models import RelatedObjectsDescriptor

class ModelGroup(models.Model):
    name = models.CharField(max_length=100)

    related = RelatedObjectsDescriptor()

    def __unicode__(self):
        return self.name

Example generic_m2m.GenericModelForm usage:

import autocomplete_light
from autocomplete_light.contrib.generic_m2m import GenericModelForm, \
    GenericManyToMany

from models import ModelGroup


class ModelGroupForm(GenericModelForm):
    related = GenericManyToMany(
        widget=autocomplete_light.AutocompleteWidget('MyGenericChannel'))

    class Meta:
        model = ModelGroup

Example ModelAdmin:

from django.contrib import admin

from models import ModelGroup
from forms import ModelGroupForm


class ModelGroupAdmin(admin.ModelAdmin):
    form = ModelGroupForm
admin.site.register(ModelGroup, ModelGroupAdmin)

API

autocomplete_light.contrib.generic_m2m couples django-autocomplete-light with django-generic-m2m.

Generic many to many are supported since 0.5. It depends on django-generic-m2m external apps. Follow django-generic-m2m installation documentation, but at the time of writing it barely consists of adding the genericm2m to INSTALLED_APPS, and adding a field to models that should have a generic m2m relation. So, kudos to the maintainers of django-generic-m2m, fantastic app, use it for generic many to many relations.

See examples in test_project/generic_m2m_example.

class autocomplete_light.contrib.generic_m2m.GenericManyToMany(required=True, widget=None, label=None, initial=None, help_text=None, error_messages=None, show_hidden_initial=False, validators=[], localize=False)[source]

Simple form field that converts strings to models.

class autocomplete_light.contrib.generic_m2m.GenericModelForm(*args, **kwargs)[source]

Extension of autocomplete_light.GenericModelForm, that handles genericm2m’s RelatedObjectsDescriptor.

Add related objects to initial for each generic m2m field.

generic_m2m_fields()[source]

Yield name, field for each RelatedObjectsDescriptor of the model of this ModelForm.

save(commit=True)[source]

Sorry guys, but we have to force commit=True and call save_m2m() right after.

The reason for that is that Django 1.4 kind of left over cases where we wanted to override save_m2m: it enforces its own, which does not care of generic_m2m of course.

save_m2m()[source]

Save selected generic m2m relations.

Project Versions

Table Of Contents

Previous topic

Integration with forms

Next topic

Proposing results from a remote API

This Page