from django import forms
from django.contrib.auth.models import User
from django.contrib.contenttypes.models import ContentType
from django.utils.safestring import mark_safe
from django.utils.translation import gettext as _

from dcim.models import DeviceRole, DeviceType, Platform, Region, Site, SiteGroup
from tenancy.models import Tenant, TenantGroup
from utilities.forms import (
    add_blank_choice, APISelectMultiple, BootstrapMixin, BulkEditForm, BulkEditNullBooleanSelect, ColorSelect,
    CommentField, ContentTypeMultipleChoiceField, CSVModelForm, DateTimePicker, DynamicModelMultipleChoiceField,
    JSONField, SlugField, StaticSelect2, BOOLEAN_WITH_BLANK_CHOICES,
)
from virtualization.models import Cluster, ClusterGroup
from .choices import *
from .models import ConfigContext, CustomField, ImageAttachment, JournalEntry, ObjectChange, Tag
from .utils import FeatureQuery


#
# Custom fields
#

class CustomFieldForm(forms.Form):
    """
    Extend Form to include custom field support.
    """
    model = None

    def __init__(self, *args, **kwargs):
        if self.model is None:
            raise NotImplementedError("CustomFieldForm must specify a model class.")
        self.custom_fields = []

        super().__init__(*args, **kwargs)

        # Append relevant custom fields to the form instance
        obj_type = ContentType.objects.get_for_model(self.model)
        for cf in CustomField.objects.filter(content_types=obj_type):
            field_name = 'cf_{}'.format(cf.name)
            self.fields[field_name] = cf.to_form_field()

            # Annotate the field in the list of CustomField form fields
            self.custom_fields.append(field_name)


class CustomFieldModelForm(forms.ModelForm):
    """
    Extend ModelForm to include custom field support.
    """
    def __init__(self, *args, **kwargs):

        self.obj_type = ContentType.objects.get_for_model(self._meta.model)
        self.custom_fields = []

        super().__init__(*args, **kwargs)

        self._append_customfield_fields()

    def _append_customfield_fields(self):
        """
        Append form fields for all CustomFields assigned to this model.
        """
        # Append form fields; assign initial values if modifying and existing object
        for cf in CustomField.objects.filter(content_types=self.obj_type):
            field_name = 'cf_{}'.format(cf.name)
            if self.instance.pk:
                self.fields[field_name] = cf.to_form_field(set_initial=False)
                self.fields[field_name].initial = self.instance.custom_field_data.get(cf.name)
            else:
                self.fields[field_name] = cf.to_form_field()

            # Annotate the field in the list of CustomField form fields
            self.custom_fields.append(field_name)

    def clean(self):

        # Save custom field data on instance
        for cf_name in self.custom_fields:
            self.instance.custom_field_data[cf_name[3:]] = self.cleaned_data.get(cf_name)

        return super().clean()


class CustomFieldModelCSVForm(CSVModelForm, CustomFieldModelForm):

    def _append_customfield_fields(self):

        # Append form fields
        for cf in CustomField.objects.filter(content_types=self.obj_type):
            field_name = 'cf_{}'.format(cf.name)
            self.fields[field_name] = cf.to_form_field(for_csv_import=True)

            # Annotate the field in the list of CustomField form fields
            self.custom_fields.append(field_name)


class CustomFieldBulkEditForm(BulkEditForm):

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.custom_fields = []
        self.obj_type = ContentType.objects.get_for_model(self.model)

        # Add all applicable CustomFields to the form
        custom_fields = CustomField.objects.filter(content_types=self.obj_type)
        for cf in custom_fields:
            # Annotate non-required custom fields as nullable
            if not cf.required:
                self.nullable_fields.append(cf.name)
            self.fields[cf.name] = cf.to_form_field(set_initial=False, enforce_required=False)
            # Annotate this as a custom field
            self.custom_fields.append(cf.name)


class CustomFieldFilterForm(forms.Form):

    def __init__(self, *args, **kwargs):

        self.obj_type = ContentType.objects.get_for_model(self.model)

        super().__init__(*args, **kwargs)

        # Add all applicable CustomFields to the form
        custom_fields = CustomField.objects.filter(content_types=self.obj_type).exclude(
            filter_logic=CustomFieldFilterLogicChoices.FILTER_DISABLED
        )
        for cf in custom_fields:
            field_name = 'cf_{}'.format(cf.name)
            self.fields[field_name] = cf.to_form_field(set_initial=True, enforce_required=False)


#
# Tags
#

class TagForm(BootstrapMixin, forms.ModelForm):
    slug = SlugField()

    class Meta:
        model = Tag
        fields = [
            'name', 'slug', 'color', 'description'
        ]
        fieldsets = (
            ('Tag', ('name', 'slug', 'color', 'description')),
        )


class TagCSVForm(CSVModelForm):
    slug = SlugField()

    class Meta:
        model = Tag
        fields = Tag.csv_headers
        help_texts = {
            'color': mark_safe('RGB color in hexadecimal (e.g. <code>00ff00</code>)'),
        }


class AddRemoveTagsForm(forms.Form):

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        # Add add/remove tags fields
        self.fields['add_tags'] = DynamicModelMultipleChoiceField(
            queryset=Tag.objects.all(),
            required=False
        )
        self.fields['remove_tags'] = DynamicModelMultipleChoiceField(
            queryset=Tag.objects.all(),
            required=False
        )


class TagFilterForm(BootstrapMixin, forms.Form):
    model = Tag
    q = forms.CharField(
        required=False,
        label=_('Search')
    )
    content_type_id = ContentTypeMultipleChoiceField(
        queryset=ContentType.objects.filter(FeatureQuery('tags').get_query()),
        required=False,
        label=_('Tagged object type')
    )


class TagBulkEditForm(BootstrapMixin, BulkEditForm):
    pk = forms.ModelMultipleChoiceField(
        queryset=Tag.objects.all(),
        widget=forms.MultipleHiddenInput
    )
    color = forms.CharField(
        max_length=6,
        required=False,
        widget=ColorSelect()
    )
    description = forms.CharField(
        max_length=200,
        required=False
    )

    class Meta:
        nullable_fields = ['description']


#
# Config contexts
#

class ConfigContextForm(BootstrapMixin, forms.ModelForm):
    regions = DynamicModelMultipleChoiceField(
        queryset=Region.objects.all(),
        required=False
    )
    site_groups = DynamicModelMultipleChoiceField(
        queryset=SiteGroup.objects.all(),
        required=False
    )
    sites = DynamicModelMultipleChoiceField(
        queryset=Site.objects.all(),
        required=False
    )
    device_types = DynamicModelMultipleChoiceField(
        queryset=DeviceType.objects.all(),
        required=False
    )
    roles = DynamicModelMultipleChoiceField(
        queryset=DeviceRole.objects.all(),
        required=False
    )
    platforms = DynamicModelMultipleChoiceField(
        queryset=Platform.objects.all(),
        required=False
    )
    cluster_groups = DynamicModelMultipleChoiceField(
        queryset=ClusterGroup.objects.all(),
        required=False
    )
    clusters = DynamicModelMultipleChoiceField(
        queryset=Cluster.objects.all(),
        required=False
    )
    tenant_groups = DynamicModelMultipleChoiceField(
        queryset=TenantGroup.objects.all(),
        required=False
    )
    tenants = DynamicModelMultipleChoiceField(
        queryset=Tenant.objects.all(),
        required=False
    )
    tags = DynamicModelMultipleChoiceField(
        queryset=Tag.objects.all(),
        required=False
    )
    data = JSONField(
        label=''
    )

    class Meta:
        model = ConfigContext
        fields = (
            'name', 'weight', 'description', 'is_active', 'regions', 'site_groups', 'sites', 'roles', 'device_types',
            'platforms', 'cluster_groups', 'clusters', 'tenant_groups', 'tenants', 'tags', 'data',
        )


class ConfigContextBulkEditForm(BootstrapMixin, BulkEditForm):
    pk = forms.ModelMultipleChoiceField(
        queryset=ConfigContext.objects.all(),
        widget=forms.MultipleHiddenInput
    )
    weight = forms.IntegerField(
        required=False,
        min_value=0
    )
    is_active = forms.NullBooleanField(
        required=False,
        widget=BulkEditNullBooleanSelect()
    )
    description = forms.CharField(
        required=False,
        max_length=100
    )

    class Meta:
        nullable_fields = [
            'description',
        ]


class ConfigContextFilterForm(BootstrapMixin, forms.Form):
    field_order = [
        'q', 'region_id', 'site_group_id', 'site_id', 'role_id', 'platform_id', 'cluster_group_id', 'cluster_id',
        'tenant_group_id', 'tenant_id',
    ]
    q = forms.CharField(
        required=False,
        label=_('Search')
    )
    region_id = DynamicModelMultipleChoiceField(
        queryset=Region.objects.all(),
        required=False,
        label=_('Regions')
    )
    site_group_id = DynamicModelMultipleChoiceField(
        queryset=SiteGroup.objects.all(),
        required=False,
        label=_('Site groups')
    )
    site_id = DynamicModelMultipleChoiceField(
        queryset=Site.objects.all(),
        required=False,
        label=_('Sites')
    )
    device_type_id = DynamicModelMultipleChoiceField(
        queryset=DeviceType.objects.all(),
        required=False,
        label=_('Device types')
    )
    role_id = DynamicModelMultipleChoiceField(
        queryset=DeviceRole.objects.all(),
        required=False,
        label=_('Roles')
    )
    platform_id = DynamicModelMultipleChoiceField(
        queryset=Platform.objects.all(),
        required=False,
        label=_('Platforms')
    )
    cluster_group_id = DynamicModelMultipleChoiceField(
        queryset=ClusterGroup.objects.all(),
        required=False,
        label=_('Cluster groups')
    )
    cluster_id = DynamicModelMultipleChoiceField(
        queryset=Cluster.objects.all(),
        required=False,
        label=_('Clusters')
    )
    tenant_group_id = DynamicModelMultipleChoiceField(
        queryset=TenantGroup.objects.all(),
        required=False,
        label=_('Tenant groups')
    )
    tenant_id = DynamicModelMultipleChoiceField(
        queryset=Tenant.objects.all(),
        required=False,
        label=_('Tenant')
    )
    tag = DynamicModelMultipleChoiceField(
        queryset=Tag.objects.all(),
        to_field_name='slug',
        required=False,
        label=_('Tags')
    )


#
# Filter form for local config context data
#

class LocalConfigContextFilterForm(forms.Form):
    local_context_data = forms.NullBooleanField(
        required=False,
        label=_('Has local config context data'),
        widget=StaticSelect2(
            choices=BOOLEAN_WITH_BLANK_CHOICES
        )
    )


#
# Image attachments
#

class ImageAttachmentForm(BootstrapMixin, forms.ModelForm):

    class Meta:
        model = ImageAttachment
        fields = [
            'name', 'image',
        ]


#
# Journal entries
#

class JournalEntryForm(BootstrapMixin, forms.ModelForm):
    comments = CommentField()

    class Meta:
        model = JournalEntry
        fields = ['assigned_object_type', 'assigned_object_id', 'kind', 'comments']
        widgets = {
            'assigned_object_type': forms.HiddenInput,
            'assigned_object_id': forms.HiddenInput,
        }


class JournalEntryBulkEditForm(BootstrapMixin, BulkEditForm):
    pk = forms.ModelMultipleChoiceField(
        queryset=JournalEntry.objects.all(),
        widget=forms.MultipleHiddenInput
    )
    kind = forms.ChoiceField(
        choices=JournalEntryKindChoices,
        required=False
    )
    comments = forms.CharField(
        required=False,
        widget=forms.Textarea()
    )

    class Meta:
        nullable_fields = []


class JournalEntryFilterForm(BootstrapMixin, forms.Form):
    model = JournalEntry
    q = forms.CharField(
        required=False,
        label=_('Search')
    )
    created_after = forms.DateTimeField(
        required=False,
        label=_('After'),
        widget=DateTimePicker()
    )
    created_before = forms.DateTimeField(
        required=False,
        label=_('Before'),
        widget=DateTimePicker()
    )
    created_by_id = DynamicModelMultipleChoiceField(
        queryset=User.objects.all(),
        required=False,
        label=_('User'),
        widget=APISelectMultiple(
            api_url='/api/users/users/',
        )
    )
    assigned_object_type_id = DynamicModelMultipleChoiceField(
        queryset=ContentType.objects.all(),
        required=False,
        label=_('Object Type'),
        widget=APISelectMultiple(
            api_url='/api/extras/content-types/',
        )
    )
    kind = forms.ChoiceField(
        choices=add_blank_choice(JournalEntryKindChoices),
        required=False,
        widget=StaticSelect2()
    )


#
# Change logging
#

class ObjectChangeFilterForm(BootstrapMixin, forms.Form):
    model = ObjectChange
    q = forms.CharField(
        required=False,
        label=_('Search')
    )
    time_after = forms.DateTimeField(
        required=False,
        label=_('After'),
        widget=DateTimePicker()
    )
    time_before = forms.DateTimeField(
        required=False,
        label=_('Before'),
        widget=DateTimePicker()
    )
    action = forms.ChoiceField(
        choices=add_blank_choice(ObjectChangeActionChoices),
        required=False,
        widget=StaticSelect2()
    )
    user_id = DynamicModelMultipleChoiceField(
        queryset=User.objects.all(),
        required=False,
        label=_('User'),
        widget=APISelectMultiple(
            api_url='/api/users/users/',
        )
    )
    changed_object_type_id = DynamicModelMultipleChoiceField(
        queryset=ContentType.objects.all(),
        required=False,
        label=_('Object Type'),
        widget=APISelectMultiple(
            api_url='/api/extras/content-types/',
        )
    )


#
# Scripts
#

class ScriptForm(BootstrapMixin, forms.Form):
    _commit = forms.BooleanField(
        required=False,
        initial=True,
        label="Commit changes",
        help_text="Commit changes to the database (uncheck for a dry-run)"
    )

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        # Move _commit to the end of the form
        commit = self.fields.pop('_commit')
        self.fields['_commit'] = commit

    @property
    def requires_input(self):
        """
        A boolean indicating whether the form requires user input (ignore the _commit field).
        """
        return bool(len(self.fields) > 1)

[(139, 'utilities.forms.SlugField', 'SlugField', False, 'from utilities.forms import add_blank_choice, APISelectMultiple, BootstrapMixin, BulkEditForm, BulkEditNullBooleanSelect, ColorSelect, CommentField, ContentTypeMultipleChoiceField, CSVModelForm, DateTimePicker, DynamicModelMultipleChoiceField, JSONField, SlugField, StaticSelect2, BOOLEAN_WITH_BLANK_CHOICES\n'), (152, 'utilities.forms.SlugField', 'SlugField', False, 'from utilities.forms import add_blank_choice, APISelectMultiple, BootstrapMixin, BulkEditForm, BulkEditNullBooleanSelect, ColorSelect, CommentField, ContentTypeMultipleChoiceField, CSVModelForm, DateTimePicker, DynamicModelMultipleChoiceField, JSONField, SlugField, StaticSelect2, BOOLEAN_WITH_BLANK_CHOICES\n'), (201, 'django.forms.CharField', 'forms.CharField', False, 'from django import forms\n'), (259, 'utilities.forms.JSONField', 'JSONField', False, 'from utilities.forms import add_blank_choice, APISelectMultiple, BootstrapMixin, BulkEditForm, BulkEditNullBooleanSelect, ColorSelect, CommentField, ContentTypeMultipleChoiceField, CSVModelForm, DateTimePicker, DynamicModelMultipleChoiceField, JSONField, SlugField, StaticSelect2, BOOLEAN_WITH_BLANK_CHOICES\n'), (276, 'django.forms.IntegerField', 'forms.IntegerField', False, 'from django import forms\n'), (284, 'django.forms.CharField', 'forms.CharField', False, 'from django import forms\n'), (394, 'utilities.forms.CommentField', 'CommentField', False, 'from utilities.forms import add_blank_choice, APISelectMultiple, BootstrapMixin, BulkEditForm, BulkEditNullBooleanSelect, ColorSelect, CommentField, ContentTypeMultipleChoiceField, CSVModelForm, DateTimePicker, DynamicModelMultipleChoiceField, JSONField, SlugField, StaticSelect2, BOOLEAN_WITH_BLANK_CHOICES\n'), (410, 'django.forms.ChoiceField', 'forms.ChoiceField', False, 'from django import forms\n'), (510, 'django.forms.BooleanField', 'forms.BooleanField', False, 'from django import forms\n'), (38, 'django.contrib.contenttypes.models.ContentType.objects.get_for_model', 'ContentType.objects.get_for_model', False, 'from django.contrib.contenttypes.models import ContentType\n'), (53, 'django.contrib.contenttypes.models.ContentType.objects.get_for_model', 'ContentType.objects.get_for_model', False, 'from django.contrib.contenttypes.models import ContentType\n'), (104, 'django.contrib.contenttypes.models.ContentType.objects.get_for_model', 'ContentType.objects.get_for_model', False, 'from django.contrib.contenttypes.models import ContentType\n'), (121, 'django.contrib.contenttypes.models.ContentType.objects.get_for_model', 'ContentType.objects.get_for_model', False, 'from django.contrib.contenttypes.models import ContentType\n'), (158, 'django.utils.safestring.mark_safe', 'mark_safe', False, 'from django.utils.safestring import mark_safe\n'), (182, 'django.utils.translation.gettext', '_', True, 'from django.utils.translation import gettext as _\n'), (187, 'django.utils.translation.gettext', '_', True, 'from django.utils.translation import gettext as _\n'), (199, 'utilities.forms.ColorSelect', 'ColorSelect', False, 'from utilities.forms import add_blank_choice, APISelectMultiple, BootstrapMixin, BulkEditForm, BulkEditNullBooleanSelect, ColorSelect, CommentField, ContentTypeMultipleChoiceField, CSVModelForm, DateTimePicker, DynamicModelMultipleChoiceField, JSONField, SlugField, StaticSelect2, BOOLEAN_WITH_BLANK_CHOICES\n'), (216, 'dcim.models.Region.objects.all', 'Region.objects.all', False, 'from dcim.models import DeviceRole, DeviceType, Platform, Region, Site, SiteGroup\n'), (220, 'dcim.models.SiteGroup.objects.all', 'SiteGroup.objects.all', False, 'from dcim.models import DeviceRole, DeviceType, Platform, Region, Site, SiteGroup\n'), (224, 'dcim.models.Site.objects.all', 'Site.objects.all', False, 'from dcim.models import DeviceRole, DeviceType, Platform, Region, Site, SiteGroup\n'), (228, 'dcim.models.DeviceType.objects.all', 'DeviceType.objects.all', False, 'from dcim.models import DeviceRole, DeviceType, Platform, Region, Site, SiteGroup\n'), (232, 'dcim.models.DeviceRole.objects.all', 'DeviceRole.objects.all', False, 'from dcim.models import DeviceRole, DeviceType, Platform, Region, Site, SiteGroup\n'), (236, 'dcim.models.Platform.objects.all', 'Platform.objects.all', False, 'from dcim.models import DeviceRole, DeviceType, Platform, Region, Site, SiteGroup\n'), (240, 'virtualization.models.ClusterGroup.objects.all', 'ClusterGroup.objects.all', False, 'from virtualization.models import Cluster, ClusterGroup\n'), (244, 'virtualization.models.Cluster.objects.all', 'Cluster.objects.all', False, 'from virtualization.models import Cluster, ClusterGroup\n'), (248, 'tenancy.models.TenantGroup.objects.all', 'TenantGroup.objects.all', False, 'from tenancy.models import Tenant, TenantGroup\n'), (252, 'tenancy.models.Tenant.objects.all', 'Tenant.objects.all', False, 'from tenancy.models import Tenant, TenantGroup\n'), (282, 'utilities.forms.BulkEditNullBooleanSelect', 'BulkEditNullBooleanSelect', False, 'from utilities.forms import add_blank_choice, APISelectMultiple, BootstrapMixin, BulkEditForm, BulkEditNullBooleanSelect, ColorSelect, CommentField, ContentTypeMultipleChoiceField, CSVModelForm, DateTimePicker, DynamicModelMultipleChoiceField, JSONField, SlugField, StaticSelect2, BOOLEAN_WITH_BLANK_CHOICES\n'), (302, 'django.utils.translation.gettext', '_', True, 'from django.utils.translation import gettext as _\n'), (305, 'dcim.models.Region.objects.all', 'Region.objects.all', False, 'from dcim.models import DeviceRole, DeviceType, Platform, Region, Site, SiteGroup\n'), (307, 'django.utils.translation.gettext', '_', True, 'from django.utils.translation import gettext as _\n'), (310, 'dcim.models.SiteGroup.objects.all', 'SiteGroup.objects.all', False, 'from dcim.models import DeviceRole, DeviceType, Platform, Region, Site, SiteGroup\n'), (312, 'django.utils.translation.gettext', '_', True, 'from django.utils.translation import gettext as _\n'), (315, 'dcim.models.Site.objects.all', 'Site.objects.all', False, 'from dcim.models import DeviceRole, DeviceType, Platform, Region, Site, SiteGroup\n'), (317, 'django.utils.translation.gettext', '_', True, 'from django.utils.translation import gettext as _\n'), (320, 'dcim.models.DeviceType.objects.all', 'DeviceType.objects.all', False, 'from dcim.models import DeviceRole, DeviceType, Platform, Region, Site, SiteGroup\n'), (322, 'django.utils.translation.gettext', '_', True, 'from django.utils.translation import gettext as _\n'), (325, 'dcim.models.DeviceRole.objects.all', 'DeviceRole.objects.all', False, 'from dcim.models import DeviceRole, DeviceType, Platform, Region, Site, SiteGroup\n'), (327, 'django.utils.translation.gettext', '_', True, 'from django.utils.translation import gettext as _\n'), (330, 'dcim.models.Platform.objects.all', 'Platform.objects.all', False, 'from dcim.models import DeviceRole, DeviceType, Platform, Region, Site, SiteGroup\n'), (332, 'django.utils.translation.gettext', '_', True, 'from django.utils.translation import gettext as _\n'), (335, 'virtualization.models.ClusterGroup.objects.all', 'ClusterGroup.objects.all', False, 'from virtualization.models import Cluster, ClusterGroup\n'), (337, 'django.utils.translation.gettext', '_', True, 'from django.utils.translation import gettext as _\n'), (340, 'virtualization.models.Cluster.objects.all', 'Cluster.objects.all', False, 'from virtualization.models import Cluster, ClusterGroup\n'), (342, 'django.utils.translation.gettext', '_', True, 'from django.utils.translation import gettext as _\n'), (345, 'tenancy.models.TenantGroup.objects.all', 'TenantGroup.objects.all', False, 'from tenancy.models import Tenant, TenantGroup\n'), (347, 'django.utils.translation.gettext', '_', True, 'from django.utils.translation import gettext as _\n'), (350, 'tenancy.models.Tenant.objects.all', 'Tenant.objects.all', False, 'from tenancy.models import Tenant, TenantGroup\n'), (352, 'django.utils.translation.gettext', '_', True, 'from django.utils.translation import gettext as _\n'), (358, 'django.utils.translation.gettext', '_', True, 'from django.utils.translation import gettext as _\n'), (369, 'django.utils.translation.gettext', '_', True, 'from django.utils.translation import gettext as _\n'), (370, 'utilities.forms.StaticSelect2', 'StaticSelect2', False, 'from utilities.forms import add_blank_choice, APISelectMultiple, BootstrapMixin, BulkEditForm, BulkEditNullBooleanSelect, ColorSelect, CommentField, ContentTypeMultipleChoiceField, CSVModelForm, DateTimePicker, DynamicModelMultipleChoiceField, JSONField, SlugField, StaticSelect2, BOOLEAN_WITH_BLANK_CHOICES\n'), (416, 'django.forms.Textarea', 'forms.Textarea', False, 'from django import forms\n'), (427, 'django.utils.translation.gettext', '_', True, 'from django.utils.translation import gettext as _\n'), (431, 'django.utils.translation.gettext', '_', True, 'from django.utils.translation import gettext as _\n'), (432, 'utilities.forms.DateTimePicker', 'DateTimePicker', False, 'from utilities.forms import add_blank_choice, APISelectMultiple, BootstrapMixin, BulkEditForm, BulkEditNullBooleanSelect, ColorSelect, CommentField, ContentTypeMultipleChoiceField, CSVModelForm, DateTimePicker, DynamicModelMultipleChoiceField, JSONField, SlugField, StaticSelect2, BOOLEAN_WITH_BLANK_CHOICES\n'), (436, 'django.utils.translation.gettext', '_', True, 'from django.utils.translation import gettext as _\n'), (437, 'utilities.forms.DateTimePicker', 'DateTimePicker', False, 'from utilities.forms import add_blank_choice, APISelectMultiple, BootstrapMixin, BulkEditForm, BulkEditNullBooleanSelect, ColorSelect, CommentField, ContentTypeMultipleChoiceField, CSVModelForm, DateTimePicker, DynamicModelMultipleChoiceField, JSONField, SlugField, StaticSelect2, BOOLEAN_WITH_BLANK_CHOICES\n'), (440, 'django.contrib.auth.models.User.objects.all', 'User.objects.all', False, 'from django.contrib.auth.models import User\n'), (442, 'django.utils.translation.gettext', '_', True, 'from django.utils.translation import gettext as _\n'), (443, 'utilities.forms.APISelectMultiple', 'APISelectMultiple', False, 'from utilities.forms import add_blank_choice, APISelectMultiple, BootstrapMixin, BulkEditForm, BulkEditNullBooleanSelect, ColorSelect, CommentField, ContentTypeMultipleChoiceField, CSVModelForm, DateTimePicker, DynamicModelMultipleChoiceField, JSONField, SlugField, StaticSelect2, BOOLEAN_WITH_BLANK_CHOICES\n'), (448, 'django.contrib.contenttypes.models.ContentType.objects.all', 'ContentType.objects.all', False, 'from django.contrib.contenttypes.models import ContentType\n'), (450, 'django.utils.translation.gettext', '_', True, 'from django.utils.translation import gettext as _\n'), (451, 'utilities.forms.APISelectMultiple', 'APISelectMultiple', False, 'from utilities.forms import add_blank_choice, APISelectMultiple, BootstrapMixin, BulkEditForm, BulkEditNullBooleanSelect, ColorSelect, CommentField, ContentTypeMultipleChoiceField, CSVModelForm, DateTimePicker, DynamicModelMultipleChoiceField, JSONField, SlugField, StaticSelect2, BOOLEAN_WITH_BLANK_CHOICES\n'), (456, 'utilities.forms.add_blank_choice', 'add_blank_choice', False, 'from utilities.forms import add_blank_choice, APISelectMultiple, BootstrapMixin, BulkEditForm, BulkEditNullBooleanSelect, ColorSelect, CommentField, ContentTypeMultipleChoiceField, CSVModelForm, DateTimePicker, DynamicModelMultipleChoiceField, JSONField, SlugField, StaticSelect2, BOOLEAN_WITH_BLANK_CHOICES\n'), (458, 'utilities.forms.StaticSelect2', 'StaticSelect2', False, 'from utilities.forms import add_blank_choice, APISelectMultiple, BootstrapMixin, BulkEditForm, BulkEditNullBooleanSelect, ColorSelect, CommentField, ContentTypeMultipleChoiceField, CSVModelForm, DateTimePicker, DynamicModelMultipleChoiceField, JSONField, SlugField, StaticSelect2, BOOLEAN_WITH_BLANK_CHOICES\n'), (470, 'django.utils.translation.gettext', '_', True, 'from django.utils.translation import gettext as _\n'), (474, 'django.utils.translation.gettext', '_', True, 'from django.utils.translation import gettext as _\n'), (475, 'utilities.forms.DateTimePicker', 'DateTimePicker', False, 'from utilities.forms import add_blank_choice, APISelectMultiple, BootstrapMixin, BulkEditForm, BulkEditNullBooleanSelect, ColorSelect, CommentField, ContentTypeMultipleChoiceField, CSVModelForm, DateTimePicker, DynamicModelMultipleChoiceField, JSONField, SlugField, StaticSelect2, BOOLEAN_WITH_BLANK_CHOICES\n'), (479, 'django.utils.translation.gettext', '_', True, 'from django.utils.translation import gettext as _\n'), (480, 'utilities.forms.DateTimePicker', 'DateTimePicker', False, 'from utilities.forms import add_blank_choice, APISelectMultiple, BootstrapMixin, BulkEditForm, BulkEditNullBooleanSelect, ColorSelect, CommentField, ContentTypeMultipleChoiceField, CSVModelForm, DateTimePicker, DynamicModelMultipleChoiceField, JSONField, SlugField, StaticSelect2, BOOLEAN_WITH_BLANK_CHOICES\n'), (483, 'utilities.forms.add_blank_choice', 'add_blank_choice', False, 'from utilities.forms import add_blank_choice, APISelectMultiple, BootstrapMixin, BulkEditForm, BulkEditNullBooleanSelect, ColorSelect, CommentField, ContentTypeMultipleChoiceField, CSVModelForm, DateTimePicker, DynamicModelMultipleChoiceField, JSONField, SlugField, StaticSelect2, BOOLEAN_WITH_BLANK_CHOICES\n'), (485, 'utilities.forms.StaticSelect2', 'StaticSelect2', False, 'from utilities.forms import add_blank_choice, APISelectMultiple, BootstrapMixin, BulkEditForm, BulkEditNullBooleanSelect, ColorSelect, CommentField, ContentTypeMultipleChoiceField, CSVModelForm, DateTimePicker, DynamicModelMultipleChoiceField, JSONField, SlugField, StaticSelect2, BOOLEAN_WITH_BLANK_CHOICES\n'), (488, 'django.contrib.auth.models.User.objects.all', 'User.objects.all', False, 'from django.contrib.auth.models import User\n'), (490, 'django.utils.translation.gettext', '_', True, 'from django.utils.translation import gettext as _\n'), (491, 'utilities.forms.APISelectMultiple', 'APISelectMultiple', False, 'from utilities.forms import add_blank_choice, APISelectMultiple, BootstrapMixin, BulkEditForm, BulkEditNullBooleanSelect, ColorSelect, CommentField, ContentTypeMultipleChoiceField, CSVModelForm, DateTimePicker, DynamicModelMultipleChoiceField, JSONField, SlugField, StaticSelect2, BOOLEAN_WITH_BLANK_CHOICES\n'), (496, 'django.contrib.contenttypes.models.ContentType.objects.all', 'ContentType.objects.all', False, 'from django.contrib.contenttypes.models import ContentType\n'), (498, 'django.utils.translation.gettext', '_', True, 'from django.utils.translation import gettext as _\n'), (499, 'utilities.forms.APISelectMultiple', 'APISelectMultiple', False, 'from utilities.forms import add_blank_choice, APISelectMultiple, BootstrapMixin, BulkEditForm, BulkEditNullBooleanSelect, ColorSelect, CommentField, ContentTypeMultipleChoiceField, CSVModelForm, DateTimePicker, DynamicModelMultipleChoiceField, JSONField, SlugField, StaticSelect2, BOOLEAN_WITH_BLANK_CHOICES\n')]