2017-01-16 3 views
0

У меня есть абстрактная модель Wagtail с несколькими StreamField. Два из этих StreamField s находятся на отдельной вкладке в виде администратора, которые добавляются к edit_handler.Каков правильный способ расширения абстрактных моделей Wagtail с дополнительными полями?

class AbstractHomePage(Page): 
    body = StreamField(
     HomePageStreamBlock(), 
     default='' 
    ) 
    headingpanel = StreamField(
     HeadingPanelStreamBlock(), 
     default='' 
    ) 
    sidepanel = StreamField(
     SidePanelStreamBlock(), 
     default='' 
    ) 

    class Meta: 
     abstract = True 

    search_fields = Page.search_fields + [index.SearchField('body')] 

    content_panels = Page.content_panels + [ 
     StreamFieldPanel('body'), 
    ] 

    pagesection_panels = [ 
     StreamFieldPanel('headingpanel'), 
     StreamFieldPanel('sidepanel'), 
    ] 

    edit_handler = TabbedInterface([ 
     ObjectList(content_panels), 
     ObjectList(pagesection_panels, heading='Page sections'), 
     ObjectList(Page.promote_panels), 
     ObjectList(Page.settings_panels, classname='settings'), 
    ]) 

Я хочу расширить эту модель и добавить поле:

class Foo(AbstractHomePage): 
    extra = models.TextField() 

    Meta: 
     verbose_name='Foo' 

    content_panels = [ 
     AbstractHomePage.content_panels[0],  # title 
     FieldPanel('extra'), 
     AbstractHomePage.content_panels[-1]  # streamfield 
    ] 

При добавлении новой страницы Foo, только поля, доступные в админ-панели являются поля из AbstractHomePage. Добавленное поле не доступно, пока я не обновлять Foo «s edit_handler:

class Foo(AbstractHomePage): 
    extra = models.TextField() 

    Meta: 
     verbose_name='Foo' 

    content_panels = [ 
     AbstractHomePage.content_panels[0],  # title 
     FieldPanel('extra'), 
     AbstractHomePage.content_panels[-1]  # streamfield 
    ] 

    edit_handler = TabbedInterface([ 
     ObjectList(content_panels), 
     ObjectList(AbstractHomePage.pagesection_panels, heading='Page sections'), 
     ObjectList(Page.promote_panels), 
     ObjectList(Page.settings_panels, classname='settings'), 
    ]) 

А теперь мой вопрос: Я сделал что-то неправильно или не следовали надлежащей практике кодирования?

Если мне нужно обновить edit_handler для каждой расширяемой модели, есть ли лучший способ сделать это? Чтобы убедиться, что новые поля для моделей, расширяющих AbstractHomePage, получают явный блок «шаблона» edit_handler каждый раз, когда он чувствует себя действительно уродливым. Я рассматриваю это как серьезное нарушение принципа СУХОЙ.

ответ

4

Причина вы должны переопределить edit_handler в Foo является то, что Python оценивает определение AbstractHomePage класса сверху вниз - в точке, что он встречает строку:

ObjectList(content_panels), 

content_panels трактуется как переменная, а не свойство класса, и поэтому обработчик редактирования строится на основе списка content_panels, как он существовал в этой точке. Переопределение content_panels в подклассе не может переопределить это.

По сути, вы ищете способ отложить построение edit_handler до тех пор, пока не будет определен подкласс. Я не вижу хорошего способа сделать это напрямую, но я думаю, что вы могли бы добиться этого с небольшим рытьем в внутренности Wagtail, переопределив the Page.get_edit_handler method:

from wagtail.utils.decorators import cached_classmethod 

class AbstractHomePage(Page): 
    ... 
    @cached_classmethod 
    def get_edit_handler(cls): 
     edit_handler = TabbedInterface([ 
      ObjectList(cls.content_panels), 
      ObjectList(cls.pagesection_panels, heading='Page sections'), 
      ObjectList(cls.promote_panels), 
      ObjectList(cls.settings_panels, classname='settings'), 
     ]) 
     return edit_handler.bind_to_model(cls) 
Смежные вопросы