forked from ungleich-public/dynamicweb
clone cms with menus, make menus standalone app
This commit is contained in:
parent
1ece5ce7c7
commit
afb096b7a3
1153 changed files with 318897 additions and 37 deletions
116
cms/forms/fields.py
Normal file
116
cms/forms/fields.py
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
from django import forms
|
||||
from django.contrib.admin.widgets import RelatedFieldWidgetWrapper
|
||||
from django.core.validators import EMPTY_VALUES
|
||||
from django.forms import ChoiceField
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from cms.forms.utils import get_page_choices, get_site_choices
|
||||
from cms.forms.validators import validate_url
|
||||
from cms.forms.widgets import PageSelectWidget, PageSmartLinkWidget
|
||||
from cms.models.pagemodel import Page
|
||||
|
||||
|
||||
class PageSelectFormField(forms.MultiValueField):
|
||||
"""
|
||||
Behaves like a :class:`django.forms.ModelChoiceField` field for the
|
||||
:class:`cms.models.pagemodel.Page` model, but displays itself as a split
|
||||
field with a select drop-down for the site and one for the page. It also
|
||||
indents the page names based on what level they're on, so that the page
|
||||
select drop-down is easier to use. This takes the same arguments as
|
||||
:class:`django.forms.ModelChoiceField`.
|
||||
"""
|
||||
widget = PageSelectWidget
|
||||
default_error_messages = {
|
||||
'invalid_site': _('Select a valid site'),
|
||||
'invalid_page': _('Select a valid page'),
|
||||
}
|
||||
|
||||
def __init__(self, queryset=None, empty_label="---------", cache_choices=False,
|
||||
required=True, widget=None, to_field_name=None, limit_choices_to=None, *args, **kwargs):
|
||||
errors = self.default_error_messages.copy()
|
||||
if 'error_messages' in kwargs:
|
||||
errors.update(kwargs['error_messages'])
|
||||
self.limit_choices_to = limit_choices_to
|
||||
kwargs['required'] = required
|
||||
fields = (
|
||||
ChoiceField(choices=get_site_choices, required=False, error_messages={'invalid': errors['invalid_site']}),
|
||||
ChoiceField(choices=get_page_choices, required=False, error_messages={'invalid': errors['invalid_page']}),
|
||||
)
|
||||
|
||||
# Remove the unexpected blank kwarg if it's supplied,
|
||||
# causes an error where the MultiValueField doesn't expect it
|
||||
# https://github.com/django/django/commit/da79ee472d803963dc3ea81ee67767dc06068aac
|
||||
if 'blank' in kwargs:
|
||||
del kwargs['blank']
|
||||
|
||||
super().__init__(fields, *args, **kwargs)
|
||||
|
||||
def compress(self, data_list):
|
||||
if data_list:
|
||||
page_id = data_list[1]
|
||||
|
||||
if page_id in EMPTY_VALUES:
|
||||
if not self.required:
|
||||
return None
|
||||
raise forms.ValidationError(self.error_messages['invalid_page'])
|
||||
return Page.objects.get(pk=page_id)
|
||||
return None
|
||||
|
||||
def has_changed(self, initial, data):
|
||||
is_empty = data and (len(data) >= 2 and data[1] in [None, ''])
|
||||
|
||||
if isinstance(self.widget, RelatedFieldWidgetWrapper):
|
||||
self.widget.decompress = self.widget.widget.decompress
|
||||
|
||||
if is_empty and initial is None:
|
||||
# when empty data will have [u'1', u'', u''] as value
|
||||
# this will cause django to always return True because of the '1'
|
||||
# so we simply follow django's default behavior when initial is None and data is "empty"
|
||||
data = ['' for x in range(0, len(data))]
|
||||
return super().has_changed(initial, data)
|
||||
|
||||
def _has_changed(self, initial, data):
|
||||
return self.has_changed(initial, data)
|
||||
|
||||
|
||||
class PageSmartLinkField(forms.CharField):
|
||||
"""
|
||||
A field making use of ``cms.forms.widgets.PageSmartLinkWidget``.
|
||||
This field will offer you a list of matching internal pages as you type.
|
||||
You can either pick one or enter an arbitrary URL to create a non-existing entry.
|
||||
Takes a `placeholder_text` argument to define the text displayed inside the
|
||||
input before you type.
|
||||
|
||||
The widget uses an ajax request to try to find pages match. It will try to find
|
||||
case-insensitive matches amongst public and published pages on the `title`, `path`,
|
||||
`page_title`, `menu_title` fields.
|
||||
|
||||
.. note::
|
||||
|
||||
``PageSmartLinkField`` stores its value as a plain URL string, so links
|
||||
do not follow pages that are later moved or renamed. For dynamically
|
||||
linking to pages, other CMS content, or external URLs, the preferred
|
||||
approach is the ``LinkField`` provided by
|
||||
`djangocms-link <https://github.com/django-cms/djangocms-link>`_, which
|
||||
keeps references stable across moves and supports a configurable set of
|
||||
link targets.
|
||||
"""
|
||||
widget = PageSmartLinkWidget
|
||||
default_validators = [validate_url]
|
||||
|
||||
def __init__(self, max_length=None, min_length=None, placeholder_text=None,
|
||||
ajax_view=None, *args, **kwargs):
|
||||
self.placeholder_text = placeholder_text
|
||||
widget = self.widget(ajax_view=ajax_view)
|
||||
super().__init__(
|
||||
max_length=max_length, min_length=min_length, widget=widget, *args, **kwargs
|
||||
)
|
||||
|
||||
def widget_attrs(self, widget):
|
||||
attrs = super().widget_attrs(widget)
|
||||
attrs.update({'placeholder_text': self.placeholder_text})
|
||||
return attrs
|
||||
|
||||
def clean(self, value):
|
||||
value = self.to_python(value).strip()
|
||||
return super().clean(value)
|
||||
Loading…
Add table
Add a link
Reference in a new issue