mezzanine icon indicating copy to clipboard operation
mezzanine copied to clipboard

Apply Mezzanine's Dynamic inline to Django's Stacked/Generic inlines

Open nekstrom opened this issue 14 years ago • 16 comments

I'm running off of head which looks to be version 0.11. I've created a new page type that in the admin uses inlined objects in the admin. The mezzanine code removes all of the inline forms that were added but doesn't put new ones back. Nor does there seem to be a method for adding new ones. Below is my code.

models.py file

from django.conf import settings
from django.db import models
from mezzanine.core.models import RichText
from mezzanine.pages.models import Page

# Create your models here.
class TemplatedPage(Page):
    template = models.CharField(max_length=512, verbose_name="Template Name",
                                                                help_text="The name of the template to use when rendering this page.", 
                                choices=getattr(settings, "EXTENDED_PAGES_TEMPLATES", []))

    class Meta:
        verbose_name = "Templated Page"
        verbose_name_plural = "Templated Pages"

class PageSection(RichText):
    page = models.ForeignKey(TemplatedPage, related_name="sections")
    name = models.CharField(max_length=32, verbose_name="Name", help_text="Name of Page Section Content.")
    order = models.PositiveSmallIntegerField(choices=[(x,x) for x in range(50)], default=0, verbose_name="Order", help_text="If you have multiple sections with the same name this helps order them.")

    class Meta:
        verbose_name = "Page Section"
        verbose_name_plural = "Page Sections"
admin.py file

from copy import deepcopy
from django.contrib import admin
from mezzanine.pages.admin import PageAdmin
from .models import PageSection, TemplatedPage

class PageSectionInline(admin.StackedInline):
    model = PageSection
    #fields = ("order", "content")
    #extra = 2

TEMPLATED_PAGE_FIELDSETS = deepcopy(PageAdmin.fieldsets)
TEMPLATED_PAGE_FIELDSETS[0][1]['fields'].insert(2,"template")
class TemplatedPageAdmin(PageAdmin):
    inlines = (PageSectionInline,)
    fieldsets = TEMPLATED_PAGE_FIELDSETS

admin.site.register(TemplatedPage, TemplatedPageAdmin)

If the problem isn't caused by mezzanine but is instead something I've done wrong please let me know.

nekstrom avatar May 03 '11 14:05 nekstrom

The problem seems to stem from core/templates/admin/base_site.html:L194 removing the inlines without there being a way to add ones back.

nekstrom avatar May 03 '11 14:05 nekstrom

Couple of things:

Firstly just double check that it's not a particular issue with your browser - have a look at an existing record with dynamic inlines on the demo site (http://mezzanine.jupo.org/admin/forms/form/3/ user/pass: demo/demo) which is running off the same 0.11 code base. You should see a link on the right-hand side under the dynamic inlines (form fields in this case) that says "Add another". If that works for you then you can rule out it being a Mezzanine bug specific to your browser.

Secondly I believe your admin class PageSectionInline should inherit from mezzanine.core.admin.DynamicInlineAdmin - again take a look at the built-in example mezzanine.forms.models.Form which makes use of all the dynamic inline functionality, taking note of the admin classes it uses to set everything up.

Hope this helps. Let me know how you go.

stephenmcd avatar May 03 '11 20:05 stephenmcd

Yep you are right. I guess I didn't see in the documentation that it needed to inherit from mezzanine.core.admin.DynamicInlineAdmin. Once I did that it worked. Thanks for clearing that up for me.

Are there plans to make a version that inherits from StackedInline?

nekstrom avatar May 03 '11 21:05 nekstrom

Glad you got it working. I actually don't think the dynamic inlines are documented anywhere to be honest.

I hadn't planned to add a StackedInline version but that is a great idea. If you'd like to set that up I'd be happy to pull it in.

I'd imagine the DynamicInlineAdmin as it stands now would no longer inherit from Tabular inline, ad we'd end up with something like:

DynamicInlineAdmin becomes: BaseDynamicInlineAdmin(object)

then add:

TabularDynamicInlineAdmin(BaseDynamicInlineAdmin, TabularInline): pass StackedDynamicInlineAdmin(BaseDynamicInlineAdmin, StackedInline): pass

I might have gotten some of those names wrong, I didn't look them up. We'd then need to update any references to the old name - I believe it's just the form admin I referred to earlier that's using this.

What do you think?

stephenmcd avatar May 03 '11 21:05 stephenmcd

I'm under a deadline right now but I'll look at doing it once that pressure is off.

On Tue, May 3, 2011 at 3:14 PM, stephenmcd < [email protected]>wrote:

Glad you got it working. I actually don't think the dynamic inlines are documented anywhere to be honest.

I hadn't planned to add a StackedInline version but that is a great idea. If you'd like to set that up I'd be happy to pull it in.

I'd imagine the DynamicInlineAdmin as it stands now would no longer inherit from Tabular inline, ad we'd end up with something like:

DynamicInlineAdmin becomes: BaseDynamicInlineAdmin(object)

then add:

TabularDynamicInlineAdmin(BaseDynamicInlineAdmin, TabularInline): pass StackedDynamicInlineAdmin(BaseDynamicInlineAdmin, StackedInline): pass

I might have gotten some of those names wrong, I didn't look them up. We'd then need to update any references to the old name - I believe it's just the form admin I referred to earlier that's using this.

What do you think?

Reply to this email directly or view it on GitHub: https://github.com/stephenmcd/mezzanine/issues/62#comment_1096468

nekstrom avatar May 03 '11 21:05 nekstrom

No worries - I'm under the pump here too but if I get a chance before you I will do it anyway :-)

stephenmcd avatar May 03 '11 22:05 stephenmcd

Hey I checked in the initial version of this:

https://github.com/stephenmcd/mezzanine/commit/42ff3b377be5b50692eb59da14925016f7a03b86

Stacked doesn't quite work yet - some of the Javascript I have in mezzanine/core/templates/admin/base_site.html conflicts with it. If you get a chance to take this any further let me know and we can talk through it.

Cheers, Steve

stephenmcd avatar May 07 '11 07:05 stephenmcd

Not sure if this is entirely related but I have never been able to get StackedInlines to work with Mezzanine and think I finally tracked down the issue. I'm wondering if its related to this. Anyways you can view the change here: https://bitbucket.org/joshcartme/mezzanine/changeset/a9e1cfa42cdd

joshcartme avatar May 13 '11 18:05 joshcartme

Thanks Josh that's great - you've resolved the issue I mentioned in my last comment here.

So StackedDynamicInlineAdmin is partially working now as of:

https://github.com/stephenmcd/mezzanine/commit/6e75c84b2f1b31770e4406facb55db392ca88d79

Drag and drop ordering doesn't work yet so I've simply hidden the widget. More work is needed - I guess the drag and drop widget should somehow go into the header above each inline. It also doesn't work at without Grappelli installed as there's no easy way to target the stacked inlines with jQuery.

Given that I'll leave this issue open for now.

stephenmcd avatar May 14 '11 03:05 stephenmcd

The script mentioned earlier is breaking StackedInlines in a separate app for me. The insertion of extra rows through JS gets busted.

If that script is still somehow needed in Mezzanine it ought to be moved or scoped in a way that it does not conflict with other apps.

https://github.com/stephenmcd/mezzanine/blob/master/mezzanine/core/static/mezzanine/js/admin/navigation.js#L91

jonatansberg avatar Oct 31 '12 10:10 jonatansberg

I've got a couple of projects where I'd love to get jQuery ordering happening. @stephenmcd are you able to point me in the right direction and I can take a look?

nlhkabu avatar Oct 22 '13 05:10 nlhkabu

@nlh-kabu - take a look at the models in mezzanine.forms and how they're built, as well as their related admin classes. This thread will make a lot more sense with that background.

If you're simply looking for drag/drop ordering with jQuery then it already exists as per the mezzanine.forms examples, it's probably just not well documented.

stephenmcd avatar Oct 22 '13 06:10 stephenmcd

Was there ever a resolution to this? From recollection Grappelli-vanilla seems to convert admin.StackedInline into dynamic versions. I'd like to use mezzanine with some other third-party apps and don't want to have to monkey patch their code to get dynamic versions.

LegoStormtroopr avatar Aug 25 '15 05:08 LegoStormtroopr

Yep this really broke third-party apps. Watch this example:


class PersonMembershipInline(admin.TabularInline):
    model = PersonMembership
    extra = 1

class GroupAdmin(admin.ModelAdmin):
    inlines = [
        PersonMembershipInline,
    ]

class Group(models.Model):
    members = models.ManyToManyField('Person', blank=True, through='PersonMembership')

In the group admin there are TWO empty rows (instead of one), but only one works on save and TabularDynamicInlineAdmin doens't save your life too. Autocomplete fields in inlines are totally useless, they works only edit related rows.

I used the same code in grappelli and there everything works (I'm also able to add extra records dynamically).

kbytesys avatar Sep 08 '15 09:09 kbytesys

I have the same problem.

My solution is use TabularDynamicInlineAdmin from mezzanine.core.admin

abusquets avatar Sep 21 '15 12:09 abusquets

Been struggling using the drag and drop sort on stacked inlines for a while, and I was able to get the sort to save by monkeypatching dynamic_inline.js. Replaced line 41: var orderSelector = window.__grappelli_installed ? '._order input' : '.field-_order input'; with var orderSelector = '.field-_order input, ._order input'; Looks like the stacked inline isn't being classed like grappelli expects, so I just check for both.

mrjoshida avatar Apr 02 '16 04:04 mrjoshida