def formfield_for_dbfield(self, db_field, **kwargs): """ Hook for specifying the form Field instance for a given database Field instance. If kwargs are given, they're passed to the form Field's constructor. """ request = kwargs.pop("request", None) formfield = db_field.formfield(**kwargs) if formfield and isinstance( db_field, (models.ForeignKey, models.ManyToManyField)): from django.contrib.admin import site as admin_site related_modeladmin = admin_site._registry.get(db_field.rel.to) can_add_related = bool( related_modeladmin and related_modeladmin.has_add_permission(request)) formfield.widget = widgets.RelatedFieldWidgetWrapper( formfield.widget, db_field.rel, admin_site, can_add_related=can_add_related) else: for klass in db_field.__class__.mro(): if klass in self.formfield_overrides: kwargs = dict( copy.deepcopy(self.formfield_overrides[klass]), **kwargs) return db_field.formfield(**kwargs) return formfield
def adminform_formfield(db_field, **kwargs): """ Enables admin form widgets when used as formfield_callback. Use with CAUTION as using admin widgets is at your risk :) """ if db_field.choices: return db_field.formfield(**kwargs) if isinstance(db_field, (models.ForeignKey, models.ManyToManyField)): if isinstance(db_field, models.ForeignKey): kwargs['widget'] = widgets.ForeignKeyRawIdWidget(db_field.rel) elif isinstance(db_field, models.ManyToManyField): kwargs['widget'] = widgets.ManyToManyRawIdWidget(db_field.rel) formfield = db_field.formfield(**kwargs) if formfield: # related_modeladmin = admin.site._registry.get(db_field.rel.to) # can_add_related = bool(related_modeladmin and # related_modeladmin.has_add_permission(request)) formfield.widget = widgets.RelatedFieldWidgetWrapper( formfield.widget, db_field.rel, admin.site, can_add_related=True) for klass in db_field.__class__.mro(): if klass in FORMFIELD_FOR_DBFIELD_DEFAULTS: kwargs = dict(FORMFIELD_FOR_DBFIELD_DEFAULTS[klass], **kwargs) return db_field.formfield(**kwargs) return db_field.formfield(**kwargs)
def formfield_for_photo_field(self, db_field, **kwargs): """ (Overrided from BaseModelAdmin to remove the RelatedFieldWidgetWrapper) Hook for specifying the form Field instance for a given database Field instance. If kwargs are given, they're passed to the form Field's constructor. """ # If the field specifies choices, we don't need to look for special # admin widgets - we just need to use a select widget of some kind. if 'request' in kwargs: request = kwargs.pop('request') if db_field.choices: return self.formfield_for_choice_field(db_field, request, **kwargs) # ForeignKey or ManyToManyFields if isinstance(db_field, models.ManyToManyField) or isinstance(db_field, models.ForeignKey): # Combine the field kwargs with any options for formfield_overrides. # Make sure the passed in **kwargs override anything in # formfield_overrides because **kwargs is more specific, and should # always win. if db_field.__class__ in self.formfield_overrides: kwargs = dict(self.formfield_overrides[db_field.__class__], **kwargs) # Get the correct formfield. if isinstance(db_field, models.ForeignKey): formfield = self.formfield_for_foreignkey(db_field, request, **kwargs) elif isinstance(db_field, models.ManyToManyField): formfield = self.formfield_for_manytomany(db_field, request, **kwargs) # For non-raw_id fields, wrap the widget with a wrapper that adds # extra HTML -- the "add other" interface -- to the end of the # rendered output. formfield can be None if it came from a # OneToOneField with parent_link=True or a M2M intermediary. if isinstance(db_field, PhotoField): pass elif formfield and db_field.name not in self.raw_id_fields: related_modeladmin = self.admin_site._registry.get(db_field.remote_field.model) wrapper_kwargs = {} if related_modeladmin: wrapper_kwargs.update( can_add_related=related_modeladmin.has_add_permission(request), can_change_related=related_modeladmin.has_change_permission(request), can_delete_related=related_modeladmin.has_delete_permission(request), ) formfield.widget = widgets.RelatedFieldWidgetWrapper( formfield.widget, db_field.remote_field, self.admin_site, **wrapper_kwargs ) return formfield # If we've got overrides for the formfield defined, use 'em. **kwargs # passed to formfield_for_dbfield override the defaults. for klass in db_field.__class__.mro(): if klass in model_admin.formfield_overrides: kwargs = dict(copy.deepcopy(model_admin.formfield_overrides[klass]), **kwargs) return db_field.formfield(**kwargs) # For any other type of field, just call its formfield() method. return db_field.formfield(**kwargs)
def formfield_for_dbfield(self, db_field, request, **kwargs): # ForeignKey or ManyToManyFields if isinstance(db_field, ArrayManyToManyField): # Combine the field kwargs with any options for formfield_overrides. # Make sure the passed in **kwargs override anything in # formfield_overrides because **kwargs is more specific, and should # always win. if db_field.__class__ in self.formfield_overrides: kwargs = dict(self.formfield_overrides[db_field.__class__], **kwargs) formfield = self.formfield_for_manytomany(db_field, request, **kwargs) # For non-raw_id fields, wrap the widget with a wrapper that adds # extra HTML -- the "add other" interface -- to the end of the # rendered output. formfield can be None if it came from a # OneToOneField with parent_link=True or a M2M intermediary. if formfield and db_field.name not in self.raw_id_fields: related_modeladmin = self.admin_site._registry.get(db_field.remote_field.model) wrapper_kwargs = {} if related_modeladmin: wrapper_kwargs.update( can_add_related=related_modeladmin.has_add_permission(request), can_change_related=related_modeladmin.has_change_permission(request), can_delete_related=related_modeladmin.has_delete_permission(request), ) formfield.widget = widgets.RelatedFieldWidgetWrapper( formfield.widget, db_field.remote_field, self.admin_site, **wrapper_kwargs ) return formfield else: return super(PostgresAdmin, self).formfield_for_dbfield(db_field, request, **kwargs)
def __init__(self, *args, **kwargs): super(MailboxForm, self).__init__(*args, **kwargs) # Hack the widget in order to display add button remote_field_mock = AttrDict( **{ 'model': Address, 'get_related_field': lambda: AttrDict(name='id'), }) widget = self.fields['addresses'].widget self.fields['addresses'].widget = widgets.RelatedFieldWidgetWrapper( widget, remote_field_mock, self.modeladmin.admin_site, can_add_related=True) account = self.modeladmin.account # Filter related addresses by account old_render = self.fields['addresses'].widget.render def render(*args, **kwargs): output = old_render(*args, **kwargs) args = 'account=%i&mailboxes=%s' % (account.pk, self.instance.pk) output = output.replace('/add/?', '/add/?%s&' % args) return mark_safe(output) self.fields['addresses'].widget.render = render queryset = self.fields['addresses'].queryset realted_addresses = queryset.filter( account_id=account.pk).order_by('name') self.fields['addresses'].queryset = realted_addresses if self.instance and self.instance.pk: self.fields['addresses'].initial = self.instance.addresses.all()
class RelatedFieldWidgetWrapperForm(forms.Form): description = "RelatedFieldWidgetWrapper" field1 = forms.ModelChoiceField( help_text='default', queryset=Permission.objects.all(), widget=widgets.RelatedFieldWidgetWrapper( widget=forms.Select(), rel=Permission._meta.get_field('content_type').remote_field, admin_site=admin_site))
def formfield_for_dbfield(self, db_field, **kwargs): """ Hook for specifying the form Field instance for a given database Field instance. If kwargs are given, they're passed to the form Field's constructor. """ request = kwargs.pop("request", None) # If the field specifies choices, we don't need to look for special # admin widgets - we just need to use a select widget of some kind. if db_field.choices is not None: return self.formfield_for_choice_field(db_field, request, **kwargs) if isinstance(db_field, ListField) and isinstance( db_field.field, ReferenceField): return self.formfield_for_manytomany(db_field, request, **kwargs) # handle RelatedFields if isinstance(db_field, ReferenceField): # For non-raw_id fields, wrap the widget with a wrapper that adds # extra HTML -- the "add other" interface -- to the end of the # rendered output. formfield can be None if it came from a # OneToOneField with parent_link=True or a M2M intermediary. form_field = db_field.formfield(**kwargs) if db_field.name not in self.raw_id_fields: related_modeladmin = self.admin_site._registry.get( db_field.document_type) can_add_related = bool( related_modeladmin and related_modeladmin.has_add_permission(request)) form_field.widget = widgets.RelatedFieldWidgetWrapper( form_field.widget, RelationWrapper(db_field.document_type), self.admin_site, can_add_related=can_add_related) return form_field if isinstance(db_field, StringField): if db_field.max_length is None: kwargs = dict({'widget': widgets.AdminTextareaWidget}, **kwargs) else: kwargs = dict({'widget': widgets.AdminTextInputWidget}, **kwargs) return db_field.formfield(**kwargs) # If we've got overrides for the formfield defined, use 'em. **kwargs # passed to formfield_for_dbfield override the defaults. for klass in db_field.__class__.mro(): if klass in self.formfield_overrides: kwargs = dict(self.formfield_overrides[klass], **kwargs) return db_field.formfield(**kwargs) # For any other type of field, just call its formfield() method. return db_field.formfield(**kwargs)
def formfield_for_dbfield(self, db_field, **kwargs): """ Hook for specifying the form Field instance for a given database Field instance. If kwargs are given, they're passed to the form Field's constructor. """ request = kwargs.pop("request", None) # If the field specifies choices, we don't need to look for special # admin widgets - we just need to use a select widget of some kind. if db_field.choices: return self.formfield_for_choice_field(db_field, request, **kwargs) # ForeignKey or ManyToManyFields if isinstance(db_field, (models.ForeignKey, models.ManyToManyField)): # Combine the field kwargs with any options for formfield_overrides. # Make sure the passed in **kwargs override anything in # formfield_overrides because **kwargs is more specific, and should # always win. if db_field.__class__ in self.formfield_overrides: kwargs = dict(self.formfield_overrides[db_field.__class__], **kwargs) # Get the correct formfield. if isinstance(db_field, models.ForeignKey): formfield = self.formfield_for_foreignkey( db_field, request, **kwargs) elif isinstance(db_field, models.ManyToManyField): formfield = self.formfield_for_manytomany( db_field, request, **kwargs) # For non-raw_id fields, wrap the widget with a wrapper that adds # extra HTML -- the "add other" interface -- to the end of the # rendered output. formfield can be None if it came from a # OneToOneField with parent_link=True or a M2M intermediary. if formfield and db_field.name not in self.raw_id_fields: formfield.widget = widgets.RelatedFieldWidgetWrapper( formfield.widget, db_field.rel, self.admin_site) return formfield # If we've got overrides for the formfield defined, use 'em. **kwargs # passed to formfield_for_dbfield override the defaults. if db_field.__class__ in self.formfield_overrides: kwargs = dict(self.formfield_overrides[db_field.__class__], **kwargs) return db_field.formfield(**kwargs) # For any other type of field, just call its formfield() method. return db_field.formfield(**kwargs)
def __init__(self, *args, **kwargs): super(InvoiceAdminForm, self).__init__(*args, **kwargs) rel = models.ManyToManyRel(Product, 'id') query = Product.objects.filter(public=True, history=False) if self.instance.pk: query |= self.instance.products.all() self.fields['products'] = forms.ModelMultipleChoiceField( queryset=query, required=False, label='Produits de la facture', widget=widgets.FilteredSelectMultiple('Produits', False, attrs={'rows': '10'})) self.fields['products'].widget = widgets.RelatedFieldWidgetWrapper( self.fields['products'].widget, rel, self.admin_site)
def admin_attribute_formfield(self, attribute, formfield, request): typ = attribute.get_type() model = typ.get_model() if model: remote_field = Value._meta.get_field( typ.get_value_field_name() ).rel related_modeladmin = self.admin_site._registry.get(model) wrapper_kwargs = {} if related_modeladmin: wrapper_kwargs.update( can_add_related=related_modeladmin.has_add_permission( request ), can_change_related= related_modeladmin.has_change_permission(request), can_delete_related= related_modeladmin.has_delete_permission(request) ) formfield.widget = widgets.RelatedFieldWidgetWrapper( formfield.widget, remote_field, self.admin_site, **wrapper_kwargs ) return formfield
def test_no_can_add_related(self): rel = models.Individual._meta.get_field('parent').rel w = widgets.AdminRadioSelect() # Used to fail with a name error. w = widgets.RelatedFieldWidgetWrapper(w, rel, widget_admin_site) self.assertFalse(w.can_add_related)
def formfield_for_dbfield(self, db_field, **kwargs): """ Hook for specifying the form Field instance for a given database Field instance. If kwargs are given, they're passed to the form Field's constructor. """ # For DateTimeFields, use a special field and widget. if isinstance(db_field, models.DateTimeField): kwargs['form_class'] = forms.SplitDateTimeField kwargs['widget'] = widgets.AdminSplitDateTime() return db_field.formfield(**kwargs) # For DateFields, add a custom CSS class. if isinstance(db_field, models.DateField): kwargs['widget'] = widgets.AdminDateWidget return db_field.formfield(**kwargs) # For TimeFields, add a custom CSS class. if isinstance(db_field, models.TimeField): kwargs['widget'] = widgets.AdminTimeWidget return db_field.formfield(**kwargs) # For FileFields and ImageFields add a link to the current file. if isinstance(db_field, models.ImageField) or isinstance( db_field, models.FileField): kwargs['widget'] = widgets.AdminFileWidget return db_field.formfield(**kwargs) # For ForeignKey or ManyToManyFields, use a special widget. if isinstance(db_field, (models.ForeignKey, models.ManyToManyField)): if isinstance( db_field, models.ForeignKey) and db_field.name in self.raw_id_fields: kwargs['widget'] = widgets.ForeignKeyRawIdWidget(db_field.rel) elif isinstance( db_field, models.ForeignKey) and db_field.name in self.radio_fields: kwargs['widget'] = widgets.AdminRadioSelect(attrs={ 'class': get_ul_class(self.radio_fields[db_field.name]), }) kwargs['empty_label'] = db_field.blank and _('None') or None else: if isinstance(db_field, models.ManyToManyField): if db_field.name in self.raw_id_fields: kwargs['widget'] = widgets.ManyToManyRawIdWidget( db_field.rel) kwargs['help_text'] = '' elif db_field.name in (list(self.filter_vertical) + list(self.filter_horizontal)): kwargs['widget'] = widgets.FilteredSelectMultiple( db_field.verbose_name, (db_field.name in self.filter_vertical)) # Wrap the widget's render() method with a method that adds # extra HTML to the end of the rendered output. formfield = db_field.formfield(**kwargs) # Don't wrap raw_id fields. Their add function is in the popup window. if not db_field.name in self.raw_id_fields: formfield.widget = widgets.RelatedFieldWidgetWrapper( formfield.widget, db_field.rel, self.admin_site) return formfield if db_field.choices and db_field.name in self.radio_fields: kwargs['widget'] = widgets.AdminRadioSelect( choices=db_field.get_choices(include_blank=db_field.blank, blank_choice=[('', _('None'))]), attrs={ 'class': get_ul_class(self.radio_fields[db_field.name]), }) # For any other type of field, just call its formfield() method. return db_field.formfield(**kwargs)
def formfield_for_dbfield(self, db_field, request, **kwargs): """ MO ADMIN NOTE: it's a COPY FROM admin.options.BaseModelAdmin to replace related actions behaviour Hook for specifying the form Field instance for a given database Field instance. If kwargs are given, they're passed to the form Field's constructor. """ # If the field specifies choices, we don't need to look for special # admin widgets - we just need to use a select widget of some kind. if db_field.choices: return self.formfield_for_choice_field(db_field, request, **kwargs) # ForeignKey or ManyToManyFields if isinstance(db_field, (models.ForeignKey, models.ManyToManyField)): # Combine the field kwargs with any options for formfield_overrides. # Make sure the passed in **kwargs override anything in # formfield_overrides because **kwargs is more specific, and should # always win. if db_field.__class__ in self.formfield_overrides: kwargs = dict(self.formfield_overrides[db_field.__class__], **kwargs) # Get the correct formfield. if isinstance(db_field, models.ForeignKey): formfield = self.formfield_for_foreignkey( db_field, request, **kwargs) elif isinstance(db_field, models.ManyToManyField): formfield = self.formfield_for_manytomany( db_field, request, **kwargs) # For non-raw_id fields, wrap the widget with a wrapper that adds # extra HTML -- the "add other" interface -- to the end of the # rendered output. formfield can be None if it came from a # OneToOneField with parent_link=True or a M2M intermediary. if formfield and db_field.name not in self.raw_id_fields: related_modeladmin = self.admin_site._registry.get( db_field.remote_field.model) wrapper_kwargs = {} if related_modeladmin: wrapper_kwargs.update( can_add_related=related_modeladmin.has_add_permission( request), can_change_related=related_modeladmin. has_change_permission(request), can_delete_related=related_modeladmin. has_delete_permission(request), ) # MO ADMIN customizations are here if self.related_models_actions.get(db_field.name): wrapper_kwargs = self.related_models_actions.get( db_field.name) else: # disable all related actions if they weren't specified explicitly wrapper_kwargs = { 'can_add_related': False, 'can_change_related': False, 'can_delete_related': False, } # MO ADMIN note, # this method could be overriden to provide internal urls to related models: # RelatedFieldWidgetWrapper.get_related_url() formfield.widget = widgets.RelatedFieldWidgetWrapper( formfield.widget, db_field.remote_field, self.admin_site, **wrapper_kwargs) return formfield # If we've got overrides for the formfield defined, use 'em. **kwargs # passed to formfield_for_dbfield override the defaults. for klass in db_field.__class__.mro(): if klass in self.formfield_overrides: kwargs = dict(copy.deepcopy(self.formfield_overrides[klass]), **kwargs) return db_field.formfield(**kwargs) # For any other type of field, just call its formfield() method. return db_field.formfield(**kwargs)
def formfield_for_dbfield(self, db_field, **kwargs): """ Hook for specifying the form Field instance for a given database Field instance. If kwargs are given, they're passed to the form Field's constructor. """ # If the field specifies choices, we don't need to look for special # admin widgets - we just need to use a select widget of some kind. if db_field.choices: if db_field.name in self.radio_fields: # If the field is named as a radio_field, use a RadioSelect kwargs['widget'] = widgets.AdminRadioSelect(attrs={ 'class': get_ul_class(self.radio_fields[db_field.name]), }) kwargs['choices'] = db_field.get_choices( include_blank=db_field.blank, blank_choice=[('', _('None'))]) return db_field.formfield(**kwargs) else: # Otherwise, use the default select widget. return db_field.formfield(**kwargs) # For DateTimeFields, use a special field and widget. if isinstance(db_field, models.DateTimeField): kwargs['form_class'] = forms.SplitDateTimeField kwargs['widget'] = widgets.AdminSplitDateTime() return db_field.formfield(**kwargs) # For DateFields, add a custom CSS class. if isinstance(db_field, models.DateField): kwargs['widget'] = widgets.AdminDateWidget return db_field.formfield(**kwargs) # For TimeFields, add a custom CSS class. if isinstance(db_field, models.TimeField): kwargs['widget'] = widgets.AdminTimeWidget return db_field.formfield(**kwargs) # For TextFields, add a custom CSS class. if isinstance(db_field, models.TextField): kwargs['widget'] = widgets.AdminTextareaWidget return db_field.formfield(**kwargs) # For URLFields, add a custom CSS class. if isinstance(db_field, models.URLField): kwargs['widget'] = widgets.AdminURLFieldWidget return db_field.formfield(**kwargs) # For IntegerFields, add a custom CSS class. if isinstance(db_field, models.IntegerField): kwargs['widget'] = widgets.AdminIntegerFieldWidget return db_field.formfield(**kwargs) # For CommaSeparatedIntegerFields, add a custom CSS class. if isinstance(db_field, models.CommaSeparatedIntegerField): kwargs['widget'] = widgets.AdminCommaSeparatedIntegerFieldWidget return db_field.formfield(**kwargs) # For TextInputs, add a custom CSS class. if isinstance(db_field, models.CharField): kwargs['widget'] = widgets.AdminTextInputWidget return db_field.formfield(**kwargs) # For FileFields and ImageFields add a link to the current file. if isinstance(db_field, models.ImageField) or isinstance( db_field, models.FileField): kwargs['widget'] = widgets.AdminFileWidget return db_field.formfield(**kwargs) # For ForeignKey or ManyToManyFields, use a special widget. if isinstance(db_field, (models.ForeignKey, models.ManyToManyField)): if isinstance( db_field, models.ForeignKey) and db_field.name in self.raw_id_fields: kwargs['widget'] = widgets.ForeignKeyRawIdWidget(db_field.rel) elif isinstance( db_field, models.ForeignKey) and db_field.name in self.radio_fields: kwargs['widget'] = widgets.AdminRadioSelect(attrs={ 'class': get_ul_class(self.radio_fields[db_field.name]), }) kwargs['empty_label'] = db_field.blank and _('None') or None else: if isinstance(db_field, models.ManyToManyField): # If it uses an intermediary model, don't show field in admin. if db_field.rel.through is not None: return None elif db_field.name in self.raw_id_fields: kwargs['widget'] = widgets.ManyToManyRawIdWidget( db_field.rel) kwargs['help_text'] = '' elif db_field.name in (list(self.filter_vertical) + list(self.filter_horizontal)): kwargs['widget'] = widgets.FilteredSelectMultiple( db_field.verbose_name, (db_field.name in self.filter_vertical)) # Wrap the widget's render() method with a method that adds # extra HTML to the end of the rendered output. formfield = db_field.formfield(**kwargs) # Don't wrap raw_id fields. Their add function is in the popup window. if not db_field.name in self.raw_id_fields: # formfield can be None if it came from a OneToOneField with # parent_link=True if formfield is not None: formfield.widget = widgets.RelatedFieldWidgetWrapper( formfield.widget, db_field.rel, self.admin_site) return formfield # For any other type of field, just call its formfield() method. return db_field.formfield(**kwargs)
def __init__(self, *args, **kwargs): super(ProductAdminForm, self).__init__(*args, **kwargs) rel = models.ManyToManyRel(Product, 'id') self.fields['pack_product'].widget = widgets.RelatedFieldWidgetWrapper( self.fields['pack_product'].widget, rel, self.admin_site)