Django's built-in link to edit model
I know this problem has been asked several times, but as Django develops with a new version, I will ask the question again:
I am using User model (Django User, not my models.py) and create another foreign key model for the user.
models.py
:
class Plan(models.Model):
user = models.ForeignKey(User)
I can just render each one Plan
to my user by doing this in admin.py
:
class PlanInline(admin.TabularInline):
model = Plan
extra = 0
class MyUserAdmin(UserAdmin):
ordering = ('-date_joined', 'username')
inlines = [PlanInline,]
admin.site.unregister(User)
admin.site.register(User, MyUserAdmin)
But things will get more complicated soon. I want to add a model with a foreign key pointing to Plan
:
class Order(models.Model):
plan = models.ForeignKey('Plan')
And I want to see everything Orders
for everyone Plan
. As of today, it is not possible to inline inline strings in Django Admin (without editing the HTML, which I want to avoid):
User
-> Plan 1
-> Order 1
-> Order 2
-> Plan 2
-> Order 3
So my idea is to display in LINKUser Admin
only for each plan, to the edit page and put as inline:Plans
Orders
class OrderInline(admin.TabularInline):
model = Order
extra = 0
class PlanAdmin(admin.ModelAdmin):
inlines = [OrderInline,]
admin.site.register(Plan, PlanAdmin)
The question is, how do I display the plan link in my User Admin?
class MyUserAdmin(UserAdmin):
ordering = ('-date_joined', 'username')
??? LINK ????
I've seen several solutions on this topic: Django InlineModelAdmin: Show a partially inline model and a link to the full model , but they are a little messy as they force us to write HTML and an absolute path into the code.
Then I saw this ticket on Djangoproject: https://code.djangoproject.com/ticket/13163 . Seems to be exactly what I'm looking for and the ticket is "fixed". So I tried to add as in fix show_change_link = True
:
class PlanInline(admin.TabularInline):
model = Plan
extra = 0
show_change_link = True
class MyUserAdmin(UserAdmin):
ordering = ('-date_joined', 'username')
show_change_link = True
inlines = [UserProfileInline, PlanInline]
But it doesn't work (and I have no log or error).
Is there a way to do this in a clean way?
source to share
I suggest adding a custom method PlanInline
that returns a link and see if it helps. Something like this:
from django.utils.safestring import mark_safe
from django.core.urlresolvers import reverse
class PlanInline(TabularInline):
model = Plan
readonly_fields = ('change_link',)
...other options here...
def change_link(self, obj):
return mark_safe('<a href="%s">Full edit</a>' % \
reverse('admin:myapp_plan_change',
args=(obj.id,)))
Basically all we do is create a custom method that returns a link to the change page (this particular implementation has not been tested, sorry if there is any parsing error, but you get this idea) and then add it to readonly_fields as described here: https://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.readonly_fields
A few notes for the method change_link
: you need to replace "myapp" in the view name with your actual application name. The method mark_safe
simply marks the text as template engine safe to render it as html.
source to share