M src/wiki/compat.py => src/wiki/compat.py +0 -17
@@ 9,28 9,11 @@ except ImportError:
__all__ = [
- 'BuildAttrsCompat',
'get_default_engine',
'include', 'url'
]
-# Django 1.11 Widget.build_attrs has a different signature, designed for the new
-# template based rendering. The previous version was more useful for our needs,
-# so we restore that version.
-# When support for Django < 1.11 is dropped, we should look at using the
-# new template based rendering, at which point this probably won't be needed at all.
-class BuildAttrsCompat:
- def build_attrs_compat(self, extra_attrs=None, **kwargs):
- "Helper function for building an attribute dictionary."
- attrs = self.attrs.copy()
- if extra_attrs is not None:
- attrs.update(extra_attrs)
- if kwargs is not None:
- attrs.update(kwargs)
- return attrs
-
-
def get_default_engine():
"""
Django >= 2.1 Engine.get_default() behaviour
M src/wiki/editors/markitup.py => src/wiki/editors/markitup.py +10 -38
@@ 1,54 1,26 @@
from django import forms
-from django.forms.utils import flatatt
-from django.utils.encoding import force_text
-from django.utils.html import conditional_escape
-from django.utils.safestring import mark_safe
-from wiki.compat import BuildAttrsCompat
from wiki.editors.base import BaseEditor
-class MarkItUpAdminWidget(BuildAttrsCompat, forms.Widget):
-
- """A simplified more fail-safe widget for the backend"""
+class MarkItUpWidget(forms.Widget):
+ template_name = "wiki/forms/markitup.html"
def __init__(self, attrs=None):
# The 'rows' and 'cols' attributes are required for HTML correctness.
- default_attrs = {'class': 'markItUp',
- 'rows': '10', 'cols': '40', }
+ default_attrs = {
+ 'class': 'markItUp',
+ 'rows': '10',
+ 'cols': '40',
+ }
if attrs:
default_attrs.update(attrs)
super().__init__(default_attrs)
- def render(self, name, value, attrs=None, renderer=None):
- if value is None:
- value = ''
- final_attrs = self.build_attrs_compat(attrs, name=name)
- return mark_safe(
- '<textarea%s>%s</textarea>' %
- (flatatt(final_attrs),
- conditional_escape(
- force_text(value))))
+class MarkItUpAdminWidget(MarkItUpWidget):
+ """A simplified more fail-safe widget for the backend"""
-class MarkItUpWidget(BuildAttrsCompat, forms.Widget):
-
- def __init__(self, attrs=None):
- # The 'rows' and 'cols' attributes are required for HTML correctness.
- default_attrs = {'class': 'markItUp',
- 'rows': '10', 'cols': '40', }
- if attrs:
- default_attrs.update(attrs)
- super().__init__(default_attrs)
-
- def render(self, name, value, attrs=None, renderer=None):
- if value is None:
- value = ''
- final_attrs = self.build_attrs_compat(attrs, name=name)
- return mark_safe(
- '<div><textarea%s>%s</textarea></div>' %
- (flatatt(final_attrs),
- conditional_escape(
- force_text(value))))
+ template_name = "wiki/forms/markitup-admin.html"
class MarkItUp(BaseEditor):
M src/wiki/forms.py => src/wiki/forms.py +15 -56
@@ 1,7 1,6 @@
import random
import string
from datetime import timedelta
-from itertools import chain
from django import forms
from django.apps import apps
@@ 9,17 8,13 @@ from django.contrib.auth import get_user_model
from django.contrib.auth.forms import UserCreationForm
from django.core import validators
from django.core.validators import RegexValidator
-from django.forms.utils import flatatt
from django.forms.widgets import HiddenInput
from django.shortcuts import get_object_or_404
from django.urls import Resolver404, resolve
from django.utils import timezone
-from django.utils.encoding import force_text
-from django.utils.html import conditional_escape, escape
from django.utils.safestring import mark_safe
from django.utils.translation import gettext, gettext_lazy as _, pgettext_lazy
from wiki import models
-from wiki.compat import BuildAttrsCompat
from wiki.conf import settings
from wiki.core import permissions
from wiki.core.diff import simple_merge
@@ 285,12 280,15 @@ class EditForm(forms.Form, SpamProtectionMixin):
return cd
-class SelectWidgetBootstrap(BuildAttrsCompat, forms.Select):
+class SelectWidgetBootstrap(forms.Select):
"""
http://twitter.github.com/bootstrap/components.html#buttonDropdowns
Needs bootstrap and jquery
"""
+ template_name = "wiki/forms/select.html"
+ option_template_name = "wiki/forms/select_option.html"
+
def __init__(self, attrs={}, choices=(), disabled=False):
attrs['class'] = 'btn-group pull-left btn-group-form'
self.disabled = disabled
@@ 302,51 300,12 @@ class SelectWidgetBootstrap(BuildAttrsCompat, forms.Select):
if k not in ('attrs', 'disabled'):
self.noscript_widget.__setattr__(k, value)
- def render(self, name, value, attrs=None, choices=()):
- if value is None:
- value = ''
- final_attrs = self.build_attrs_compat(attrs, name=name)
- output = [
- """<div%(attrs)s>"""
- """ <button class="btn btn-group-label%(disabled)s" type="button">%(label)s</button>"""
- """ <button class="btn btn-default dropdown-toggle%(disabled)s" type="button" data-toggle="dropdown">"""
- """ <span class="caret"></span>"""
- """ </button>"""
- """ <ul class="dropdown-menu">"""
- """ %(options)s"""
- """ </ul>"""
- """ <input type="hidden" name="%(name)s" value="" class="btn-group-value" />"""
- """</div>"""
- """<noscript>%(noscript)s</noscript>""" %
- {'attrs': flatatt(final_attrs),
- 'options': self.render_options(choices, [value]),
- 'label': _('Select an option'),
- 'name': name, 'disabled': ' disabled' if self.disabled else '',
- 'noscript': self.noscript_widget.render(name, value, {})}]
- return mark_safe('\n'.join(output))
-
- def render_option(self, selected_choices, option_value, option_label):
- option_value = force_text(option_value)
- selected_html = (
- option_value in selected_choices) and ' selected="selected"' or ''
- return '<li><a href="javascript:void(0)" data-value="%s"%s>%s</a></li>' % (
- escape(option_value), selected_html,
- conditional_escape(force_text(option_label)))
-
- def render_options(self, choices, selected_choices):
- # Normalize to strings.
- selected_choices = set([force_text(v) for v in selected_choices])
- output = []
- for option_value, option_label in chain(self.choices, choices):
- if isinstance(option_label, (list, tuple)):
- output.append(
- '<li class="divider" label="%s"></li>' %
- escape(force_text(option_value)))
- for option in option_label:
- output.append(self.render_option(selected_choices, *option))
- else:
- output.append(self.render_option(selected_choices, option_value, option_label))
- return '\n'.join(output)
+ def get_context(self, name, value, attrs):
+ context = super().get_context(name, value, attrs)
+ context['label'] = _('Select an option')
+ context['noscript'] = self.noscript_widget.render(name, value, {})
+ context['disabled'] = ' disabled' if self.disabled else ''
+ return context
class Media(forms.Media):
@@ 354,16 313,16 @@ class SelectWidgetBootstrap(BuildAttrsCompat, forms.Select):
class TextInputPrepend(forms.TextInput):
+ template_name = "wiki/forms/text.html"
def __init__(self, *args, **kwargs):
self.prepend = kwargs.pop('prepend', "")
super().__init__(*args, **kwargs)
- def render(self, *args, **kwargs):
- html = super().render(*args, **kwargs)
- return mark_safe(
- '<div class="input-group"><span class="input-group-addon">%s</span>%s</div>' %
- (self.prepend, html))
+ def get_context(self, name, value, attrs):
+ context = super().get_context(name, value, attrs)
+ context['prepend'] = mark_safe(self.prepend)
+ return context
class CreateForm(forms.Form, SpamProtectionMixin):
A src/wiki/templates/wiki/forms/markitup-admin.html => src/wiki/templates/wiki/forms/markitup-admin.html +1 -0
@@ 0,0 1,1 @@
+<textarea name="{{ widget.name }}"{% include "django/forms/widgets/attrs.html" %}>{% if widget.value %}{{ widget.value }}{% endif %}</textarea>
A src/wiki/templates/wiki/forms/markitup.html => src/wiki/templates/wiki/forms/markitup.html +1 -0
@@ 0,0 1,1 @@
+<div><textarea name="{{ widget.name }}"{% include "django/forms/widgets/attrs.html" %}>{% if widget.value %}{{ widget.value }}{% endif %}</textarea></div>
A src/wiki/templates/wiki/forms/select.html => src/wiki/templates/wiki/forms/select.html +15 -0
@@ 0,0 1,15 @@
+<div{% include "django/forms/widgets/attrs.html" %}>
+ <button class="btn btn-group-label{{ disabled }}" type="button">{{ label }}</button>
+ <button class="btn btn-default dropdown-toggle{{ disabled }}" type="button" data-toggle="dropdown">
+ <span class="caret"></span>
+ </button>
+ <ul class="dropdown-menu">{% for group_name, group_choices, group_index in widget.optgroups %}
+ {% if group_name %}<li class="divider" label="{{ group_name }}"></li>{% endif %}
+ {% for option in group_choices %}
+ {% include option.template_name with widget=option %}
+ {% endfor %}
+ {% endfor %}
+ </ul>
+ <input type="hidden" name="{{ widget.name }}" value="" class="btn-group-value" />
+</div>
+<noscript>{{ noscript }}</noscript>
A src/wiki/templates/wiki/forms/select_option.html => src/wiki/templates/wiki/forms/select_option.html +1 -0
@@ 0,0 1,1 @@
+<li><a href="javascript:void(0)" data-value="{{ widget.value|stringformat:'s' }}"{% include "django/forms/widgets/attrs.html" %}>{{ widget.label }}</a></li>
A src/wiki/templates/wiki/forms/text.html => src/wiki/templates/wiki/forms/text.html +1 -0
@@ 0,0 1,1 @@
+<div class="input-group"><span class="input-group-addon">{{ prepend }}</span>{% include "django/forms/widgets/input.html" %}</div>