dynamicweb/cms/models/fields.py

102 lines
3.6 KiB
Python
Raw Normal View History

from itertools import chain
from django.contrib.contenttypes.fields import GenericRelation
from django.db import models
from cms.forms.fields import PageSelectFormField
from cms.models.placeholdermodel import Placeholder
class PageField(models.ForeignKey):
"""
This is a foreign key field to the :class:`cms.models.pagemodel.Page` model
that defaults to the :class:`~cms.forms.fields.PageSelectFormField` form
field when rendered in forms. It has the same API as the
:class:`django:django.db.models.ForeignKey` but does not require
the ``othermodel`` argument.
"""
default_form_class = PageSelectFormField
def __init__(self, **kwargs):
# We hard-code the `to` argument for ForeignKey.__init__
# since a PageField can only be a ForeignKey to a Page
kwargs['to'] = 'cms.Page'
kwargs['on_delete'] = models.CASCADE
super().__init__(**kwargs)
def formfield(self, **kwargs):
defaults = {
'form_class': self.default_form_class,
}
defaults.update(kwargs)
return super().formfield(**defaults)
class PlaceholderField(models.ForeignKey):
"""
.. warning::
This field is for django CMS versions below 4 only. It may only be used inside migrations.
The ``PlaceholderField`` has been replaced by the :class:`~cms.models.fields.PlaceholderRelationField`,
the built-in migrations will automatically take care of the replacement.
See documentation of :class:`~cms.models.fields.PlaceholderRelationField` for how to replace the code.
"""
system_check_removed_details = {
"msg": (
"PlaceholderField is for django CMS versions below 4 only. It may only be used inside migrations."
),
"hint": "Use PlaceholderRelationField instead.",
"id": "cms.E001",
}
def __init__(self, slotname, *args, **kwargs):
kwargs.update({'null': True}) # always allow Null
kwargs.update({'editable': False}) # never allow edits in admin
# We hard-code the `to` argument for ForeignKey.__init__
# since a PlaceholderField can only be a ForeignKey to a Placeholder
self.slotname = slotname
kwargs['to'] = 'cms.Placeholder'
kwargs['on_delete'] = models.CASCADE
super().__init__(**kwargs)
def deconstruct(self):
name, path, args, kwargs = super().deconstruct()
kwargs['slotname'] = self.slotname
return name, path, args, kwargs
class PlaceholderRelationField(GenericRelation):
""":class:`~django.contrib.contenttypes.fields.GenericForeignKey` to placeholders.
If you create a model which contains placeholders you first create the ``PlaceHolderRelationField``::
from cms.utils.placeholder import get_placeholder_from_slot
class Post(models.Model):
...
placeholders = PlaceholderRelationField() # Generic relation
@cached_property
def content(self):
return get_placeholder_from_slot(self.placeholders, "content") # A specific placeholder
"""
default_checks = []
def __init__(self, checks=None, **kwargs):
self._checks = checks or ()
kwargs.pop('object_id_field', None)
kwargs.pop('content_type_field', None)
super().__init__(
Placeholder,
object_id_field='object_id',
content_type_field='content_type',
**kwargs
)
@property
def checks(self):
return chain(self.default_checks, self._checks)
def run_checks(self, placeholder, user):
return all(check_(placeholder, user) for check_ in self.checks)