Exemplo n.º 1
0
class TaskListUpdateForm(Form):
    keywords = fields.CharField(
        error_messages={
            "required": "关键词不能为空!",
        },
    )
    url = fields.URLField(
        error_messages={
            "required": "网址不能为空!",
            "invalid": "网址格式不正确!"
        },
    )

    day_click_number = fields.IntegerField(
        error_messages={
            "required": "日点击次数不能为空!",
            "invalid": "日点击次数只能为整数!",
        },
    )

    search_engine = fields.CharField(
        error_messages={
            "required": "搜索引擎不能为空!",
        },
    )

    click_strategy_id = fields.CharField(
        error_messages={
            "required": "点击策略不能为空!",
        },
    )
Exemplo n.º 2
0
class AddGitForm(Form):
    title = fields.CharField(
        label="标题",
        widget=widgets.TextInput(attrs={
            "id": "person_title",
            "class": "form-control"
        }),
        error_messages={"required": "标题不能为空"},
    )
    url = fields.URLField(
        label="根URL",
        widget=widgets.URLInput(attrs={
            "id": "gitlab_url",
            "class": "form-control"
        }),
        error_messages={"required": "URL不能为空"},
    )
    person_token = fields.CharField(
        label="个人访问令牌",
        widget=widgets.TextInput(attrs={
            "id": "person_token",
            "class": "form-control"
        }),
        error_messages={"required": "个人访问令牌不能为空"},
    )
    myuser_id = fields.IntegerField(widget=widgets.HiddenInput, )
Exemplo n.º 3
0
class UrlCheck(Form):

    url = fields.URLField(required=True,
                          error_messages={
                              'required': 'url不能为空',
                              'invalid': '链接地址格式不正确'
                          })
Exemplo n.º 4
0
class SneakerForm(Form):
    title = fields.CharField(max_length=100)
    content = fields.CharField(max_length=1000,
                               widget=forms.Textarea(attrs={
                                   'rows': 15,
                                   'cols': 100
                               }))
    pic = fields.ImageField()
    sneakerReleaseDate = forms.DateField(widget=forms.TextInput(
        attrs={'class': 'datepicker'}))
    color = fields.CharField(max_length=100)
    price = fields.IntegerField()

    store = fields.CharField(max_length=100)
    storepic = fields.ImageField()
    url = fields.URLField(max_length=100)

    reseller = fields.CharField(max_length=100)
    resellerlink = fields.URLField(max_length=100)
Exemplo n.º 5
0
class StudentInfoForm(forms.ModelForm):
  """Django form for the student profile page.
  """

  class Meta:
    model = GSoCStudentInfo
    css_prefix = 'student_info'
    exclude = ['school', 'school_type', 'number_of_proposals']
    widgets = forms.choiceWidgets(GSoCStudentInfo,
        ['school_country', 'school_type', 'degree'])

  school_home_page = fields.URLField(required=True)
  clean_school_home_page =  cleaning.clean_url('school_home_page')
Exemplo n.º 6
0
class UrlAdd(Form):
    UrlName = fields.CharField(
        max_length=16,
        error_messages={'required': 'Url名称不能为空',
                        'max_length': 'Url名称不能超过16位'},
        widget=widgets.TextInput(attrs={'class': 'form-control', 'id': 'UrlName', 'placeholder': "名称",
                                        })
    )
    UrlAddress = fields.URLField(
        max_length=128,
        error_messages={'required': 'Url地址不能为空',
                        'max_length': 'Url地址不能超过128位'},
        widget=widgets.TextInput(attrs={'class': 'form-control', 'id': 'UrlAddress', 'placeholder': "http://",
                                         })
    )
Exemplo n.º 7
0
class TaskListCreateForm(Form):
    keywords = fields.CharField(
        error_messages={
            "required": "关键词不能为空!",
        },
    )
    url = fields.URLField(
        error_messages={
            "required": "网址不能为空!",
            "invalid": "网址格式不正确!"
        },
    )

    def clean_keywords(self):
        keywords = self.data['keywords']
        url = self.data['url']
        user_id = self.data["user_id"]

        if url.startswith("http://"):
            print(url)
            url = url.lstrip("http://")
        elif url.startswith("https://"):
            url = url.lstrip("https://")

        task_objs = models.Task.objects.filter(keywords=keywords, url=url, user_id=user_id)

        if task_objs:
            self.errors["keywords"] = "关键词和url 已经存在"
        else:
            return keywords

    def clean_url(self):
        url = self.data['url']
        if url.startswith("http://"):
            print(url)
            url = url.lstrip("http://")
        elif url.startswith("https://"):
            url = url.lstrip("https://")

        return url
Exemplo n.º 8
0
class ROIForm(Form):
    link = fields.URLField()
    label = fields.CharField()

    def __init__(self, user, data):
        super().__init__(data)
        self.user = user

    def save(self, commit=False):
        if commit:
            if ROILink.objects.filter(
                user=self.user,
                link=self.cleaned_data['link'],
                label=self.cleaned_data['label']
            ).count() > 0:
                raise ValidationError(
                    f"""Ссылка "{self.cleaned_data['link']}" уже зарегистрирована!"""
                )
            ROILink.objects.create(
                user=self.user,
                link=self.cleaned_data['link'],
                label=self.cleaned_data['label']
            )
Exemplo n.º 9
0
class LinkForm(ModelForm):
    """
    Form class to add fake fields for rendering the ModelAdmin's form, which later are used to
    populate the glossary of the model.
    """
    LINK_TYPE_CHOICES = (('cmspage', _("CMS Page")), ('exturl', _("External URL")), ('email', _("Mail To")),)
    link_type = fields.ChoiceField(label=_("Link"), help_text=_("Type of link"))
    cms_page = LinkSearchField(required=False, label='',
        help_text=_("An internal link onto CMS pages of this site"))
    section = fields.ChoiceField(required=False, label='',
        help_text=_("Page bookmark"))
    ext_url = fields.URLField(required=False, label='', help_text=_("Link onto external page"))
    mail_to = fields.EmailField(required=False, label='', help_text=_("Open Email program with this address"))

    class Meta:
        fields = ('glossary',)

    def __init__(self, data=None, *args, **kwargs):
        instance = kwargs.get('instance')
        default_link_type = {'type': self.LINK_TYPE_CHOICES[0][0]}
        initial = dict(instance.glossary) if instance else {'link': default_link_type}
        initial.update(kwargs.pop('initial', {}))
        initial.setdefault('link', {'type': default_link_type})
        link_type = initial['link']['type']
        self.base_fields['link_type'].choices = self.LINK_TYPE_CHOICES
        self.base_fields['link_type'].initial = link_type
        if data and data.get('shared_glossary'):
            # convert this into an optional field since it is disabled with ``shared_glossary`` set
            self.base_fields['link_type'].required = False
        set_initial_linktype = getattr(self, 'set_initial_{}'.format(link_type), None)

        # populate Select field for choosing a CMS page
        try:
            site = instance.placeholder.page.site
        except AttributeError:
            site = Site.objects.get_current()
        choices = [(p.pk, '{0} ({1})'.format(p.get_page_title(), p.get_absolute_url()))
                   for p in Page.objects.drafts().on_site(site)]
        self.base_fields['cms_page'].choices = choices

        if callable(set_initial_linktype):
            set_initial_linktype(initial)
        self._preset_section(data, initial)
        super(LinkForm, self).__init__(data, initial=initial, *args, **kwargs)

    def _preset_section(self, data, initial):
        choices = [(None, _("Page root"))]
        try:
            if data:
                cms_page = Page.objects.get(pk=data['cms_page'])
            else:
                cms_page = Page.objects.get(pk=initial['link']['pk'])
        except (KeyError, ValueError, ObjectDoesNotExist):
            pass
        else:
            CascadePage.assure_relation(cms_page)
            for key, val in cms_page.cascadepage.glossary.get('element_ids', {}).items():
                choices.append((key, val))

        self.base_fields['section'].initial = initial['link'].get('section')
        self.base_fields['section'].choices = choices

    def clean_glossary(self):
        """
        This method rectifies the behavior of JSONFormFieldBase.clean which converts
        the value of empty fields to None, although it shall be an empty dict.
        """
        glossary = self.cleaned_data['glossary']
        if glossary is None:
            glossary = {}
        return glossary

    def clean(self):
        cleaned_data = super(LinkForm, self).clean()
        if self.is_valid():
            if 'link_data' in cleaned_data:
                cleaned_data['glossary'].update(link=cleaned_data['link_data'])
                del self.cleaned_data['link_data']
            elif 'link_type' in cleaned_data:
                cleaned_data['glossary'].update(link={'type': cleaned_data['link_type']})
            else:
                cleaned_data['glossary'].update(link={'type': 'none'})
        return cleaned_data

    def clean_cms_page(self):
        if self.cleaned_data.get('link_type') == 'cmspage':
            self.cleaned_data['link_data'] = {
                'type': 'cmspage',
                'model': 'cms.Page',
                'pk': self.cleaned_data['cms_page'],
            }
            validate_link(self.cleaned_data['link_data'])
        return self.cleaned_data['cms_page']

    def clean_section(self):
        if self.cleaned_data.get('link_type') == 'cmspage':
            self.cleaned_data['link_data']['section'] = self.cleaned_data['section']
        return self.cleaned_data['section']

    def clean_ext_url(self):
        if self.cleaned_data.get('link_type') == 'exturl':
            self.cleaned_data['link_data'] = {'type': 'exturl', 'url': self.cleaned_data['ext_url']}
        return self.cleaned_data['ext_url']

    def clean_mail_to(self):
        if self.cleaned_data.get('link_type') == 'email':
            self.cleaned_data['link_data'] = {'type': 'email', 'email': self.cleaned_data['mail_to']}
        return self.cleaned_data['mail_to']

    def set_initial_none(self, initial):
        pass

    def set_initial_cmspage(self, initial):
        try:
            # check if that page still exists, otherwise return nothing
            Model = apps.get_model(*initial['link']['model'].split('.'))
            initial['cms_page'] = Model.objects.get(pk=initial['link']['pk']).pk
        except (KeyError, ObjectDoesNotExist):
            pass

    def set_initial_exturl(self, initial):
        try:
            initial['ext_url'] = initial['link']['url']
        except KeyError:
            pass

    def set_initial_email(self, initial):
        try:
            initial['mail_to'] = initial['link']['email']
        except KeyError:
            pass

    @classmethod
    def get_form_class(cls):
        """
        Hook to return a form class for editing a CMSPlugin inheriting from ``LinkPluginBase``.
        """
        return cls

    @classmethod
    def unset_required_for(cls, sharable_fields):
        """
        Fields borrowed by `SharedGlossaryAdmin` to build its temporary change form, only are
        required if they are declared in `sharable_fields`. Otherwise just deactivate them.
        """
        if 'link_content' in cls.base_fields and 'link_content' not in sharable_fields:
            cls.base_fields['link_content'].required = False
        if 'link_type' in cls.base_fields and 'link' not in sharable_fields:
            cls.base_fields['link_type'].required = False
Exemplo n.º 10
0
class LinkForm(ModelForm):
    """
    Form class to add fake fields for rendering the ModelAdmin's form, which later are used to
    populate the glossary of the model.
    """
    LINK_TYPE_CHOICES = (('cmspage', _("CMS Page")), ('exturl', _("External URL")), ('email', _("Mail To")),)
    link_type = fields.ChoiceField()
    cms_page = PageSelectFormField(required=False, label='',
        help_text=_("An internal link onto CMS pages of this site"))
    ext_url = fields.URLField(required=False, label='', help_text=_("Link onto external page"))
    mail_to = fields.EmailField(required=False, label='', help_text=_("Open Email program with this address"))

    class Meta:
        fields = ('glossary',)

    def __init__(self, raw_data=None, *args, **kwargs):
        instance = kwargs.get('instance')
        default_link_type = {'type': self.LINK_TYPE_CHOICES[0][0]}
        initial = instance and dict(instance.glossary) or {'link': default_link_type}
        initial.update(kwargs.pop('initial', {}))
        link_type = initial['link']['type']
        self.base_fields['link_type'].choices = self.LINK_TYPE_CHOICES
        self.base_fields['link_type'].initial = link_type
        if raw_data and raw_data.get('shared_glossary'):
            # convert this into an optional field since it is disabled with ``shared_glossary`` set
            self.base_fields['link_type'].required = False
        try:
            site = instance.page.site
        except AttributeError:
            site = Site.objects.get_current()
        self.base_fields['cms_page'].queryset = Page.objects.drafts().on_site(site)
        set_initial_linktype = getattr(self, 'set_initial_{0}'.format(link_type), None)
        if callable(set_initial_linktype):
            set_initial_linktype(initial)
        kwargs.update(initial=initial)
        super(LinkForm, self).__init__(raw_data, *args, **kwargs)

    def clean_glossary(self):
        """
        This method rectifies the behavior of JSONFormFieldBase.clean which
        converts the value of empty fields to None, while it shall be an empty dict.
        """
        glossary = self.cleaned_data['glossary']
        if glossary is None:
            glossary = {}
        return glossary

    def clean(self):
        cleaned_data = super(LinkForm, self).clean()
        if self.is_valid():
            if 'link_data' in cleaned_data:
                cleaned_data['glossary'].update(link=cleaned_data['link_data'])
                del self.cleaned_data['link_data']
            elif 'link_type' in cleaned_data:
                cleaned_data['glossary'].update(link={'type': cleaned_data['link_type']})
            else:
                cleaned_data['glossary'].update(link={'type': 'none'})
        return cleaned_data

    def clean_cms_page(self):
        if self.cleaned_data.get('link_type') == 'cmspage':
            self.cleaned_data['link_data'] = {
                'type': 'cmspage',
                'model': 'cms.Page',
                'pk': self.cleaned_data['cms_page'] and self.cleaned_data['cms_page'].pk or None
            }

    def clean_ext_url(self):
        if self.cleaned_data.get('link_type') == 'exturl':
            self.cleaned_data['link_data'] = {'type': 'exturl', 'url': self.cleaned_data['ext_url']}

    def clean_mail_to(self):
        if self.cleaned_data.get('link_type') == 'email':
            self.cleaned_data['link_data'] = {'type': 'email', 'email': self.cleaned_data['mail_to']}

    def set_initial_none(self, initial):
        pass

    def set_initial_cmspage(self, initial):
        try:
            Model = get_model(*initial['link']['model'].split('.'))
            initial['cms_page'] = Model.objects.get(pk=initial['link']['pk'])
        except (KeyError, ObjectDoesNotExist):
            pass

    def set_initial_exturl(self, initial):
        try:
            initial['ext_url'] = initial['link']['url']
        except KeyError:
            pass

    def set_initial_email(self, initial):
        try:
            initial['mail_to'] = initial['link']['email']
        except KeyError:
            pass

    @classmethod
    def get_form_class(cls):
        """
        Hook to return a form class for editing a CMSPlugin inheriting from ``LinkPluginBase``.
        """
        return cls

    @classmethod
    def unset_required_for(cls, sharable_fields):
        """
        Fields borrowed by `SharedGlossaryAdmin` to build its temporary change form, only are
        required if they are declared in `sharable_fields`. Otherwise just deactivate them.
        """
        if 'link' not in sharable_fields:
            cls.base_fields['link_type'].required = False
Exemplo n.º 11
0
class LinkForm(EntangledModelFormMixin):
    LINK_TYPE_CHOICES = [
        ('cmspage', _("CMS Page")),
        ('download', _("Download File")),
        ('exturl', _("External URL")),
        ('email', _("Mail To")),
    ]

    link_type = fields.ChoiceField(
        label=_("Link"),
        help_text=_("Type of link"),
    )

    cms_page = LinkSearchField(
        required=False,
        label='',
        help_text=_("An internal link onto any CMS page of this site"),
    )

    section = SectionChoiceField(
        required=False,
        label='',
        help_text=_("Page bookmark"),
    )

    download_file = ModelChoiceField(
        label='',
        queryset=FilerFileModel.objects.all(),
        widget=AdminFileWidget(ManyToOneRel(FilerFileField, FilerFileModel, 'id'), admin_site),
        required=False,
        help_text=_("An internal link onto a file from filer"),
    )

    ext_url = fields.URLField(
        required=False,
        label=_("URL"),
        help_text=_("Link onto external page"),
    )

    mail_to = fields.EmailField(
        required=False,
        label=_("Email"),
        help_text=_("Open Email program with this address"),
    )

    link_target = fields.ChoiceField(
        choices=[
            ('', _("Same Window")),
            ('_blank', _("New Window")),
            ('_parent', _("Parent Window")),
            ('_top', _("Topmost Frame")),
        ],
        label=_("Link Target"),
        widget=RadioSelect,
        required=False,
        help_text=_("Open Link in other target."),
    )

    link_title = fields.CharField(
        label=_("Title"),
        required=False,
        help_text=_("Link's Title"),
    )

    class Meta:
        entangled_fields = {'glossary': ['link_type', 'cms_page', 'section', 'download_file', 'ext_url', 'mail_to',
                                         'link_target', 'link_title']}

    def __init__(self, *args, **kwargs):
        link_type_choices = []
        if not getattr(self, 'require_link', True):
            link_type_choices.append(('', _("No Link")))
            self.declared_fields['link_type'].required = False
        link_type_choices.extend(self.LINK_TYPE_CHOICES)
        self.declared_fields['link_type'].choices = link_type_choices
        self.declared_fields['link_type'].initial = link_type_choices[0][0]
        instance = kwargs.get('instance')
        if instance and instance.glossary.get('link_type') == 'cmspage':
            self._preset_section(instance)
        super().__init__(*args, **kwargs)

    def _preset_section(self, instance):
        """
        Field ``cms_page`` may refer onto any CMS page, which itself may contain bookmarks. This method
        creates the list of bookmarks.
        """
        self.base_fields['section'].choices = self.base_fields['section'].choices[:1]
        try:
            cascade_page = get_related_object(instance.glossary, 'cms_page').cascadepage
            for key, val in cascade_page.glossary.get('element_ids', {}).items():
                self.base_fields['section'].choices.append((key, val))
        except (AttributeError, ObjectDoesNotExist):
            pass

    def clean(self):
        cleaned_data = super().clean()
        link_type = cleaned_data.get('link_type')
        error = None
        if link_type == 'cmspage':
            if cleaned_data['cms_page'] is None:
                error = ValidationError(_("CMS page to link to is missing."))
                self.add_error('cms_page', error)
        elif link_type == 'download':
            if cleaned_data['download_file'] is None:
                error = ValidationError(_("File for download is missing."))
                self.add_error('download_file', error)
        elif link_type == 'exturl':
            ext_url = cleaned_data['ext_url']
            if ext_url:
                try:
                    response = requests.head(ext_url, allow_redirects=True)
                    if response.status_code != 200:
                        error = ValidationError(_("No external page found on {url}.").format(url=ext_url))
                except Exception as exc:
                    error = ValidationError(_("Failed to connect to {url}.").format(url=ext_url))
            else:
                error = ValidationError(_("No external URL provided."))
            if error:
                self.add_error('ext_url', error)
        elif link_type == 'email':
            mail_to = cleaned_data['mail_to']
            if not re.match(r'(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$)', mail_to):
                error = ValidationError(_("'{email}' is not a valid email address.").format(email=mail_to))
                self.add_error('mail_to', error)
        if error:
            raise error
        return cleaned_data

    @classmethod
    def unset_required_for(cls, sharable_fields):
        """
        Fields borrowed by `SharedGlossaryAdmin` to build its temporary change form, only are
        required if they are declared in `sharable_fields`. Otherwise just deactivate them.
        """
        if 'link_content' in cls.base_fields and 'link_content' not in sharable_fields:
            cls.base_fields['link_content'].required = False
        if 'link_type' in cls.base_fields and 'link' not in sharable_fields:
            cls.base_fields['link_type'].required = False
Exemplo n.º 12
0
class SchoolEditModelForm(SchoolBaseForm):
    English_name = Ffields.CharField(
        required=False,
        widget=Fwidgets.TextInput(attrs={
            'class': 'form-control',
            'style': 'width: 600px'
        }))
    local_school_name = Ffields.CharField(
        required=False,
        widget=Fwidgets.TextInput(attrs={
            'class': 'form-control',
            'style': 'width: 600px'
        }))
    campus_english_name = Ffields.CharField(
        required=False,
        widget=Fwidgets.TextInput(attrs={
            'class': 'form-control',
            'style': 'width: 600px'
        }))
    website = Ffields.URLField(
        required=False,
        widget=Fwidgets.TextInput(attrs={
            'class': 'form-control',
            'style': 'width: 600px'
        }))
    school_type = Ffields.ChoiceField(required=False,
                                      choices=((1, '公立'), (2, '民办')),
                                      widget=Fwidgets.RadioSelect())
    school_layer = Ffields.ChoiceField(
        required=False,
        choices=((1, '幼儿园'), (2, '小学'), (3, '初中'), (4, '高中阶段'), (5, '九年一惯制'),
                 (6, '中等职业学校'), (7, '十二年一贯制')),
        widget=Fwidgets.RadioSelect(attrs={'class': 'school_layer'}))
    logo = Ffields.FileField(
        required=False,
        widget=Fwidgets.FileInput(attrs={'style': 'display:none'}))
    pattern = Ffields.FileField(
        required=False,
        widget=Fwidgets.FileInput(attrs={'style': 'display:none'}))

    class Meta:
        model = scmodels.SchoolInfo
        fields = ("school_name", "English_name", "local_school_name",
                  "country", "province", 'city', 'region', "campus_district",
                  "address", 'school_type', 'campus_english_name', 'website',
                  'school_layer', 'logo', 'pattern')

        widgets = {
            "abbreviation":
            Fwidgets.TextInput(attrs={
                'class': 'form-control',
                'style': 'width: 600px'
            }),
        }
        widgets.update(SchoolBaseForm.base_weight)

        error_messages = {
            "school_name": {
                "required": "请输入学校"
            },
            "province": {
                "required": "请选择省市区"
            },
            "address": {
                "required": "请输入学校地址"
            },
        }
Exemplo n.º 13
0
class RegisterForm(Form):
    """
    注册form
    """
    username = fields.CharField(
        widget=widgets.TextInput(attrs={
            'placeholder': u'用户名',
            "class": "form-control"
        }),
        max_length=18,
        min_length=6,
        required=True,
        error_messages={
            'required': "用户名不能为空",
            'max_length': "用户名长度不能超过18位",
            'min_length': "用户名长度不能少于6位",
        })
    email = fields.EmailField(widget=widgets.EmailInput(attrs={
        'placeholder': u'邮箱',
        "class": "form-control"
    }),
                              required=True,
                              error_messages={
                                  'required': "邮箱不能为空",
                              })
    url = fields.URLField(widget=widgets.URLInput(attrs={
        'placeholder': u'个人博客地址',
        "class": "form-control"
    }),
                          initial="http://",
                          required=True,
                          error_messages={'required': "个人博客地址不能为空"})
    password = fields.CharField(
        widget=widgets.TextInput(attrs={
            'placeholder': u'密码',
            "class": "form-control"
        }),
        max_length=16,
        min_length=8,
        required=True,
        error_messages={
            'required': "密码不能为空",
            'max_length': "密码长度不能超过18位",
            'min_length': "密码长度不能少于8位",
        })
    check_password = fields.CharField(
        widget=widgets.TextInput(attrs={
            'placeholder': u'请再次输入密码',
            "class": "form-control"
        }),
        max_length=16,
        min_length=8,
        required=True,
        error_messages={
            'required': "密码不能为空",
            'max_length': "密码长度不能超过18位",
            'min_length': "密码长度不能少于8位",
        })

    def clean_username(self):
        val = self.cleaned_data.get("username")
        ret = User.objects.filter(username=val)
        if not ret:
            return val
        else:
            raise ValidationError("该用户已注册")

    def clean_email(self):
        val = self.cleaned_data.get("email")
        ret = User.objects.filter(email=val)
        if not ret:
            return val
        else:
            raise ValidationError("该邮箱已被注册")

    def clean_check_password(self):
        pwd = self.cleaned_data.get("password")
        ck_pwd = self.cleaned_data.get("check_password")
        if pwd and ck_pwd:
            if pwd == ck_pwd:
                return ck_pwd
            else:
                raise ValidationError('两次密码不一致')
        else:
            raise ValidationError("请填写密码")
Exemplo n.º 14
0
class LinkForm(EntangledModelFormMixin):
    LINK_TYPE_CHOICES = [
        ('cmspage', _("CMS Page")),
        ('download', _("Download File")),
        ('exturl', _("External URL")),
        ('email', _("Mail To")),
    ]
    if PhoneNumberField:
        LINK_TYPE_CHOICES.append(('phonenumber', _("Phone number")))

    link_type = fields.ChoiceField(
        label=_("Link"),
        help_text=_("Type of link"),
    )

    cms_page = LinkSearchField(
        required=False,
        label='',
        help_text=_("An internal link onto any CMS page of this site"),
    )

    section = SectionChoiceField(
        required=False,
        label='',
        help_text=_("Page bookmark"),
    )

    download_file = ModelChoiceField(
        label='',
        queryset=FilerFileModel.objects.all(),
        widget=AdminFileWidget(ManyToOneRel(FilerFileField, FilerFileModel, 'id'), admin_site),
        required=False,
        help_text=_("An internal link onto a file from filer"),
    )

    ext_url = fields.URLField(
        required=False,
        label=_("URL"),
        help_text=_("Link onto external page"),
    )

    mail_to = fields.EmailField(
        required=False,
        label=_("Email"),
        help_text=_("Open Email program with this address"),
    )

    if PhoneNumberField:
        phone_number = PhoneNumberField(
            required=False,
            label=_("Phone Number"),
            help_text=_("International phone number, ex. +1 212 555 2368."),
        )

    link_target = fields.ChoiceField(
        choices=[
            ('', _("Same Window")),
            ('_blank', _("New Window")),
            ('_parent', _("Parent Window")),
            ('_top', _("Topmost Frame")),
        ],
        label=_("Link Target"),
        widget=RadioSelect,
        required=False,
        help_text=_("Open Link in other target."),
    )

    link_title = fields.CharField(
        label=_("Title"),
        required=False,
        help_text=_("Link's Title"),
    )

    class Meta:
        entangled_fields = {'glossary': ['link_type', 'cms_page', 'section', 'download_file', 'ext_url', 'mail_to',
                                         'link_target', 'link_title']}
        if PhoneNumberField:
            entangled_fields['glossary'].append('phone_number')

    def __init__(self, *args, **kwargs):
        link_type_choices = []
        if not getattr(self, 'require_link', True):
            link_type_choices.append(('', _("No Link")))
            self.declared_fields['link_type'].required = False
        link_type_choices.extend(self.LINK_TYPE_CHOICES)
        self.declared_fields['link_type'].choices = link_type_choices
        self.declared_fields['link_type'].initial = link_type_choices[0][0]
        instance = kwargs.get('instance')
        if instance and instance.glossary.get('link_type') == 'cmspage':
            self._preset_section(instance)
        super().__init__(*args, **kwargs)

    def _preset_section(self, instance):
        """
        Field ``cms_page`` may refer onto any CMS page, which itself may contain bookmarks. This method
        creates the list of bookmarks.
        """
        self.base_fields['section'].choices = self.base_fields['section'].choices[:1]
        try:
            cascade_page = get_related_object(instance.glossary, 'cms_page').cascadepage
            for key, val in cascade_page.glossary.get('element_ids', {}).items():
                self.base_fields['section'].choices.append((key, val))
        except (AttributeError, ObjectDoesNotExist):
            pass

    def _post_clean(self):
        super()._post_clean()
        empty_fields = [None, '']
        link_type = self.cleaned_data['glossary'].get('link_type')
        if link_type == 'cmspage':
            if self.cleaned_data['glossary'].get('cms_page', False) in empty_fields:
                error = ValidationError(_("CMS page to link to is missing."), code='required')
                self.add_error('cms_page', error)
        elif link_type == 'download':
            if self.cleaned_data['glossary'].get('download_file', False) in empty_fields:
                error = ValidationError(_("File for download is missing."), code='required')
                self.add_error('download_file', error)
        elif link_type == 'exturl':
            ext_url = self.cleaned_data['glossary'].get('ext_url', False)
            if ext_url in empty_fields:
                error = ValidationError(_("No valid URL provided."), code='required')
                self.add_error('ext_url', error)
        elif link_type == 'email':
            if self.cleaned_data['glossary'].get('mail_to', False) in empty_fields:
                error = ValidationError(_("No email address provided."), code='required')
                self.add_error('mail_to', error)
        elif link_type == 'phonenumber':
            if self.cleaned_data['glossary'].get('phone_number', False) in empty_fields:
                error = ValidationError(_("No phone number provided."), code='required')
                self.add_error('phone_number', error)

    def clean_phone_number(self):
        return str(self.cleaned_data['phone_number'])

    @classmethod
    def unset_required_for(cls, sharable_fields):
        """
        Fields borrowed by `SharedGlossaryAdmin` to build its temporary change form, only are
        required if they are declared in `sharable_fields`. Otherwise just deactivate them.
        """
        if 'link_content' in cls.base_fields and 'link_content' not in sharable_fields:
            cls.base_fields['link_content'].required = False
        if 'link_type' in cls.base_fields and 'link' not in sharable_fields:
            cls.base_fields['link_type'].required = False