def finalize(self): """ """ self.flush_deferred_objects() if len(self.AFTER_LOAD_HANDLERS): logger.info( "Finalize %d after_load handlers", len(self.AFTER_LOAD_HANDLERS)) for h in self.AFTER_LOAD_HANDLERS: logger.info("Running after_load handler %s", h.__doc__) h(self) logger.info("Loaded %d objects", self.count_objects) if self.save_later: count = 0 s = '' for model, msg_objects in self.save_later.items(): for msg, objects in msg_objects.items(): if False: # detailed content of the first object s += "\n- %s %s (%d object(s), e.g. %s)" % ( full_model_name(model), msg, len(objects), obj2str(objects[0].object, force_detailed=True)) else: # pk of all objects s += "\n- %s %s (%d object(s) with primary key %s)" % ( full_model_name(model), msg, len(objects), ', '.join([unicode(o.object.pk) for o in objects])) count += len(objects) msg = "Abandoning with %d unsaved instances:%s" % (count, s) logger.warning(msg)
def sort_models(self, unsorted): sorted = [] hope = True """ 20121120 if we convert the list to a set, we gain some performance for the ``in`` tests, but we obtain a random sorting order for all independent models, making the double dump test less evident. """ #~ 20121120 unsorted = set(unsorted) while len(unsorted) and hope: hope = False guilty = dict() #~ print "hope for", [m.__name__ for m in unsorted] for model in unsorted: deps = set([f.rel.to for f in model._meta.fields if f.rel is not None and f.rel.to is not model and f.rel.to in unsorted]) #~ deps += [m for m in model._meta.parents.keys()] for m in sorted: if m in deps: deps.remove(m) if len(deps): guilty[model] = deps else: sorted.append(model) unsorted.remove(model) hope = True break #~ ok = True #~ for d in deps: #~ if d in unsorted: #~ ok = False #~ if ok: #~ sorted.append(model) #~ unsorted.remove(model) #~ hope = True #~ break #~ else: #~ guilty[model] = deps #~ print model.__name__, "depends on", [m.__name__ for m in deps] if unsorted: assert len(unsorted) == len(guilty) msg = "There are %d models with circular dependencies :\n" % len( unsorted) msg += "- " + '\n- '.join([ full_model_name(m) + ' (depends on %s)' % ", ".join([ full_model_name(d) for d in deps]) for m, deps in guilty.items()]) if False: # we don't write them to the .py file because they are # in random order which would cause false ddt to fail for ln in msg.splitlines(): self.stream.write('\n# %s' % ln) logger.info(msg) sorted.extend(unsorted) return sorted
def get_data_elem(model, name): #~ logger.info("20120202 get_data_elem %r,%r",model,name) if not name.startswith('__'): parts = name.split('__') if len(parts) > 1: """It's going to be a RemoteField """ # logger.warning("20120406 RemoteField %s in %s",name,self) #~ model = self.model from lino.ui import store field_chain = [] for n in parts: assert model is not None # ~ 20130508 model.get_default_table().get_handle() # make sure that all atomizers of those fields get created. fld = model.get_data_elem(n) if fld is None: # raise Exception("Part %s of %s got None" % (n,model)) raise Exception( "Invalid RemoteField %s.%s (no field %s in %s)" % (full_model_name(model), name, n, full_model_name(model))) # make sure that the atomizer gets created. store.get_atomizer(fld, fld.name) field_chain.append(fld) if fld.rel: model = fld.rel.to else: model = None def func(obj, ar=None): #~ if ar is None: raise Exception(20130802) #~ print '20130422',name,obj, [fld.name for fld in field_chain] try: for fld in field_chain: #~ obj = fld.value_from_object(obj) obj = fld._lino_atomizer.full_value_from_object( obj, ar) #~ for n in parts: #~ obj = getattr(obj,n) #~ print '20130422 %s --> %r', fld.name,obj return obj except Exception, e: # ~ if False: # only for debugging if True: # see 20130802 logger.exception(e) return str(e) return None return fields.RemoteField(func, name, fld)
def value2string(self, obj, field): if isinstance(field, (BabelCharField, BabelTextField)): #~ return repr([repr(x) for x in dbutils.field2args(obj,field.name)]) return repr(settings.SITE.field2args(obj, field.name)) value = field._get_val_from_obj(obj) # Protected types (i.e., primitives like None, numbers, dates, # and Decimals) are passed through as is. All other values are # converted to string first. if value is None: #~ if value is None or value is NOT_PROVIDED: return 'None' if isinstance(field, models.DateTimeField): d = value return 'dt(%d,%d,%d,%d,%d,%d)' % ( d.year, d.month, d.day, d.hour, d.minute, d.second) if isinstance(field, models.TimeField): d = value return 'time(%d,%d,%d)' % (d.hour, d.minute, d.second) if isinstance(field, models.ForeignKey) and field.rel.to is ContentType: ct = ContentType.objects.get(pk=value) return full_model_name(ct.model_class(), '_') #~ return "'"+full_model_name(ct.model_class())+"'" #~ return repr(tuple(value.app_label,value.model)) if isinstance(field, models.DateField): d = value return 'date(%d,%d,%d)' % (d.year, d.month, d.day) #~ return 'i2d(%4d%02d%02d)' % (d.year,d.month,d.day) if isinstance(value, (float, Decimal)): return repr(str(value)) if isinstance(value, (int, long)): return str(value) return repr(field.value_to_string(obj))
def fk_display(obj, value): ct = getattr(obj, self.ct_field) if ct: try: return unicode(ct.get_object_for_this_type(pk=value)) except ct.model_class().DoesNotExist: return "%s with pk %r does not exist" % ( full_model_name(ct.model_class()), value)
def add(name): for f,qs in getattr(self,name): if qs.count() > 0: lst.append('- %d %s %s rows using %s : %s' % ( qs.count(), name, full_model_name(f.model), f.name, ' '.join([str(o.pk) for o in qs])))
def __init__(self,model,**kw): fields = dict( #~ merge_from=models.ForeignKey(model,verbose_name=_("Merge...")), merge_to=models.ForeignKey(model,verbose_name=_("into...")), reason=models.CharField(_("Reason"),max_length=100) #~ notify=models.BooleanField(_("Send notifications")) ) keep_volatiles = [] #~ logger.info("20131025 MergeAction for %s",model) #~ logger.info("20130421 MergeAction for %s : _lino_ddh.fklist is %s",model,model._lino_ddh.fklist) for m,fk in model._lino_ddh.fklist: if fk.name in m.allow_cascaded_delete: fieldname = full_model_name(m,'_') if not fieldname in keep_volatiles: keep_volatiles.append(fieldname) fields[fieldname] = models.BooleanField(m._meta.verbose_name_plural,default=False) #~ logger.info("20130421 %r in %r",fk.name,m.allow_cascaded_delete) layout = dict() if len(keep_volatiles) == 0: width = 50 main = """ merge_to reason """ else: COLCOUNT = 2 width = 70 if len(keep_volatiles) > COLCOUNT: tpl = '' for i,name in enumerate(keep_volatiles): if i % COLCOUNT == 0: tpl += '\n' else: tpl += ' ' tpl += name else: tpl = ' '.join(keep_volatiles) main = """ merge_to keep_volatiles reason """ layout.update(keep_volatiles=layouts.Panel(tpl,label=_("Also reassign volatile related objects"))) layout.update(window_size=(width,'auto')) #~ from lino.mixins.mergeable import MergeAction kw.update( parameters=fields, params_layout=layouts.Panel(main,**layout)) super(MergeAction,self).__init__(**kw)
def analyze(self): self.volatiles = [] self.related = [] for m,fk in self.obj._lino_ddh.fklist: qs = m.objects.filter(**{fk.name:self.obj}) if fk.name in m.allow_cascaded_delete and not self.keep_volatiles.get(full_model_name(m,'_')): self.volatiles.append((fk,qs)) else: self.related.append((fk,qs)) self.generic_related = [] for gfk,qs in settings.SITE.get_generic_related(self.obj): if not getattr(gfk,'dont_merge',False): self.generic_related.append( (gfk,qs) )
def write_files(self): logger.info("Writing %s...", self.main_file) self.stream = open(self.main_file, 'wt') current_version = settings.SITE.version self.stream.write("""\ #!/usr/bin/env python # -*- coding: UTF-8 -*- """) self.stream.write('''\ """ This is a `Python dump <http://north.lino-framework.org>`_ created using %s. ''' % settings.SITE.using_text()) #~ self.stream.write(settings.SITE.welcome_text()) self.stream.write(''' """ from __future__ import unicode_literals import logging logger = logging.getLogger('%s') import os ''' % __name__) if False: self.stream.write(""" os.environ['DJANGO_SETTINGS_MODULE'] = '%s' """ % settings.SETTINGS_MODULE) self.stream.write('SOURCE_VERSION = %r\n' % str(current_version)) self.stream.write(''' from decimal import Decimal from datetime import datetime as dt from datetime import time,date from django.conf import settings from django.contrib.contenttypes.models import ContentType from north.dpy import create_mti_child from north.dpy import DpyLoader from north.dbutils import resolve_model def new_content_type_id(m): if m is None: return m ct = ContentType.objects.get_for_model(m) if ct is None: return None return ct.pk ''') s = ','.join([ '%s=values[%d]' % (lng.name, lng.index) for lng in settings.SITE.languages]) self.stream.write(''' def bv2kw(fieldname, values): """ Needed if `Site.languages` changed between dumpdata and loaddata """ return settings.SITE.babelkw(fieldname, %s) ''' % s) self.models = [m for m in sorted_models_list() if not issubclass(m, (ContentType, Session))] for model in self.models: self.stream.write('%s = resolve_model("%s")\n' % ( full_model_name(model, '_'), full_model_name(model))) self.stream.write('\n') self.models = self.sort_models(self.models) self.stream.write('\n') for model in self.models: fields = [f for f, m in model._meta.get_fields_with_model() if m is None] for f in fields: if getattr(f, 'auto_now_add', False): raise Exception("%s.%s.auto_now_add is True : values will be lost!" % ( full_model_name(model), f.name)) #~ fields = model._meta.local_fields #~ fields = [f for f in model._meta.fields if f.serialize] #~ fields = [f for f in model._meta.local_fields if f.serialize] self.stream.write('def create_%s(%s):\n' % ( model._meta.db_table, ', '.join([ f.attname for f in fields if not getattr(f, '_lino_babel_field', False)]))) if model._meta.parents: if len(model._meta.parents) != 1: msg = "%s : model._meta.parents is %r" % ( model, model._meta.parents) raise Exception(msg) pm, pf = model._meta.parents.items()[0] child_fields = [f for f in fields if f != pf] if child_fields: attrs = ',' + ','.join([ '%s=%s' % (f.attname, f.attname) for f in child_fields]) else: attrs = '' #~ self.stream.write(' return insert_child(%s.objects.get(pk=%s),%s%s)\n' % ( #~ full_model_name(pm,'_'),pf.attname,full_model_name(model,'_'),attrs)) self.stream.write(' return create_mti_child(%s,%s,%s%s)\n' % ( full_model_name(pm, '_'), pf.attname, full_model_name(model, '_'), attrs)) else: self.stream.write(" kw = dict()\n") for f in fields: if getattr(f, '_lino_babel_field', False): continue elif isinstance(f, (BabelCharField, BabelTextField)): self.stream.write( ' if %s is not None: kw.update(bv2kw(%r,%s))\n' % ( f.attname, f.attname, f.attname)) else: if isinstance(f, models.DecimalField): self.stream.write( ' if %s is not None: %s = Decimal(%s)\n' % ( f.attname, f.attname, f.attname)) elif isinstance(f, models.ForeignKey) and f.rel.to is ContentType: #~ self.stream.write( #~ ' %s = ContentType.objects.get_for_model(%s).pk\n' % ( #~ f.attname,f.attname)) self.stream.write( ' %s = new_content_type_id(%s)\n' % ( f.attname, f.attname)) self.stream.write( ' kw.update(%s=%s)\n' % (f.attname, f.attname)) self.stream.write(' return %s(**kw)\n\n' % full_model_name(model, '_')) self.stream.write('\n') #~ used_models = set() self.stream.write(""" def main(): loader = DpyLoader(globals()) from django.core.management import call_command # call_command('initdb', interactive=False) call_command('initdb') os.chdir(os.path.dirname(__file__)) loader.initialize() """) for model in self.models: filename = '%s.py' % model._meta.db_table filename = os.path.join(self.output_dir, filename) logger.info("Writing %s...", filename) stream = file(filename, 'wt') stream.write('# -*- coding: UTF-8 -*-\n') qs = model.objects.all() stream.write( 'logger.info("Loading %d objects to table %s...")\n' % ( qs.count(), model._meta.db_table)) fields = [ f for f, m in model._meta.get_fields_with_model() if m is None] fields = [ f for f in fields if not getattr(f, '_lino_babel_field', False)] stream.write( "# fields: %s\n" % ', '.join( [f.name for f in fields])) for obj in qs: self.count_objects += 1 #~ used_models.add(model) stream.write('loader.save(create_%s(%s))\n' % ( obj._meta.db_table, ','.join([self.value2string(obj, f) for f in fields]))) stream.write('\n') stream.write('loader.flush_deferred_objects()\n') stream.close() #~ self.stream.write('\nfilename = os.path.join(os.path.dirname(__file__),"%s.py")\n' % ) self.stream.write(' execfile("%s.py")\n' % model._meta.db_table) self.stream.write( ' loader.finalize()\n') # self.stream.write( # ' logger.info("Loaded %d objects",loader.count_objects)\n') self.stream.write(""" if __name__ == '__main__': main() """) #~ self.stream.write('\nsettings.SITE.load_from_file(globals())\n') self.stream.close()
def serialize(self, queryset, **options): self.options = options self.stream = options.get("stream", StringIO()) self.selected_fields = options.get("fields") self.use_natural_keys = options.get("use_natural_keys", False) if self.write_preamble: current_version = settings.SITE.version if '+' in current_version: logger.warning( "Dumpdata from intermediate version %s" % current_version) self.stream.write('# -*- coding: UTF-8 -*-\n') self.stream.write('''\ """ This is a `Python dump <http://north.lino-framework.org>`_ created using %s. ''' % settings.SITE.using_text()) #~ self.stream.write(settings.SITE.welcome_text()) self.stream.write(''' """ from __future__ import unicode_literals ''') self.stream.write('SOURCE_VERSION = %r\n' % str(current_version)) self.stream.write('from decimal import Decimal\n') self.stream.write('from datetime import datetime as dt\n') self.stream.write('from datetime import time,date\n') #~ self.stream.write('from north import dbutils\n') self.stream.write('from north.dpy import create_mti_child\n') self.stream.write('from north.dbutils import resolve_model\n') self.stream.write( 'from django.contrib.contenttypes.models import ContentType\n') self.stream.write('from django.conf import settings\n') self.stream.write(''' def new_content_type_id(m): if m is None: return m # if not fmn: return None # m = resolve_model(fmn) ct = ContentType.objects.get_for_model(m) if ct is None: return None return ct.pk ''') #~ s = ','.join([ #~ '%s=values[%d]' % (k,i) #~ for i,k in enumerate(settings.SITE.AVAILABLE_LANGUAGES)]) s = ','.join([ '%s=values[%d]' % (lng.name, lng.index) for lng in settings.SITE.languages]) self.stream.write(''' def bv2kw(fieldname,values): """ Needed if `Site.languages` changed between dumpdata and loaddata """ return settings.SITE.babelkw(fieldname,%s) ''' % s) #~ model = queryset.model if self.models is None: self.models = sorted_models_list() # models.get_models() if self.write_preamble: for model in self.models: self.stream.write('%s = resolve_model("%s")\n' % ( full_model_name(model, '_'), full_model_name(model))) self.stream.write('\n') for model in self.models: fields = [f for f, m in model._meta.get_fields_with_model() if m is None] for f in fields: if getattr(f, 'auto_now_add', False): raise Exception("%s.%s.auto_now_add is True : values will be lost!" % ( full_model_name(model), f.name)) #~ fields = model._meta.local_fields #~ fields = [f for f in model._meta.fields if f.serialize] #~ fields = [f for f in model._meta.local_fields if f.serialize] self.stream.write('def create_%s(%s):\n' % ( model._meta.db_table, ', '.join([f.attname for f in fields if not getattr(f, '_lino_babel_field', False)]))) if model._meta.parents: if len(model._meta.parents) != 1: msg = "%s : model._meta.parents is %r" % ( model, model._meta.parents) raise Exception(msg) pm, pf = model._meta.parents.items()[0] child_fields = [f for f in fields if f != pf] if child_fields: attrs = ',' + ','.join([ '%s=%s' % (f.attname, f.attname) for f in child_fields]) else: attrs = '' #~ self.stream.write(' return insert_child(%s.objects.get(pk=%s),%s%s)\n' % ( #~ full_model_name(pm,'_'),pf.attname,full_model_name(model,'_'),attrs)) self.stream.write(' return create_mti_child(%s,%s,%s%s)\n' % ( full_model_name(pm, '_'), pf.attname, full_model_name(model, '_'), attrs)) else: self.stream.write(" kw = dict()\n") for f in fields: if getattr(f, '_lino_babel_field', False): continue elif isinstance(f, (dbutils.BabelCharField, dbutils.BabelTextField)): self.stream.write( ' if %s is not None: kw.update(bv2kw(%r,%s))\n' % ( f.attname, f.attname, f.attname)) else: if isinstance(f, models.DecimalField): self.stream.write( ' if %s is not None: %s = Decimal(%s)\n' % ( f.attname, f.attname, f.attname)) elif isinstance(f, models.ForeignKey) and f.rel.to is ContentType: #~ self.stream.write( #~ ' %s = ContentType.objects.get_for_model(%s).pk\n' % ( #~ f.attname,f.attname)) self.stream.write( ' %s = new_content_type_id(%s)\n' % ( f.attname, f.attname)) self.stream.write( ' kw.update(%s=%s)\n' % (f.attname, f.attname)) self.stream.write(' return %s(**kw)\n\n' % full_model_name(model, '_')) #~ self.start_serialization() self.stream.write('\n') model = None all_models = [] for obj in queryset: if isinstance(obj, ContentType): continue if isinstance(obj, Session): continue #~ if isinstance(obj,Permission): continue if obj.__class__ != model: model = obj.__class__ if model in all_models: raise Exception("%s instances weren't grouped!" % model) all_models.append(model) self.stream.write('\ndef %s_objects():\n' % model._meta.db_table) fields = [f for f, m in model._meta.get_fields_with_model() if m is None] fields = [ f for f in fields if not getattr(f, '_lino_babel_field', False)] self.stream.write(' yield create_%s(%s)\n' % ( obj._meta.db_table, ','.join([self.value2string(obj, f) for f in fields]))) self.stream.write('\n\ndef objects():\n') all_models = self.sort_models(all_models) for model in all_models: #~ self.stream.write(' for o in %s_objects(): yield o\n' % model._meta.db_table) self.stream.write(' yield %s_objects()\n' % model._meta.db_table)
def model_name(m): return settings.SITE.userdocs_prefix + full_model_name(m).lower()
def get_rst(self): #~ from actordoc import get_actor_description #~ from django.conf import settings #~ from djangosite.dbutils import set_language with translation.override(self.language): level, cls = resolve_name(self.content[0]) if isinstance(cls, models.Field): fld = cls s = '' name = str(fld.model) + '.' + fld.name title = force_unicode(fld.verbose_name).strip() s += "\n.. index::\n single: " s += unicode(_('%(field)s (field in %(model)s)') % dict( field=title, model=model_ref(fld.model))) s += '\n\n' s += rstgen.header(level, _("%s (field)") % title) if len(self.content) > 1: s += '\n'.join(self.content[1:]) s += '\n\n' return s if isinstance(cls, Plugin): s = '' title = unicode(cls.verbose_name) s += "\n.. index::\n single: " s += unicode(_('%s (app)') % title) s += '\n\n.. _' + name + ':\n' s += '\n' s += rstgen.header(level, _("%s (app)") % title) return s if not isinstance(cls, type): raise Exception("%s is not an actor." % self.content[0]) if issubclass(cls, models.Model): model = cls s = '' name = model_name(model).lower() title = force_unicode(model._meta.verbose_name) s += "\n.. index::\n single: " s += unicode(_('%(model)s (model in %(app)s)') % dict( model=title, app=model._meta.app_label)) s += '\n\n' s += '\n\n.. _' + name + ':\n' s += '\n' s += rstgen.header(level, _("%s (model)") % title) s += '\n' s += '\n:Internal name: ``%s``\n' % full_model_name(cls) s += '\n:Implemented by: %s\n' % typeref(cls) s += '\n' if len(self.content) > 1: s += '\n'.join(self.content[1:]) s += '\n\n' model_reports = [ r for r in dbtables.master_reports if r.model is cls] model_reports += [r for r in dbtables.slave_reports if r.model is cls] s += rstgen.boldheader(_("Views on %s") % cls._meta.verbose_name) s += actors_overview_ul(model_reports) s += rstgen.boldheader(_("Fields in %s") % cls._meta.verbose_name) s += fields_ul(cls._meta.fields) action_list = cls._lino_default_table.get_actions() action_list = [ ba for ba in action_list if not isinstance(ba.action, IGNORED_ACTIONS)] if action_list: s += '\n' s += rstgen.boldheader(_("Actions on %s") % cls._meta.verbose_name) s += actions_ul(action_list) slave_tables = getattr(cls, '_lino_slaves', {}).values() if slave_tables: s += rstgen.boldheader(_("Tables referring to %s") % cls._meta.verbose_name) s += actors_overview_ul(slave_tables) return s if issubclass(cls, actors.Actor): title = force_unicode(cls.label or cls.title) indextext = _('%(actor)s (view in %(app)s)') % dict( actor=title, app=cls.app_label) name = actor_name(cls) #~ if name == 'welfare.reception.waitingvisitors': #~ self.debug = True #~ print(20130907, name) self.index_entries.append(('single', indextext, name, '')) #~ self.add_ref_target(name,name) s = '' s += '\n\n.. _%s:\n\n' % name s += rstgen.header(level, _("%s (view)") % title) s += '\n:Internal name: ``%s`` (%s)\n' % (cls, typeref(cls)) if len(self.content) > 1: s += '\n'.join(self.content[1:]) s += '\n\n' s += '\n\n' s += get_actor_description(cls) s += '\n\n' return s raise Exception("Cannot handle actor %r." % cls)
def get_rst(self): #~ from actordoc import get_actor_description #~ from django.conf import settings #~ from djangosite.dbutils import set_language with translation.override(self.state.document.settings.env.config.language): #~ lng = self.state.document.settings.env.config.language #~ set_language(lng) level, cls = resolve_name(self.content[0]) if isinstance(cls,models.Field): fld = cls s = '' name = str(fld.model)+'.'+fld.name title = force_unicode(fld.verbose_name).strip() s += "\n.. index::\n single: " s += unicode(_('%s (field in "%s")') % (title,fld.model)) s += '\n\n' s += rstgen.header(level,_("The **%s** field") % title) if len(self.content) > 1: s += '\n'.join(self.content[1:]) s += '\n\n' return s if isinstance(cls,dd.__class__): # it's a module (an app) s = '' name = app_name(cls) app = getattr(cls,'App',None) if app is None: title = name else: title = unicode(app.verbose_name) s += "\n.. index::\n single: " s += unicode(_('%s (app)') % title) s += '\n\n.. _'+ name + ':\n' s += '\n' s += rstgen.header(level,_("The %s app") % title) return s if not isinstance(cls,type): raise Exception("%s is not an actor." % self.content[0]) if issubclass(cls,models.Model): model = cls #~ if full_model_name(cls) == 'newcomers.Broker': #~ self.debug = True #~ self.add_model_index_entry(cls) s = '' name = model_name(model).lower() title = force_unicode(model._meta.verbose_name) s += "\n.. index::\n single: " s += unicode(_('%s (model in app "%s")') % (title,model._meta.app_label)) s += '\n\n' #~ title = unicode(cls._meta.verbose_name) #~ indextext = _('%s (%s)') % (full_model_name(cls),title) #~ name = model_name(cls) #~ self.index_entries.append(('single', indextext, name, '')) #~ self.add_ref_target(name,name) s += '\n\n.. _'+ name + ':\n' s += '\n' s += rstgen.header(level,_("The %s model") % title) #~ print(s) #~ s += rstgen.header(3,_('%s (%s)') % (title,full_model_name(cls))) s += '\n' s += '\n:Internal name: ``%s``\n' % full_model_name(cls) s += '\n:Implemented by: %s\n' % typeref(cls) s += '\n' if len(self.content) > 1: s += '\n'.join(self.content[1:]) s += '\n\n' model_reports = [r for r in dbtables.master_reports if r.model is cls] model_reports += [r for r in dbtables.slave_reports if r.model is cls] #~ s += rstgen.boldheader(_("Tables on a %s") % cls._meta.verbose_name) s += rstgen.boldheader(_("Views on %s") % cls._meta.verbose_name) s += actors_overview_ul(model_reports) s += rstgen.boldheader(_("Fields in %s") % cls._meta.verbose_name) s += fields_ul(cls._meta.fields) action_list = cls._lino_default_table.get_actions() #~ action_list = [ba for ba in action_list if ba.action.sort_index >= 30] action_list = [ba for ba in action_list if not isinstance(ba.action,IGNORED_ACTIONS)] if action_list: s += '\n' s += rstgen.boldheader(_("Actions on %s") % cls._meta.verbose_name) s += actions_ul(action_list) slave_tables = getattr(cls,'_lino_slaves',{}).values() if slave_tables: s += rstgen.boldheader(_("Tables referring to %s") % cls._meta.verbose_name) #~ for tb in slave_tables: #~ s += '\n.. _'+ settings.SITE.userdocs_prefix + str(tb) + ':\n' #~ s += '\n' #~ s += rstgen.header(4,_("Slave tables of %s") % cls._meta.verbose_name) #~ s += "\n\n**%s**\n\n" % _("Tables referring to %s") % cls._meta.verbose_name s += actors_overview_ul(slave_tables) #~ if model_reports: #~ s += '\nMaster tables: %s\n' % rptlist(model_reports) #~ if slave_tables: #~ s += '\nSlave tables: %s\n' % rptlist(slave_tables) return s if issubclass(cls,actors.Actor): title = force_unicode(cls.label or cls.title) indextext = _('%s (table in module %s)') % (title,cls.app_label) name = actor_name(cls) #~ if name == 'welfare.reception.waitingvisitors': #~ self.debug = True #~ print(20130907, name) self.index_entries.append(('single', indextext, name, '')) #~ self.add_ref_target(name,name) s = '' s += '\n\n.. _%s:\n\n' % name s += rstgen.header(level,_("The %s view") % title) s += '\n:Internal name: ``%s`` (%s)\n' % (cls,typeref(cls)) if len(self.content) > 1: s += '\n'.join(self.content[1:]) s += '\n\n' s += '\n\n' s += get_actor_description(cls) s += '\n\n' return s raise Exception("Cannot handle actor %r." % cls)