charettes / django-admin-enhancer Goto Github PK
View Code? Open in Web Editor NEWA simple django app that provides change and deletion links to FK fields in the admin
License: MIT License
A simple django app that provides change and deletion links to FK fields in the admin
License: MIT License
The recommended way to install the Debug Toolbar is via pip:
Debug Toolbar, should’t that be Admin Enhancer?
Hi,
first of all, thank you for this nice widget wrapper :-)
When using the enhancer with a Model with a ManyToManyField, the wrapper is also activated for the ManyToMany field. Although the "add-link" still works correctly, the edit- and delete- links don't work since they are passed an array of keys instead of an integer.
Except for creating a custom dropdown where the edit- and delete- links would be located on each line of the drop-down, I don't really see a good solution for ManyToManyField's so maybe the wrapper should only be enabled for ForeignKey's and not for every RelatedFieldWidgetWrapper
It's slightly disturbing when that happens. You probably don't want to list Django itself in 'install_requires'
I typed:
pip install django-admin-enhancer
I saw:
Found existing installation: Django 1.8.2
Uninstalling Django-1.8.2
I expected:
A warning message? An exception? Maybe even nothing - it might work fine on 1.8...
At the moment django-admin-enhancer can't be used to Django CMS plugins: CMSPluginBase class -ancestor of every Django CMS plugin- is derived from ModelAdmin and works pretty much as any ModelAdinm class, so it'd be nice to use admin-enhancer.
To display proper interface CMSPluginBase fakes a "popup" interface, thus triggering modified response_change
in EnhancedModelAdminMixin
I managed to fix this creating a derived mixin which overrides response_change
reverting to the default behavior:
class EnhancedModelPluginMixin(EnhancedModelAdminMixin):
def response_change(self, request, obj):
return super(EnhancedModelAdminMixin, self).response_change(request, obj)
If this looks like a proper solution to you, I'll create a PR to include this in your codebase
At least in README.md
Good day!
I'm trying to use your widget in application, which formerly used patch from https://code.djangoproject.com/ticket/13163 .
You can see code below, when editing Series admin enhancer working with FeaturesInline, but ModelsInline renders without widget. Screenshot: http://rghost.ru/38857605/image.png
Is there any way to make it work without re-factoring logic of application and it's DB?
#admin.py
class FeaturesInline(enhanced_admin.EnhancedAdminMixin, admin.TabularInline):
model = Feature
class ModelsInline(enhanced_admin.EnhancedAdminMixin, admin.TabularInline):
model = Model
class SeriesAdmin(EnhancedModelAdmin):
inlines = [PhotoInline, FeaturesInline, ModelsInline]
list_display = ('name', 'category', 'created_at', 'updated_at',)
list_display_links = ('name',)
list_per_page = 50
ordering = ['category']
search_fields = ['name', 'description']
prepopulated_fields = {'slug' : ('name',)}
admin.site.register(Series, SeriesAdmin)
#models.py
class Series(models.Model):
category = models.ForeignKey(Category, verbose_name='Категория')
brand = models.ForeignKey(Brand, verbose_name='Производитель')
name = models.CharField(max_length=255, verbose_name='Название')
slug = models.SlugField(max_length=255, unique=True, verbose_name='Ссылка')
mini_html_description = tinymce_models.HTMLField()
html_description = models.TextField(blank=True, verbose_name='Описание', help_text='Описание в HTML')
is_active = models.BooleanField(default=True, verbose_name='Активный')
is_bestseller = models.BooleanField(default=False, verbose_name='Лидер продаж')
is_special_price = models.BooleanField(default=False, verbose_name='Специальная цена')
is_discount = models.BooleanField(default=True, verbose_name='Скидка')
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __unicode__(self):
return self.name
@models.permalink
def get_absolute_url(self):
return ('product-page', [str(self.slug)])
class Meta:
ordering = ['brand']
verbose_name_plural = 'Серии товара'
class Model(models.Model):
name = models.CharField(max_length=255, unique=True, verbose_name='Название')
series = models.ForeignKey(Series)
price = models.DecimalField(max_digits=9,decimal_places=2, verbose_name='Цена', null=True, blank=True)
def __unicode__(self):
return self.name
class Meta:
ordering = ['name']
verbose_name_plural = 'Модели товара'
class FeaturesName(models.Model):
name = models.CharField(max_length=50, unique=True)
def __unicode__(self):
return self.name
class Meta:
ordering = ['name']
verbose_name_plural = 'Характеристики товара'
class Feature(models.Model):
name = models.ForeignKey(FeaturesName, verbose_name='Характеристика')
series = models.ForeignKey(Series)
def __unicode__(self):
return unicode(self.name)
Hi,
I'd like to use the enhance_exclude
option you merged in from @yakky a while ago. Would it be possible to make a new release on pypi?
Really awesome little library you have here, it makes the admin so much more usable!
Is thee any possibility for the name that appears in the drop-down list to be updated when a user has edited the item in question? The changes does get saved to the database, but the drop-down list is not updated at the time of editing.
This is from an install from master on 4 Feb 2013. I followed the setup as per the example, with:
class EnhancedModelAdmin(enhanced_admin.EnhancedModelAdminMixin,
admin.ModelAdmin):
pass
and using:
class MyModelAdmin(EnhancedModelAdmin):
Traceback:
File "/usr/local/lib/python2.7/dist-packages/django/core/handlers/base.py" in get_response
136. response = response.render()
File "/usr/local/lib/python2.7/dist-packages/django/template/response.py" in render
104. self._set_content(self.rendered_content)
File "/usr/local/lib/python2.7/dist-packages/django/template/response.py" in rendered_content
81. content = template.render(context)
File "/usr/local/lib/python2.7/dist-packages/django/template/base.py" in render
140. return self._render(context)
File "/usr/local/lib/python2.7/dist-packages/django/template/base.py" in _render
134. return self.nodelist.render(context)
File "/usr/local/lib/python2.7/dist-packages/django/template/base.py" in render
823. bit = self.render_node(node, context)
File "/usr/local/lib/python2.7/dist-packages/django/template/base.py" in render_node
837. return node.render(context)
File "/usr/local/lib/python2.7/dist-packages/django/template/loader_tags.py" in render
123. return compiled_parent._render(context)
File "/usr/local/lib/python2.7/dist-packages/django/template/base.py" in _render
134. return self.nodelist.render(context)
File "/usr/local/lib/python2.7/dist-packages/django/template/base.py" in render
823. bit = self.render_node(node, context)
File "/usr/local/lib/python2.7/dist-packages/django/template/base.py" in render_node
837. return node.render(context)
File "/usr/local/lib/python2.7/dist-packages/django/template/loader_tags.py" in render
123. return compiled_parent._render(context)
File "/usr/local/lib/python2.7/dist-packages/django/template/base.py" in _render
134. return self.nodelist.render(context)
File "/usr/local/lib/python2.7/dist-packages/django/template/base.py" in render
823. bit = self.render_node(node, context)
File "/usr/local/lib/python2.7/dist-packages/django/template/base.py" in render_node
837. return node.render(context)
File "/usr/local/lib/python2.7/dist-packages/django/template/loader_tags.py" in render
62. result = block.nodelist.render(context)
File "/usr/local/lib/python2.7/dist-packages/django/template/base.py" in render
823. bit = self.render_node(node, context)
File "/usr/local/lib/python2.7/dist-packages/django/template/base.py" in render_node
837. return node.render(context)
File "/usr/local/lib/python2.7/dist-packages/django/template/loader_tags.py" in render
62. result = block.nodelist.render(context)
File "/usr/local/lib/python2.7/dist-packages/django/template/base.py" in render
823. bit = self.render_node(node, context)
File "/usr/local/lib/python2.7/dist-packages/django/template/base.py" in render_node
837. return node.render(context)
File "/usr/local/lib/python2.7/dist-packages/django/template/defaulttags.py" in render
192. nodelist.append(node.render(context))
File "/usr/local/lib/python2.7/dist-packages/django/template/loader_tags.py" in render
155. return self.render_template(self.template, context)
File "/usr/local/lib/python2.7/dist-packages/django/template/loader_tags.py" in render_template
137. output = template.render(context)
File "/usr/local/lib/python2.7/dist-packages/django/template/base.py" in render
140. return self._render(context)
File "/usr/local/lib/python2.7/dist-packages/django/template/base.py" in _render
134. return self.nodelist.render(context)
File "/usr/local/lib/python2.7/dist-packages/django/template/base.py" in render
823. bit = self.render_node(node, context)
File "/usr/local/lib/python2.7/dist-packages/django/template/base.py" in render_node
837. return node.render(context)
File "/usr/local/lib/python2.7/dist-packages/django/template/defaulttags.py" in render
192. nodelist.append(node.render(context))
File "/usr/local/lib/python2.7/dist-packages/django/template/defaulttags.py" in render
192. nodelist.append(node.render(context))
File "/usr/local/lib/python2.7/dist-packages/django/template/defaulttags.py" in render
281. return nodelist.render(context)
File "/usr/local/lib/python2.7/dist-packages/django/template/base.py" in render
823. bit = self.render_node(node, context)
File "/usr/local/lib/python2.7/dist-packages/django/template/base.py" in render_node
837. return node.render(context)
File "/usr/local/lib/python2.7/dist-packages/django/template/defaulttags.py" in render
281. return nodelist.render(context)
File "/usr/local/lib/python2.7/dist-packages/django/template/base.py" in render
823. bit = self.render_node(node, context)
File "/usr/local/lib/python2.7/dist-packages/django/template/base.py" in render_node
837. return node.render(context)
File "/usr/local/lib/python2.7/dist-packages/django/template/base.py" in render
880. return _render_value_in_context(output, context)
File "/usr/local/lib/python2.7/dist-packages/django/template/base.py" in _render_value_in_context
858. value = force_unicode(value)
File "/usr/local/lib/python2.7/dist-packages/django/utils/encoding.py" in force_unicode
71. s = unicode(s)
File "/usr/local/lib/python2.7/dist-packages/django/forms/forms.py" in __unicode__
411. return self.as_widget()
File "/usr/local/lib/python2.7/dist-packages/django/forms/forms.py" in as_widget
458. return widget.render(name, self.value(), attrs=attrs)
File "/usr/local/lib/python2.7/dist-packages/django_admin_enhancer-0.1.2-py2.7.egg/admin_enhancer/widgets.py" in render
61. return mark_safe(render_to_string('admin_enhancer/related-widget-wrapper.html', context))
File "/usr/local/lib/python2.7/dist-packages/django/template/loader.py" in render_to_string
169. t = get_template(template_name)
File "/usr/local/lib/python2.7/dist-packages/django/template/loader.py" in get_template
145. template, origin = find_template(template_name)
File "/usr/local/lib/python2.7/dist-packages/django/template/loader.py" in find_template
138. raise TemplateDoesNotExist(name)
Exception Type: TemplateDoesNotExist at /admin/locales/plotconfiguration/add/
Exception Value: admin_enhancer/related-widget-wrapper.html
The Edition and Deletion popup don't close when I do the same steps which you explain it and when I try to run the test project and I use python 2.7 and Django 1.3.
Hi,
I have modified EnhancedAdminMixin to have the possibility to disable only the delete link or all links (delete, modify, add). Below my modification:
class EnhancedAdminMixin(object):
enhance_exclude = ()
db_field_exclude = ()
can_delete = False
filtered_multiple_wrapper = FilteredSelectMultipleWrapper
related_widget_wrapper = RelatedFieldWidgetWrapper
def formfield_for_dbfield(self, db_field, **kwargs):
formfield = super(EnhancedAdminMixin, self).formfield_for_dbfield(db_field, **kwargs)
if (formfield and db_field.name not in self.enhance_exclude and
isinstance(formfield.widget, admin.widgets.RelatedFieldWidgetWrapper)):
request = kwargs.pop('request', None)
related_modeladmin = self.admin_site._registry.get(db_field.rel.to)
if related_modeladmin:
can_change_related = related_modeladmin.has_change_permission(request)
can_delete_related = related_modeladmin.has_delete_permission(request)
if isinstance(formfield.widget.widget, admin.widgets.FilteredSelectMultiple):
formfield.widget.widget = self.filtered_multiple_wrapper.wrap(formfield.widget.widget)
if db_field.name in self.db_field_exclude:
formfield.widget.can_add_related = False
can_change_related = False
can_delete_related = False
else:
formfield.widget.can_add_related = True
can_change_related = True
can_delete_related = self.can_delete
widget = self.related_widget_wrapper.wrap(formfield.widget,
can_change_related,
can_delete_related)
formfield.widget = widget
return formfield
What do you think about these features?
bye
Robert
This may be a stretch; but is there any way for this app to work well with autocomplete_light (https://github.com/yourlabs/django-autocomplete-light)? That app replaces the drop-down list with an incremental look-up approach. I think it would make more sense if django-admin-enhancer could be disabled for those specific fields being used by the enhancer.
There is a collision with the django-polymorphic app.
There is an error when a model is edited that is polymorphic and has the EnhancedModelAdminMixin.
A reverse url for the change form cannot be found in widgets.py line 29.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.