12๐
Thanks to the comments for a change in 1.4. My implementation here wasnโt thread safe either, so it really should have been deleted.
Since get_formsets
is passed the object and calls get_inline_instances
, we can modify both functions to act on the object.
This should work:
class ThingAdmin(admin.ModelAdmin):
model = Thing
inlines = [inline]
other_set_of_inlines = [other_inline]
def get_inline_instances(self, request, obj=None):
# ^^^ this is new
inline_instances = []
if obj.date > datetime.date(2012, 1, 1):
inlines = self.inlines
else:
inlines = self.other_set_of_inlines
for inline_class in inlines:
inline = inline_class(self.model, self.admin_site)
if request:
if not (inline.has_add_permission(request) or
inline.has_change_permission(request) or
inline.has_delete_permission(request)):
continue
if not inline.has_add_permission(request):
inline.max_num = 0
inline_instances.append(inline)
return inline_instances
def get_formsets(self, request, obj=None):
for inline in self.get_inline_instances(request, obj):
# ^^^^^ this is new
yield inline.get_formset(request, obj)
10๐
As of Django 2.2.2 (current latest version as of this writing), I would use the solution provided earlier by @aggieNick02, which is to override get_inline_instances
shown below.
class ThingAdmin(models.ModelAdmin):
inlines = [MyInline,]
def get_inline_instances(self, request, obj=None):
if not obj or obj.date >= today: return []
return super(ThingAdmin, self).get_inline_instances(request, obj)
Iโm posting this new answer because as of April 17th, 2019 in this commit, it looks like the future recommended way to do this would be to instead override the get_inlines
method. So in later versions, the solution to this could look like the code below, which allows you to specify different sets of inlines and use them based on a condition.
class ThingAdmin(admin.ModelAdmin):
model = Thing
inlines = [inline]
other_set_of_inlines = [other_inline]
def get_inlines(self, request, obj):
if obj.date > datetime.date(2012, 1, 1):
return self.inlines
else:
return self.other_set_of_inlines
- How to throttle Django error emails
- Python venv not creating virtual environment
- Django: how to change values for nullbooleanfield in a modelform?
7๐
You can use (django 3.0+) get_inlines method. All you have to do is override the method and define your logic,
class ThingInline(admin.StackedInline):
""" inline needs to be returned """
models = ThingModel
class ThingAdmin(admin.ModelAdmin):
model = Thing
inlines = []
def get_inlines(self, request, obj):
if obj.date < today: # the date
return [ThingInline]
# or else
return []
Update:
Going through this approach I faced this issue so instead of using the above mentioned approach samething can be done by overidding change_view()
method,
class ThingAdmin(admin.ModelAdmin):
model = Thing
inlines = []
def change_view(self, request, object_id, form_url='', extra_context=None):
self.inlines = []
try:
obj = self.model.objects.get(pk=object_id)
except self.model.DoesNotExist:
pass # ... the error msg
else:
if obj.date < today:
self.inlines = [ThingInline,]
return super(ThingAdmin, self).change_view(request, object_id, form_url, extra_context)
- How to remove Add button in Django admin, for specific Model?
- Django Newsletter App
- Django vs. Pylons
- PyCharm โ Unresolved library 'staticfiles'
4๐
I had a complex case where the solutions I tried failed in unexpected ways (problems with readonly fields in inlines). This is the most clear and failsafe way Iโve found:
class MyAdmin(admin.ModelAdmin):
def add_view(self, request, form_url='', extra_context=None):
self.inlines = [InlineA, InlineC]
return super(MyAdmin, self).add_view(request, form_url, extra_context)
def change_view(self, request, object_id, form_url='', extra_context=None):
self.inlines = [InlineB, InlineC, InlineD]
return super(MyAdmin, self).change_view(request, object_id, form_url, extra_context)
This is working in Django 1.4.x.
- Django Generic Views: When to use ListView vs. DetailView
- Executing a Django Shell Command from the Command Line
- Python: How can I override one module in a package with a modified version that lives outside the package?
- How do I hide the field label for a HiddenInput widget in Django Admin?
- In django, is aggregate(Count()) faster or better than .count() in anyway?
2๐
In recent version of Django, youโll need to override ModelAdmin.get_formsets. e.g.
class MyAdmin(admin.ModelAdmin):
def get_formsets(self, request, obj=None):
if obj:
for _ in super(MyAdmin, self).get_formsets(request, obj):
yield _
else:
for inline in self.get_specific_inlines(request):
yield inline.get_formset(request, obj)
- Django Multi-Table Inheritance VS Specifying Explicit OneToOne Relationship in Models
- Django Pandas to http response (download file)
- Django order items by two fields, but ignoring them if they're zero
- Performance, load and stress testing in Django
1๐
The best solution for this issue is already answered here. Instead of overriding get_inline_instances
override change_view
method.
def change_view(self, request, object_id, form_url='', extra_context=None):
self.inlines = []
try:
obj = self.model.objects.get(pk=object_id)
except self.model.DoesNotExist:
pass
else:
if condition:
self.inlines = [InlineClass]
return super(AdminClass, self).change_view(request, object_id, form_url, extra_context)
- How to convert request.user into a proxy auth.User class?
- Django 3.1: StreamingHttpResponse with an async generator
0๐
I had a situation where I needed to show an Inline based on the admin site that you were on for a given story.
I was able to get dynamic inlines working for Django 1.3 using the following code:
In highlights/admin.py
class HighlightInline(generic.GenericTabularInline):
model = Highlight
extra = 1
max_num = 4
fields = ('order', 'highlight')
template = 'admin/highlights/inline.html'
class HighlightAdmin(admin.ModelAdmin):
def regulate_highlight_inlines(self):
highlights_enabled = Setting.objects.get_or_default('highlights_enabled', default='')
highlight_inline_instance = HighlightInline(self.model, self.admin_site)
highlight_found = any(isinstance(x, HighlightInline) for x in self.inline_instances)
if highlights_enabled.strip().lower() == 'true':
if not highlight_found:
self.inline_instances.insert(0, highlight_inline_instance)
else:
if highlight_found:
self.inline_instances.pop(0)
print self.inline_instances
def change_view(self, request, object_id, form_url='', extra_context=None):
self.regulate_highlight_inlines()
return super(HighlightAdmin, self).change_view(request, object_id)
def add_view(self, request, form_url='', extra_context=None):
self.regulate_highlight_inlines()
return super(HighlightAdmin, self).add_view(request, form_url, extra_context)
In story/admin.py
class StoryAdmin(HighlightAdmin):
One thing to note is that Iโm not merely manipulating inline classes(HighlightInline) but rather, Iโm changing inline instances(HighlightInline(self.model, self.admin_site)). This is because django has already constructed a list of inline instances based on a list of inline classes during the initial construction of the admin class.
- Django rest framework nested viewsets and routes
- Error installing mysqlclient for python on Ubuntu 18.04
- Creating an entire web application using django admin
0๐
I think the easiest way to hack this is to call your custom funciton in get_fields
, or get_fieldsets
and so on, just set self.inlines
in a custom function.
class XXXAdmin(admin.ModelAdmin):
def set_inlines(self, request, obj):
""" hack inlines models according current request.user or obj """
self.inlines = []
if request.user.is_superuser or request.user is obj.recorder:
self.inlines = [AbcInline, ]
def get_fields(self, request, obj=None):
self.set_inlines(request, obj) # NOTICE this line
super(XXXAdmin, self).get_fields(request, obj)
- Django filter through multiple fields in a many-to-many intermediary table
- Group models in django admin
- TimeField format in Django template
- Does Django have a way to open a HTTP long poll connection?
0๐
The most turnkey way to do this now is to override and super call to get_inline_instances.
class ThingAdmin(models.ModelAdmin):
inlines = [MyInline,]
def get_inline_instances(self, request, obj=None):
unfiltered = super(ThingAdmin, self).get_inline_instances(request, obj)
#filter out the Inlines you don't want
keep_myinline = obj and obj.date < today
return [x for x in unfiltered if not isinstance(x,MyInline) or keep_myinline]
This puts MyInline in when you want it and not when you donโt. If you know the only inline you have in your class is MyInline, you can make it even simpler:
class ThingAdmin(models.ModelAdmin):
inlines = [MyInline,]
def get_inline_instances(self, request, obj=None):
if not obj or obj.date >= today:
return []
return super(ThingAdmin, self).get_inline_instances(request, obj)
- How to find out whether a model's column is a foreign key?
- Django rest auth email instead of username