diff --git a/wagtail/wagtailadmin/blocks.py b/wagtail/wagtailadmin/blocks.py
index 1042440fa..4617f701b 100644
--- a/wagtail/wagtailadmin/blocks.py
+++ b/wagtail/wagtailadmin/blocks.py
@@ -324,7 +324,7 @@ class FieldBlock(Block):
})
def value_from_datadict(self, data, files, prefix):
- return self.field.widget.value_from_datadict(data, files, prefix)
+ return self.to_python(self.field.widget.value_from_datadict(data, files, prefix))
def clean(self, value):
return self.field.clean(value)
@@ -343,42 +343,44 @@ class RichTextBlock(FieldBlock):
def render_basic(self, value):
return mark_safe('
' + expand_db_html(value) + '
')
-class PageChooserBlock(FieldBlock):
+
+class ChooserBlock(FieldBlock):
+ """Abstract superclass for fields that implement a chooser interface (page, image, snippet etc)"""
@cached_property
def field(self):
- from wagtail.wagtailcore.models import Page # TODO: allow limiting to specific page types
- from wagtail.wagtailadmin.widgets import AdminPageChooser
- return ModelChoiceField(queryset=Page.objects.all(), widget=AdminPageChooser)
+ return ModelChoiceField(queryset=self.target_model.objects.all(), widget=self.widget)
-# =======
-# Chooser
-# =======
-
-class ChooserBlock(Block):
- class Meta:
- default = None
-
- @property
- def media(self):
- return Media(js=['wagtailadmin/js/blocks/chooser.js'])
-
- def js_initializer(self):
- return "Chooser('%s')" % self.definition_prefix
-
- def render_form(self, value, prefix='', error=None):
- if self.label:
- return format_html(
- """ """,
- label=self.label, prefix=prefix
- )
+ def to_python(self, value):
+ if value is None or isinstance(value, self.target_model):
+ return value
else:
- return format_html(
- """""",
- prefix=prefix
- )
+ try:
+ return self.target_model.objects.get(pk=value)
+ except self.target_model.DoesNotExist:
+ return None
- def value_from_datadict(self, data, files, prefix):
- return 123
+ def get_prep_value(self, value):
+ if isinstance(value, self.target_model):
+ return value.id
+ else:
+ return value
+
+class PageChooserBlock(ChooserBlock):
+ @cached_property
+ def target_model(self):
+ from wagtail.wagtailcore.models import Page # TODO: allow limiting to specific page types
+ return Page
+
+ @cached_property
+ def widget(self):
+ from wagtail.wagtailadmin.widgets import AdminPageChooser
+ return AdminPageChooser
+
+ def render_basic(self, value):
+ if value:
+ return format_html('{1}', value.url, value.title)
+ else:
+ return ''
# ===========
diff --git a/wagtail/wagtailadmin/widgets.py b/wagtail/wagtailadmin/widgets.py
index 946f5987e..5c283b26e 100644
--- a/wagtail/wagtailadmin/widgets.py
+++ b/wagtail/wagtailadmin/widgets.py
@@ -53,6 +53,17 @@ class AdminChooser(WidgetWithScript, widgets.Input):
except model_class.DoesNotExist:
return None
+ def get_instance_and_id(self, model_class, value):
+ if value is None:
+ return (None, None)
+ elif isinstance(value, model_class):
+ return (value, value.pk)
+ else:
+ try:
+ return (model_class.objects.get(pk=value), value)
+ except model_class.DoesNotExist:
+ return (None, None)
+
def value_from_datadict(self, data, files, name):
# treat the empty string as None
result = super(AdminChooser, self).value_from_datadict(data, files, name)
@@ -82,10 +93,10 @@ class AdminPageChooser(AdminChooser):
self.target_content_type = content_type or ContentType.objects.get_for_model(Page)
def render_html(self, name, value, attrs):
- original_field_html = super(AdminPageChooser, self).render_html(name, value, attrs)
-
model_class = self.target_content_type.model_class()
- instance = self.get_instance(model_class, value)
+ instance, value = self.get_instance_and_id(model_class, value)
+
+ original_field_html = super(AdminPageChooser, self).render_html(name, value, attrs)
return render_to_string("wagtailadmin/widgets/page_chooser.html", {
'widget': self,
@@ -96,7 +107,11 @@ class AdminPageChooser(AdminChooser):
})
def render_js_init(self, id_, name, value):
- page = Page.objects.get(pk=value) if value else None
+ model_class = self.target_content_type.model_class()
+ if isinstance(value, model_class):
+ page = value
+ else:
+ page = self.get_instance(model_class, value)
parent = page.get_parent() if page else None
content_type = self.target_content_type
diff --git a/wagtail/wagtailimages/blocks.py b/wagtail/wagtailimages/blocks.py
new file mode 100644
index 000000000..9e06ef28d
--- /dev/null
+++ b/wagtail/wagtailimages/blocks.py
@@ -0,0 +1,20 @@
+from django.utils.functional import cached_property
+
+from wagtail.wagtailadmin.blocks import ChooserBlock
+
+class ImageChooserBlock(ChooserBlock):
+ @cached_property
+ def target_model(self):
+ from wagtail.wagtailimages.models import get_image_model
+ return get_image_model()
+
+ @cached_property
+ def widget(self):
+ from wagtail.wagtailimages.widgets import AdminImageChooser
+ return AdminImageChooser
+
+ def render_basic(self, value):
+ if value:
+ return value.get_rendition('original').img_tag()
+ else:
+ return ''
diff --git a/wagtail/wagtailimages/widgets.py b/wagtail/wagtailimages/widgets.py
index e628ed4e9..e2e104d26 100644
--- a/wagtail/wagtailimages/widgets.py
+++ b/wagtail/wagtailimages/widgets.py
@@ -19,10 +19,9 @@ class AdminImageChooser(AdminChooser):
self.image_model = get_image_model()
def render_html(self, name, value, attrs):
+ instance, value = self.get_instance_and_id(self.image_model, value)
original_field_html = super(AdminImageChooser, self).render_html(name, value, attrs)
- instance = self.get_instance(self.image_model, value)
-
return render_to_string("wagtailimages/widgets/image_chooser.html", {
'widget': self,
'original_field_html': original_field_html,