kopia lustrzana https://github.com/wagtail/wagtail
rodzic
e77da0a1a1
commit
c606e3f722
|
@ -225,7 +225,7 @@ class StreamField(Field):
|
||||||
foreign objects are nested objects with id and meta as attributes.
|
foreign objects are nested objects with id and meta as attributes.
|
||||||
"""
|
"""
|
||||||
def to_representation(self, value):
|
def to_representation(self, value):
|
||||||
return value.stream_block.get_prep_value(value)
|
return value.stream_block.get_api_representation(value, self.context)
|
||||||
|
|
||||||
|
|
||||||
class TagsField(Field):
|
class TagsField(Field):
|
||||||
|
|
|
@ -1025,6 +1025,18 @@ class TestPageDetailWithStreamField(TestCase):
|
||||||
# ForeignKeys in a StreamField shouldn't be translated into dictionary representation
|
# ForeignKeys in a StreamField shouldn't be translated into dictionary representation
|
||||||
self.assertEqual(content['body'], [{'type': 'image', 'value': 1}])
|
self.assertEqual(content['body'], [{'type': 'image', 'value': 1}])
|
||||||
|
|
||||||
|
def test_image_block_with_custom_get_api_representation(self):
|
||||||
|
stream_page = self.make_stream_page('[{"type": "image", "value": 1}]')
|
||||||
|
|
||||||
|
response_url = '{}?extended=1'.format(
|
||||||
|
reverse('wagtailapi_v2:pages:detail', args=(stream_page.id, ))
|
||||||
|
)
|
||||||
|
response = self.client.get(response_url)
|
||||||
|
content = json.loads(response.content.decode('utf-8'))
|
||||||
|
|
||||||
|
# the custom get_api_representation returns a dict of id and title for the image
|
||||||
|
self.assertEqual(content['body'], [{'type': 'image', 'value': {'id': 1, 'title': 'A missing image'}}])
|
||||||
|
|
||||||
|
|
||||||
@override_settings(
|
@override_settings(
|
||||||
WAGTAILFRONTENDCACHE={
|
WAGTAILFRONTENDCACHE={
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.10.4 on 2016-12-20 10:57
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
import wagtail.tests.testapp.models
|
||||||
|
import wagtail.wagtailcore.blocks
|
||||||
|
import wagtail.wagtailcore.fields
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('tests', '0012_panelsettings_tabbedsettings'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='streampage',
|
||||||
|
name='body',
|
||||||
|
field=wagtail.wagtailcore.fields.StreamField([('text', wagtail.wagtailcore.blocks.CharBlock()), ('rich_text', wagtail.wagtailcore.blocks.RichTextBlock()), ('image', wagtail.tests.testapp.models.ExtendedImageChooserBlock())]),
|
||||||
|
),
|
||||||
|
]
|
|
@ -638,11 +638,27 @@ class StreamModel(models.Model):
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|
||||||
|
class ExtendedImageChooserBlock(ImageChooserBlock):
|
||||||
|
"""
|
||||||
|
Example of Block with custom get_api_representation method.
|
||||||
|
If the request has an 'extended' query param, it returns a dict of id and title,
|
||||||
|
otherwise, it returns the default value.
|
||||||
|
"""
|
||||||
|
def get_api_representation(self, value, context=None):
|
||||||
|
image_id = super(ExtendedImageChooserBlock, self).get_api_representation(value, context=context)
|
||||||
|
if 'request' in context and context['request'].query_params.get('extended', False):
|
||||||
|
return {
|
||||||
|
'id': image_id,
|
||||||
|
'title': value.title
|
||||||
|
}
|
||||||
|
return image_id
|
||||||
|
|
||||||
|
|
||||||
class StreamPage(Page):
|
class StreamPage(Page):
|
||||||
body = StreamField([
|
body = StreamField([
|
||||||
('text', CharBlock()),
|
('text', CharBlock()),
|
||||||
('rich_text', RichTextBlock()),
|
('rich_text', RichTextBlock()),
|
||||||
('image', ImageChooserBlock()),
|
('image', ExtendedImageChooserBlock()),
|
||||||
])
|
])
|
||||||
|
|
||||||
api_fields = ('body',)
|
api_fields = ('body',)
|
||||||
|
|
|
@ -257,6 +257,12 @@ class Block(six.with_metaclass(BaseBlock, object)):
|
||||||
|
|
||||||
return mark_safe(render_to_string(template, new_context))
|
return mark_safe(render_to_string(template, new_context))
|
||||||
|
|
||||||
|
def get_api_representation(self, value, context=None):
|
||||||
|
"""
|
||||||
|
Can be used to customise the API response and defaults to the value returned by get_prep_value.
|
||||||
|
"""
|
||||||
|
return self.get_prep_value(value)
|
||||||
|
|
||||||
def render_basic(self, value, context=None):
|
def render_basic(self, value, context=None):
|
||||||
"""
|
"""
|
||||||
Return a text rendering of 'value', suitable for display on templates. render() will fall back on
|
Return a text rendering of 'value', suitable for display on templates. render() will fall back on
|
||||||
|
|
|
@ -143,6 +143,13 @@ class ListBlock(Block):
|
||||||
for item in value
|
for item in value
|
||||||
]
|
]
|
||||||
|
|
||||||
|
def get_api_representation(self, value, context=None):
|
||||||
|
# recursively call get_api_representation on children and return as a list
|
||||||
|
return [
|
||||||
|
self.child_block.get_api_representation(item, context=context)
|
||||||
|
for item in value
|
||||||
|
]
|
||||||
|
|
||||||
def render_basic(self, value, context=None):
|
def render_basic(self, value, context=None):
|
||||||
children = format_html_join(
|
children = format_html_join(
|
||||||
'\n', '<li>{0}</li>',
|
'\n', '<li>{0}</li>',
|
||||||
|
|
|
@ -211,6 +211,16 @@ class BaseStreamBlock(Block):
|
||||||
for child in value # child is a BoundBlock instance
|
for child in value # child is a BoundBlock instance
|
||||||
]
|
]
|
||||||
|
|
||||||
|
def get_api_representation(self, value, context=None):
|
||||||
|
if value is None:
|
||||||
|
# treat None as identical to an empty stream
|
||||||
|
return []
|
||||||
|
|
||||||
|
return [
|
||||||
|
{'type': child.block.name, 'value': child.block.get_api_representation(child.value, context=context)}
|
||||||
|
for child in value # child is a BoundBlock instance
|
||||||
|
]
|
||||||
|
|
||||||
def render_basic(self, value, context=None):
|
def render_basic(self, value, context=None):
|
||||||
return format_html_join(
|
return format_html_join(
|
||||||
'\n', '<div class="block-{1}">{0}</div>',
|
'\n', '<div class="block-{1}">{0}</div>',
|
||||||
|
|
|
@ -138,6 +138,13 @@ class BaseStructBlock(Block):
|
||||||
for name, val in value.items()
|
for name, val in value.items()
|
||||||
])
|
])
|
||||||
|
|
||||||
|
def get_api_representation(self, value, context=None):
|
||||||
|
# recursively call get_api_representation on children and return as a plain dict
|
||||||
|
return dict([
|
||||||
|
(name, self.child_blocks[name].get_api_representation(val, context=context))
|
||||||
|
for name, val in value.items()
|
||||||
|
])
|
||||||
|
|
||||||
def get_searchable_content(self, value):
|
def get_searchable_content(self, value):
|
||||||
content = []
|
content = []
|
||||||
|
|
||||||
|
|
|
@ -961,6 +961,39 @@ class TestStructBlock(SimpleTestCase):
|
||||||
|
|
||||||
self.assertHTMLEqual(html, expected_html)
|
self.assertHTMLEqual(html, expected_html)
|
||||||
|
|
||||||
|
def test_get_api_representation_calls_same_method_on_fields_with_context(self):
|
||||||
|
"""
|
||||||
|
The get_api_representation method of a StructBlock should invoke
|
||||||
|
the block's get_api_representation method on each field and the
|
||||||
|
context should be passed on.
|
||||||
|
"""
|
||||||
|
class ContextBlock(blocks.CharBlock):
|
||||||
|
def get_api_representation(self, value, context=None):
|
||||||
|
return context[value]
|
||||||
|
|
||||||
|
class AuthorBlock(blocks.StructBlock):
|
||||||
|
language = ContextBlock()
|
||||||
|
author = ContextBlock()
|
||||||
|
|
||||||
|
block = AuthorBlock()
|
||||||
|
api_representation = block.get_api_representation(
|
||||||
|
{
|
||||||
|
'language': 'en',
|
||||||
|
'author': 'wagtail',
|
||||||
|
},
|
||||||
|
context={
|
||||||
|
'en': 'English',
|
||||||
|
'wagtail': 'Wagtail!'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertDictEqual(
|
||||||
|
api_representation, {
|
||||||
|
'language': 'English',
|
||||||
|
'author': 'Wagtail!'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
def test_render_unknown_field(self):
|
def test_render_unknown_field(self):
|
||||||
class LinkBlock(blocks.StructBlock):
|
class LinkBlock(blocks.StructBlock):
|
||||||
title = blocks.CharBlock()
|
title = blocks.CharBlock()
|
||||||
|
@ -1334,6 +1367,28 @@ class TestListBlock(unittest.TestCase):
|
||||||
self.assertIn('<h1 lang="fr">Bonjour le monde!</h1>', html)
|
self.assertIn('<h1 lang="fr">Bonjour le monde!</h1>', html)
|
||||||
self.assertIn('<h1 lang="fr">Au revoir le monde!</h1>', html)
|
self.assertIn('<h1 lang="fr">Au revoir le monde!</h1>', html)
|
||||||
|
|
||||||
|
def test_get_api_representation_calls_same_method_on_children_with_context(self):
|
||||||
|
"""
|
||||||
|
The get_api_representation method of a ListBlock should invoke
|
||||||
|
the block's get_api_representation method on each child and
|
||||||
|
the context should be passed on.
|
||||||
|
"""
|
||||||
|
class ContextBlock(blocks.CharBlock):
|
||||||
|
def get_api_representation(self, value, context=None):
|
||||||
|
return context[value]
|
||||||
|
|
||||||
|
block = blocks.ListBlock(
|
||||||
|
ContextBlock()
|
||||||
|
)
|
||||||
|
api_representation = block.get_api_representation(["en", "fr"], context={
|
||||||
|
'en': 'Hello world!',
|
||||||
|
'fr': 'Bonjour le monde!'
|
||||||
|
})
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
api_representation, ['Hello world!', 'Bonjour le monde!']
|
||||||
|
)
|
||||||
|
|
||||||
def render_form(self):
|
def render_form(self):
|
||||||
class LinkBlock(blocks.StructBlock):
|
class LinkBlock(blocks.StructBlock):
|
||||||
title = blocks.CharBlock()
|
title = blocks.CharBlock()
|
||||||
|
@ -1652,6 +1707,38 @@ class TestStreamBlock(SimpleTestCase):
|
||||||
|
|
||||||
return block.render(value)
|
return block.render(value)
|
||||||
|
|
||||||
|
def test_get_api_representation_calls_same_method_on_children_with_context(self):
|
||||||
|
"""
|
||||||
|
The get_api_representation method of a StreamBlock should invoke
|
||||||
|
the block's get_api_representation method on each child and
|
||||||
|
the context should be passed on.
|
||||||
|
"""
|
||||||
|
class ContextBlock(blocks.CharBlock):
|
||||||
|
def get_api_representation(self, value, context=None):
|
||||||
|
return context[value]
|
||||||
|
|
||||||
|
block = blocks.StreamBlock([
|
||||||
|
('language', ContextBlock()),
|
||||||
|
('author', ContextBlock()),
|
||||||
|
])
|
||||||
|
api_representation = block.get_api_representation(
|
||||||
|
block.to_python([
|
||||||
|
{'type': 'language', 'value': 'en'},
|
||||||
|
{'type': 'author', 'value': 'wagtail'},
|
||||||
|
]),
|
||||||
|
context={
|
||||||
|
'en': 'English',
|
||||||
|
'wagtail': 'Wagtail!'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertListEqual(
|
||||||
|
api_representation, [
|
||||||
|
{'type': 'language', 'value': 'English'},
|
||||||
|
{'type': 'author', 'value': 'Wagtail!'},
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
def test_render(self):
|
def test_render(self):
|
||||||
html = self.render_article([
|
html = self.render_article([
|
||||||
{
|
{
|
||||||
|
|
Ładowanie…
Reference in New Issue