2017-01-26 13 views
0

私はWagtailとStreamFieldを使用する複雑さを学ぼうとしており、ブロックは私に頭痛を与えています。私はWagtailのドキュメントやデモアプリケーションには問題はありませんでしたが、それを超えることは外部の手助けがなければ克服できないようです。Page get_context関数を使用してStreamFieldのコンテンツをプログラムで使用する

これは私が達成しようとしている(そして失敗している)ものです。

ブログアプリケーションで遊んでいるときに、StreamFieldは、pygmentsに基づいて、構文の強調表示を含むコードブロックの追加を許可するように拡張しようとしました。ソースコードは、カスタムStructBlockクラス(当然、CodeBlock)によって管理され、BlogPageStreamField本体の一部です。 Wagtailの管理者では、コード、使用言語、適用するハイライトスタイル、行番号を表示するかどうかを入力できます。これはすべて、選択したハイライトスタイルに基づいてレンダリングテンプレート用の追加のスタイルシートを選択したいという点まで完全にうまく動作します。ここではページテンプレートにはスタイルシートが含まれる方法です:

{% block extra_css %} 
    {# This goes in the page <head> section #} 
    {% if has_code_block %} 
     {% if code_colorizer %} 
      <link rel="stylesheet" type="text/css" href="{% static 'css/highlight_{{ code_colorizer }}.css' %}"> 
     {% else %} 
      <link rel="stylesheet" type="text/css" href="{% static 'css/highlight_default.css' %}"> 
     {% endif %} 
    {% endif %} 
{% endblock %} 

CodeBlock( - と臆面もなく使用 - オンラインアイデアは感謝しています)renderメソッドでその仕事をしていません。アプリフローのこの時点では、ページコンテキストにハイライトスタイルを追加するのが遅すぎるので、オーバーライドされたdef get_context関数でページ本文フィールドを分解して、成功することはありませんでした。私は基本的なJSONテキストにアクセスできず、BlogPageクラスのクラスメンバーからのデータにアクセスできませんでした。

データがDBからロードされた直後に、テンプレートに渡される直前に、ページ・コンテキストにハイライト・スタイルを追加する方法はありますか?ここで

は、私の基本的なブログのページです:

class BlogPage(Page): 
    tags = ClusterTaggableManager(through=BlogPageTag, blank=True) 
    posted_date = models.DateField("Post date") 
    edited_date = models.DateField("Edited date", null=True, blank=True) 
    feed_image = models.ForeignKey('wagtailimages.Image', null=True, blank=True, on_delete=models.SET_NULL, related_name='+') 
    body = StreamField(BlogStreamBlock) 

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

    subpage_types = [] 

    parent_page_types = ['BlogIndexPage'] 

    @property 
    def blog_index(self): 
     return self.get_ancestors().type(BlogIndexPage).last() 

BlogPage.content_panels = [ 
    FieldPanel('title', classname='full title'), 
    FieldPanel('posted_date'), 
    FieldPanel('edited_date'), 
    StreamFieldPanel('body'), 
    InlinePanel('related_links', label="Related links"), 
] 

BlogPage.promote_panels = Page.promote_panels + [ 
    ImageChooserPanel('feed_image'), 
    FieldPanel('tags'), 
] 

これは私のBlogStreamBlockクラスの定義です:

class BlogStreamBlock(StreamBlock): 
    subtitle = CharBlock(icon='title', classname='title') 
    abstract = RichTextBlock(icon='pilcrow') 
    paragraph = RichTextBlock() 
    aligned_image = ImageBlock() 
    source_code = CodeBlock() 
    quote = QuoteBlock() 

そして最後に、ここにCodeBlockクラスです:

class CodeBlock(StructBlock): 
    LANGUAGE_CHOICES = (
     ('aspx-cs', '.NET ASP/C#'), 
     ('aspx-vb', '.NET ASP/VisualBasic'), 
     ('csharp', '.NET C#'), 
     ('fsharp', '.NET F#'), 
     ('vbnet', '.NET VisualBasic'), 
     ('ng2', 'Angular 2'), 
     ('html+ng2', 'Angular 2 Html'), 
     ('apache', 'Apache Config'), 
     ('arduino', 'Arduino Sketch'), 
     ('asm', 'Assembly'), 
     ('bash', 'Bash Shell'), 
     ('batch', 'Batch CMD File'), 
     ('c', 'C'), 
     ('cpp', 'C++'), 
     ('cmake', 'CMake'), 
     ('coffeescript', 'Coffee Script'), 
     ('css', 'CSS'), 
     # ... and many, many more ... 
     ('vhdl', 'Vhdl'), 
     ('registry', 'Windows Registry'), 
     ('xml', 'XML'), 
     ('xml+php', 'XML/PHP'), 
     ('xslt', 'XSLT'), 
     ('yaml', 'Yaml'), 
    ) 

    COLORIZER_CHOICES = (
     ('abap', 'Abap'), 
     ('algol', 'Algol'), 
     ('algol_nu', 'Algol Nu'), 
     # ... finish the list with all the highlight styles in the current version of pygments 
     ('vs', 'Vs'), 
     ('xcode', 'Xcode'), 
    ) 

    language = ChoiceBlock(choices=LANGUAGE_CHOICES, classname='full') 
    colors = ChoiceBlock(choices=COLORIZER_CHOICES, classname='full') 
    code = TextBlock() 
    line_numbers = BooleanBlock(classname='full') 

    class Meta: 
     icon = 'code' 

    def render(self, value, context=None): 
     src = value['code'].strip('\n'); 
     lang = value['language'] 
     line_nos = value['line_numbers'] 

     lexer = get_lexer_by_name(lang) 
     formatter = get_formatter_by_name('html', linenos='table' if line_nos else False, cssclass='codehilite', style='default',noclasses=False) 
     return mark_safe(highlight(src, lexer, formatter)) 
+0

'get_context'メソッドで既に試して失敗したことの詳細を教えてください。 'self.body'にアクセスすると、興味のあるデータが確実に得られるはずです。 – gasman

+0

私のエラーは、ページを公開するのを忘れてしまったので、ボディブロックをループしたときに新しいブロックは含まれていませんでした... –

答えて

0

あなたの思考プロセスを明らかにするために数時間の睡眠がどのように役立つかは驚くべきことです!あなたの時間を無駄にして申し訳ありません。

あなたのページを管理者のエディタに保存するだけでは不十分です!あなたはそれを公開しなければなりません!

ガスマンが彼のコメントで提案したように、をBlogPageに上書きすると、bodyのクラスメンバーに直接アクセスできます。そこで私は、ループ要素の上に、自分のblock_typeをチェックし、そのような彼らのサブ要素にアクセスすることができます。

def get_context(self, request, *args, **kwargs): 
    context = super(BlogPage, self).get_context(request) 
    if self.body and len(self.body) > 0: 
     for block in self.body: 
      if block.block_type == 'source_code': 
       context['has_code_block'] = True 
       context['code_colorizer'] = block.value['colors'] if block.value['colors'] else 'default' 
    return context 

これは、CSSスタイルシートは、常にページのソースコードのブロックがある場合に利用可能であることを確認してくださいます。

ここでは、上のコードで他の目立つエラーに対処しましょう。スタイルシートを設定するためのテンプレートコードが投稿されたときに機能しません。何それは実際にする必要があるが、次のされ

<link rel="stylesheet" type="text/css" href="/static/css/highlight_%7B%7B%20code_colorizer%20%7D%7D.css"> 

{% block extra_css %} 
    {% if has_code_block %} 
     {% if code_colorizer %} 
      {% with 'css/highlight_'|add:code_colorizer|add:'.css' as colorizer_choice %} 
       <link rel="stylesheet" type="text/css" href="{% static colorizer_choice %}"> 
      {% endwith %} 
     {% else %} 
      <link rel="stylesheet" type="text/css" href="{% static 'css/highlight_default.css' %}"> 
     {% endif %} 
    {% endif %} 
{% endblock %} 

実際には、場合get_context関数は常に、「デフォルト」カラー表示機能が設定されますので、何それが生成することのようないくつかのURLエスケープ文字でありますユーザが1つを選択しない場合は、{% if code_colorizer %}チェックとその{% else %}ブランチを完全に削除できます。

このコードを使用するユーザーは、異なる構文の強調表示スタイルを使用して同じページに複数のコードブロックを配置すると、期待どおりに機能しないことに注意してください。つまり、ページクラスには最後のコードブロックの選択されたスタイルシートのみが含まれます。各コードブロックで選択されている場合は、すべての異なるCSSファイルを追加できますが、ハイライト表示が同じCSSクラス名を使用しているため、HTMLファイル内の複数のスタイルを使用しても機能しません。もちろん、pygments APIを使用して、それぞれのハイライトスタイル(renderファンクションのCodeBlock)の特定のクラスを含む同封の<div></div>タグを生成し、対応するCSSファイルを編集して各エレメントに同じクラスを追加することができますこの質問の範囲を超えています。

関連する問題