Coverage for lino/mixins/__init__.py : 68%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
# -*- coding: UTF-8 -*- # Copyright 2010-2015 Luc Saffre # License: BSD (see file COPYING for details)
by :mod:`lino.modlib`. None of them is mandatory for a Lino application.
.. autosummary:: :toctree:
duplicable dupable sequenced human periods polymorphic uploadable
Parameter panels:
- :class:`ObservedPeriod <lino.mixins.periods.ObservedPeriod>` - :class:`Yearly <lino.mixins.periods.Yearly>` - :class:`Today <lino.mixins.periods.Today>`
"""
""" Base class to anything that may be "registered" and "deregistered" (e.g. Invoices, Vouchers, Declarations, Reservations,...). "Registered" in general means "this object has been taken account of". Registered objects are not editable.
.. attribute:: state
The ChoiceList of the `state` field must have at least two items named "draft" and "registered". There may be additional states. Every state must have an extra attribute "editable".
"""
def get_registrable_fields(cls, site): """Return a list of the fields which are *disabled* when this is *registered* (i.e. `state` is not `editable`).
Usage example::
class MyModel(dd.Registrable):
@classmethod def get_registrable_fields(self, site): for f in super(MyModel, self).get_registrable_fields(site): yield f yield 'user' yield 'date'
""" #~ yield 'date'
def on_analyze(cls, site): #~ logger.info("20130128 %s %s",cls,cls._registrable_fields)
if not self.state.editable: return self._registrable_fields return super(Registrable, self).disabled_fields(ar)
"""Only rows in an editable state may be edited.
Note that `ba` is the action being requested while `ar.bound_action` is the action from which the request was started.
""" # print "20150628 Registrable.get_row_permission %s %s : %s %s" \ # % (self, ba, state.editable, ba.action.readonly) ba.action, ChangeStateAction): # if not ar.bound_action.action.readonly: if not ba.action.readonly: return False
"""Register this object. The base implementation just sets the state to "registered".
Subclasses may override this to add custom behaviour. Instead of subclassing you can also override :meth:`set_workflow_state <lino.core.model.Model.set_workflow_state>`, :meth:`before_state_change <lino.core.model.Model.before_state_change>` or :meth:`after_state_change <lino.core.model.Model.after_state_change>`.
"""
state_field = self._meta.get_field(self.workflow_state_field) target_state = state_field.choicelist.registered self.set_workflow_state(ar, state_field, target_state)
"""Deregister this object. The base implementation just sets the state to "draft".
Subclasses may override this to add custom behaviour. Instead of subclassing you can also override :meth:`set_workflow_state <lino.core.model.Model.set_workflow_state>`, :meth:`before_state_change <lino.core.model.Model.before_state_change>` or :meth:`after_state_change <lino.core.model.Model.after_state_change>`.
"""
state_field = self._meta.get_field(self.workflow_state_field) target_state = state_field.choicelist.draft self.set_workflow_state(ar, state_field, target_state)
"""Mixin for models which have a field :attr:`created`
.. attribute:: created
The timestame when this object was created.
"""
def created_natural(self, ar):
"""Adds two timestamp fields `created` and `modified`.
We don't use Django's `auto_now` and `auto_now_add` features because their deserialization (restore from a python dump) would be problematic.
"""
"""Mixin for Models that are automatically related to a "project". A project means here "the central most important thing that is used to classify most other things".
Whether an application has such a concept of "project", and which model has this privileged status, is set in :attr:`lino.core.site.Site.project_model`.
For example in :ref:`welfare` the "project" is a Client.
"""
settings.SITE.project_model, blank=True, null=True, related_name="%(app_label)s_%(class)s_set_by_project", ) else:
if settings.SITE.project_model: return self.project
#~ def summary_row(self,ui,rr,**kw): s = [ar.obj2html(self)] if settings.SITE.project_model: #~ if self.project and not dd.has_fk(rr,'project'): if self.project: #~ s += " (" + ui.obj2html(self.project) + ")" s += [" (", ar.obj2html(self.project), ")"] return s
""" When a :class:`project-related <ProjectRelated>` object controls another project-related object, then the controlled automatically inherits the `project` of its controller. """ if isinstance(controllable, ProjectRelated): controllable.project = self.project super(ProjectRelated, self).update_owned_instance(controllable)
if isinstance(self.project, settings.SITE.modules.contacts.Partner): if self.project.email: yield ('to', self.project) for r in super(ProjectRelated, self).get_mailable_recipients(): yield r
if isinstance(self.project, settings.SITE.modules.contacts.Partner): yield self.project for p in super(ProjectRelated, self).get_postable_recipients(): yield p
""" Mixin for things that have a unique `ref` field and a `get_by_ref` method. """
max_length=ref_max_length, blank=True, null=True, unique=True)
"""After duplicating we must change the :attr:`ref`.
""" if self.ref: self.ref += '(DUP)' super(Referrable, self).on_duplicate(ar, master)
try: return cls.objects.get(ref=ref) except cls.DoesNotExist: if default is models.NOT_PROVIDED: raise cls.DoesNotExist( "No %s with reference %r" % (str(cls._meta.verbose_name), ref)) return default
#~ def __unicode__(self): #~ return self.ref or unicode(_('(Root)'))
# def __unicode__(self): # return super(Referrable, self).__unicode__() + " (" + self.ref + ")" # return unicode(super(Referrable, self)) + " (" + self.ref + ")"
Printable, PrintableType, CachedPrintable, TypedPrintable, DirectPrintAction, CachedPrintAction)
|