# Django 1.8.18.dev20170123152445 documentation

# Source code for django.contrib.contenttypes.forms

    from __future__ import unicode_literals

    from django.contrib.contenttypes.models import ContentType
    from django.db import models
    from django.forms import ModelForm, modelformset_factory
    from django.forms.models import BaseModelFormSet

    class BaseGenericInlineFormSet(BaseModelFormSet):
        """
        A formset for generic inline objects to a parent.
        """

        def __init__(self, data=None, files=None, instance=None, save_as_new=None,
                     prefix=None, queryset=None, **kwargs):
            opts = self.model._meta
            self.instance = instance
            self.rel_name = '-'.join((
                opts.app_label, opts.model_name,
                self.ct_field.name, self.ct_fk_field.name,
            ))
            if self.instance is None or self.instance.pk is None:
                qs = self.model._default_manager.none()
            else:
                if queryset is None:
                    queryset = self.model._default_manager
                qs = queryset.filter(**{
                    self.ct_field.name: ContentType.objects.get_for_model(
                        self.instance, for_concrete_model=self.for_concrete_model),
                    self.ct_fk_field.name: self.instance.pk,
                })
            super(BaseGenericInlineFormSet, self).__init__(
                queryset=qs, data=data, files=files,
                prefix=prefix,
                **kwargs
            )

        @classmethod
        def get_default_prefix(cls):
            opts = cls.model._meta
            return '-'.join(
                (opts.app_label, opts.model_name,
                cls.ct_field.name, cls.ct_fk_field.name)
            )

        def save_new(self, form, commit=True):
            setattr(form.instance, self.ct_field.get_attname(),
                ContentType.objects.get_for_model(self.instance).pk)
            setattr(form.instance, self.ct_fk_field.get_attname(),
                self.instance.pk)
            return form.save(commit=commit)

    def generic_inlineformset_factory(model, form=ModelForm,
                                      formset=BaseGenericInlineFormSet,
                                      ct_field="content_type", fk_field="object_id",
                                      fields=None, exclude=None,
                                      extra=3, can_order=False, can_delete=True,
                                      max_num=None, formfield_callback=None,
                                      validate_max=False, for_concrete_model=True,
                                      min_num=None, validate_min=False):
        """
        Returns a ``GenericInlineFormSet`` for the given kwargs.

        You must provide ``ct_field`` and ``fk_field`` if they are different from
        the defaults ``content_type`` and ``object_id`` respectively.
        """
        opts = model._meta
        # if there is no field called `ct_field` let the exception propagate
        ct_field = opts.get_field(ct_field)
        if not isinstance(ct_field, models.ForeignKey) or ct_field.rel.to != ContentType:
            raise Exception("fk_name '%s' is not a ForeignKey to ContentType" % ct_field)
        fk_field = opts.get_field(fk_field)  # let the exception propagate
        if exclude is not None:
            exclude = list(exclude)
            exclude.extend([ct_field.name, fk_field.name])
        else:
            exclude = [ct_field.name, fk_field.name]
        FormSet = modelformset_factory(model, form=form,
                                       formfield_callback=formfield_callback,
                                       formset=formset,
                                       extra=extra, can_delete=can_delete, can_order=can_order,
                                       fields=fields, exclude=exclude, max_num=max_num,
                                       validate_max=validate_max, min_num=min_num,
                                       validate_min=validate_min)
        FormSet.ct_field = ct_field
        FormSet.ct_fk_field = fk_field
        FormSet.for_concrete_model = for_concrete_model
        return FormSet