from django.apps import apps from django.conf import settings from django.utils.translation import activate, ugettext as _ import datetime from jinja2 import Template import locale import os from ishtar_common.version import get_version from ishtar_common.models_common import Address, GeoItem # TODO: à traduire TYPES = { 'IntegerField': "Entier", 'PositiveIntegerField': "Entier positif", 'FloatField': "Nombre à virgule", 'TextField': "Texte", 'CharField': "Chaîne de caractères", 'DateField': "Date", 'DateTimeField': "Date/heure", 'EmailField': "Courriel", 'NullBooleanField': "Booléen", 'BooleanField': "Booléen", 'ImageField': "Image", 'FileField': "Fichier", 'URLField': "Adresse web", 'PointField': "Point", 'LineStringField': "Ligne", 'MultiPolygonField': "Multi-polygones", 'MultiPointField': "Multi-points", 'MultiLineStringField': "Multi-lignes" } TEMPLATES = ( ("fr/source/_templates/annexe-tech-3-variables-gen.jinja", "fr/source/annexe-tech-3-variables-gen.rst", "fr-fr"), ) TPL_MODEL = { "fr-fr": """{% for field_name, desc in fields %} - **{{field_name}}** : {{desc}}{% endfor %}""" } EXCLUDED = [ "id", "data", "history_creator", "history_m2m", "history_modifier", "imports", "last_modified", "lock_user", "locked", "search_vector", "uuid", "need_update", "merge_key", "merge_candidate", "merge_exclusion", "archived", "ishtaruser", "profiles", "properties", "relation_bitmap_image_above", "relation_bitmap_image_below", "relation_dot", "relation_dot_above", "relation_dot_below", "relation_image_above", "relation_image_below", "auto_external_id", "history_date", "created", "cached_x", "cached_y", "cached_z", "import_key", "departement", ] EXCLUDED += ["parcel_owner"] # temporary MODELS = { "ishtar_common": ["person", "organization", "author", "document", "geovectordata", "area", "town"], "archaeological_operations": ["operation", "archaeologicalsite", "parcel", "administrativeact"], "archaeological_files": ["file"], "archaeological_context_records": ["dating", "contextrecord"], "archaeological_finds": ["basefind", "find", "treatment", "treatmentfile"], "archaeological_warehouse": ["warehouse", "container"], } lc = settings.LANGUAGE_CODE lc = lc[:2] + "_" + lc[-2:].upper() + ".UTF-8" locale.setlocale(locale.LC_ALL, lc) MESSAGES = { 'value_only_message': str(_("Field not available for imports")) } MESSAGES = { 'value_only_message': "Champ non disponible pour les imports" } def get_values(tpl_model, model, excluded, model_types, messages): fields = {} related_fields = {} for field in model._meta.get_fields(): if field.name in excluded: continue help_text = "" if getattr(field, "help_text", None): h = field.help_text if callable(h): h = h() help_text = str(h) if getattr(field, "related_model", None): key = field.name + "__" rel = field.related_model related_fields[key] = "*" if getattr(field, "multiple", False): related_fields[key] += "→ " + str( rel._meta.verbose_name_plural) else: related_fields[key] += "→ " + str( rel._meta.verbose_name) extra = "" if not getattr(field, "verbose_name", None) and \ hasattr(field.remote_field, "verbose_name"): extra = str(field.remote_field.verbose_name).lower() if hasattr(rel, "get_documentation_string"): if extra: extra += " - " related_fields[key] += "* ({}{})".format( extra, rel.get_documentation_string()) elif extra: related_fields[key] += " ({})*".format(extra) else: related_fields[key] += "*" if getattr(field, "verbose_name", None): related_fields[key] += " - " + str(field.verbose_name) + " " if help_text: if related_fields[key]: related_fields[key] += " - " related_fields[key] += help_text + " " elif getattr(field, "verbose_name", None): type_desc = "" field_classes = [field.__class__.__name__] + [ sub.__name__ for sub in field.__class__.__subclasses__()] for model_class in model_types: if model_class in field_classes: type_desc = model_types[model_class] break if getattr(field, "max_length", None): type_desc += " ({})".format(field.max_length) if not type_desc: print("Missing type", field.name, field_classes) fields[field.name] = str(field.verbose_name) if type_desc: fields[field.name] = "*{}* - {}".format( type_desc, fields[field.name]) if help_text: fields[field.name] += " - " + help_text else: print("No doc for the field: " + field.name) if hasattr(model, "DOC_VALUES"): for k, v in model.DOC_VALUES: fields[k] = "{} - **{}**".format( v, messages["value_only_message"]) fields = sorted(list(fields.items()) + list(related_fields.items())) return { "fields": [k for k, __ in fields], "render": tpl_model.render({"fields": fields}) } for template_name, template_name_dest, language in TEMPLATES: tpl_model = Template(TPL_MODEL[language]) activate(language) render_dct = dict((app, {}) for app in MODELS) render_dct['current_date'] = datetime.date.today().strftime("%Y-%m-%d") render_dct['version'] = get_version() excluded = EXCLUDED[:] address_values = get_values(tpl_model, Address, excluded=excluded, model_types=TYPES, messages=MESSAGES) render_dct["ishtar_common"]["address"] = address_values excluded += address_values["fields"] geo_values = get_values(tpl_model, GeoItem, excluded=excluded, model_types=TYPES, messages=MESSAGES) #render_dct["ishtar_common"]["geoitem"] = geo_values excluded += geo_values["fields"] for app_name in MODELS: # print([m._meta.model_name # for m in apps.get_app_config(app_name).get_models()]) for model_name in MODELS[app_name]: model = apps.get_app_config(app_name).get_model(model_name) render_dct[app_name][model_name] = get_values( tpl_model, model, excluded, TYPES, messages=MESSAGES) template_name = os.path.abspath( settings.ROOT_PATH + "../docs/" + template_name) template_name_dest = os.path.abspath( settings.ROOT_PATH + "../docs/" + template_name_dest) with open(template_name, "r") as tpl: rendered = Template(tpl.read()) with open(template_name_dest, "w") as tpl_dest: tpl_dest.write(rendered.render(render_dct))