Commit 2669b862 authored by fred.perso's avatar fred.perso

add uuid fields for main tables

parent dee7c278
......@@ -18,3 +18,4 @@ import_bdchironalpesra.sh
/core/static/img/logo_site.png
core/static/img/logo_site.png
.vscode/*
/docs/build
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
......@@ -19,8 +19,9 @@
#
import os
import sys
sys.path.insert(0, os.path.abspath('../../'))
os.environ['DJANGO_SETTINGS_MODULE'] = 'dbchiro.settings.dev'
sys.path.insert(0, os.path.abspath("../../"))
os.environ["DJANGO_SETTINGS_MODULE"] = "dbchiro.settings.dev"
# -- General configuration ------------------------------------------------
......@@ -32,42 +33,40 @@ os.environ['DJANGO_SETTINGS_MODULE'] = 'dbchiro.settings.dev'
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = ['sphinx.ext.autodoc',
'sphinx.ext.todo',
'sphinx.ext.viewcode']
extensions = ["sphinx.ext.autodoc", "sphinx.ext.todo", "sphinx.ext.viewcode"]
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
templates_path = ["_templates"]
# The suffix(es) of source filenames.
# You can specify multiple suffix as a list of string:
#
# source_suffix = ['.rst', '.md']
source_suffix = '.rst'
source_suffix = ".rst"
# The master toctree document.
master_doc = 'index'
master_doc = "index"
# General information about the project.
project = 'dbchiro[web]'
copyright = '2018, Frédéric CLOITRE'
author = 'Frédéric CLOITRE'
project = "dbchiro[web]"
copyright = "2019, Frédéric CLOITRE"
author = "Frédéric CLOITRE"
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = '20180330'
version = "20190128"
# The full version, including alpha/beta/rc tags.
release = '20180330'
release = "20190128"
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#
# This is also used if you do content translation via gettext catalogs.
# Usually you set "language" from the command line for these cases.
language = 'fr'
language = "fr"
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
......@@ -75,7 +74,7 @@ language = 'fr'
exclude_patterns = []
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
pygments_style = "sphinx"
# If true, `todo` and `todoList` produce output, else they produce nothing.
todo_include_todos = True
......@@ -86,7 +85,7 @@ todo_include_todos = True
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
html_theme = 'sphinx_rtd_theme'
html_theme = "sphinx_rtd_theme"
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
......@@ -97,7 +96,7 @@ html_theme = 'sphinx_rtd_theme'
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
html_static_path = ["_static"]
# Custom sidebar templates, must be a dictionary that maps document names
# to template names.
......@@ -105,9 +104,9 @@ html_static_path = ['_static']
# This is required for the alabaster theme
# refs: http://alabaster.readthedocs.io/en/latest/installation.html#sidebars
html_sidebars = {
'**': [
'relations.html', # needs 'show_related': True theme option to display
'searchbox.html',
"**": [
"relations.html", # needs 'show_related': True theme option to display
"searchbox.html",
]
}
......@@ -115,7 +114,7 @@ html_sidebars = {
# -- Options for HTMLHelp output ------------------------------------------
# Output file base name for HTML help builder.
htmlhelp_basename = 'dbchirowebdoc'
htmlhelp_basename = "dbchirowebdoc"
# -- Options for LaTeX output ---------------------------------------------
......@@ -124,15 +123,12 @@ latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#
# 'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#
# 'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#
# 'preamble': '',
# Latex figure (float) alignment
#
# 'figure_align': 'htbp',
......@@ -142,8 +138,13 @@ latex_elements = {
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
(master_doc, 'dbchiroweb.tex', 'dbchiro{[}web{]} Documentation',
'Frédéric CLOITRE', 'manual'),
(
master_doc,
"dbchiroweb.tex",
"dbchiro{[}web{]} Documentation",
"Frédéric CLOITRE",
"manual",
)
]
......@@ -152,8 +153,7 @@ latex_documents = [
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
(master_doc, 'dbchiroweb', 'dbchiro[web] Documentation',
[author], 1)
(master_doc, "dbchiroweb", "dbchiro[web] Documentation", [author], 1)
]
......@@ -163,10 +163,14 @@ man_pages = [
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
(master_doc, 'dbchiroweb', 'dbchiro[web] Documentation',
author, 'dbchiroweb', 'One line description of project.',
'Miscellaneous'),
(
master_doc,
"dbchiroweb",
"dbchiro[web] Documentation",
author,
"dbchiroweb",
"One line description of project.",
"Miscellaneous",
)
]
......@@ -11,6 +11,7 @@ Welcome to dbchiro[web]'s documentation!
:caption: Contents:
installation
update
Indices and tables
......
This diff is collapsed.
.. _`update`:
.. include:: update_with_uuid.rst
\ No newline at end of file
.. _`update`:
*******************************
Mise à jour avec ajout des UUID
*******************************
La version 20190128 implante la création automatique d'identifiants uniques universels (uuidv4) sur l'ensemble des tables caractérisant une donnée (observateurs, localités, sessions, observations et observations détaillées).
Pour les instances déjà existantes, cette manipulation est délicate car elle nécessite d'intervenir dans le processus de mise à jour en modifiant manuellement les fichiers de migrations.
Mise à jour des profiles utilisateurs
=====================================
Fichier automatiquement généré
.. code-block:: python3
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
import uuid
class Migration(migrations.Migration):
dependencies = [("accounts", "MA_MISE_A_JOUR_PRECEDENTE")]
operations = [
migrations.AddField(
model_name="profile",
name="uuid",
field=models.UUIDField(
default=uuid.uuid4, editable=False, null=True
),
)
]
.. code-block:: python3
from __future__ import unicode_literals
from django.db import migrations
import uuid
from django.apps import apps
app_models = apps.get_app_config("sights").get_models()
def gen_uuid(apps, schema_editor):
for MyModel in app_models:
if "uuid" in [f.name for f in MyModel._meta.get_fields()]:
tablename = MyModel.objects.model._meta.db_table
MyModel.objects.raw(
"update {} set uuid=uuid_generate_v4()", [tablename]
)
class Migration(migrations.Migration):
dependencies = [("accounts", "MA_MISE_A_JOUR_PRECEDENTE")]
operations = [
# omit reverse_code=... if you don't want the migration to be reversible.
migrations.RunPython(gen_uuid, reverse_code=migrations.RunPython.noop)
]
.. code-block:: python3
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
import uuid
class Migration(migrations.Migration):
dependencies = [("accounts", "MA_MISE_A_JOUR_PRECEDENTE")]
operations = [
migrations.AlterField(
model_name="profile",
name="uuid",
field=models.UUIDField(
default=uuid.uuid4, editable=False, unique=True
),
)
]
Mise à jour des profiles observations
=====================================
.. code-block:: python3
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
import uuid
class Migration(migrations.Migration):
dependencies = [("sights", "MA_MISE_A_JOUR_PRECEDENTE")]
operations = [
migrations.AddField(
model_name="countdetail",
name="uuid",
field=models.UUIDField(
default=uuid.uuid4, editable=False, null=True
),
),
migrations.AddField(
model_name="place",
name="uuid",
field=models.UUIDField(
default=uuid.uuid4, editable=False, null=True
),
),
migrations.AddField(
model_name="session",
name="uuid",
field=models.UUIDField(
default=uuid.uuid4, editable=False, null=True
),
),
migrations.AddField(
model_name="sighting",
name="uuid",
field=models.UUIDField(
default=uuid.uuid4, editable=False, null=True
),
),
migrations.AlterField(
model_name="session",
name="contact",
field=models.ForeignKey(
default=10,
on_delete=django.db.models.deletion.DO_NOTHING,
to="dicts.Contact",
verbose_name="Type de contact",
),
),
]
.. code-block:: python3
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, transaction
from django.apps import apps
import uuid
app_models = apps.get_app_config("sights").get_models()
def gen_uuid(apps, schema_editor):
for MyModel in app_models:
if "uuid" in [f.name for f in MyModel._meta.get_fields()]:
tablename = MyModel.objects.model._meta.db_table
print("Début du traitement de la table {}".format(tablename))
i = 0
MyModel.objects.filter(uuid__isnull=False).update(uuid=None)
while MyModel.objects.filter(uuid__isnull=True).exists():
print(
"Datas to update for {}: {} over {}".format(
tablename,
MyModel.objects.filter(uuid__isnull=True).count(),
MyModel.objects.count(),
)
)
with transaction.atomic():
for row in MyModel.objects.filter(uuid__isnull=True)[:1000]:
row.uuid = uuid.uuid4()
row.save()
class Migration(migrations.Migration):
atomic = False
dependencies = [("sights", "MA_MISE_A_JOUR_PRECEDENTE")]
operations = [migrations.RunPython(gen_uuid)]
.. code-block:: python3
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
import uuid
class Migration(migrations.Migration):
dependencies = [("sights", "MA_MISE_A_JOUR_PRECEDENCE")]
operations = [
migrations.AlterField(
model_name="countdetail",
name="uuid",
field=models.UUIDField(editable=False, unique=True),
),
migrations.AlterField(
model_name="place",
name="uuid",
field=models.UUIDField(editable=False, unique=True),
),
migrations.AlterField(
model_name="session",
name="uuid",
field=models.UUIDField(editable=False, unique=True),
),
migrations.AlterField(
model_name="sighting",
name="uuid",
field=models.UUIDField(editable=False, unique=True),
),
]
......@@ -12,53 +12,68 @@ from dicts.models import LandCoverCLC
class Territory(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=100, verbose_name='Nom', db_index=True)
code = models.CharField(max_length=5, verbose_name='Code', db_index=True)
coverage = models.BooleanField(default=False, verbose_name='Territoire couvert', db_index=True)
name = models.CharField(max_length=100, verbose_name="Nom", db_index=True)
code = models.CharField(max_length=5, verbose_name="Code", db_index=True)
coverage = models.BooleanField(
default=False, verbose_name="Territoire couvert", db_index=True
)
geom = models.MultiPolygonField(
srid=settings.GEODATA_SRID, verbose_name='Emprise géographique', spatial_index=True)
srid=settings.GEODATA_SRID,
verbose_name="Emprise géographique",
spatial_index=True,
)
def __str__(self):
return "%s ∙ %s" % (self.code, self.name)
class Meta:
verbose_name = _('Territoire du groupe local')
verbose_name_plural = _('Territoires des groupes locaux')
verbose_name = _("Territoire du groupe local")
verbose_name_plural = _("Territoires des groupes locaux")
class Municipality(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=100, verbose_name='Nom')
code = models.CharField(max_length=5, verbose_name='Code')
name = models.CharField(max_length=100, verbose_name="Nom")
code = models.CharField(max_length=5, verbose_name="Code")
geom = models.MultiPolygonField(
srid=settings.GEODATA_SRID, verbose_name='Emprise géographique',spatial_index=True)
srid=settings.GEODATA_SRID,
verbose_name="Emprise géographique",
spatial_index=True,
)
def __str__(self):
return "%s %s" % (self.code[0:2], self.name)
class Meta:
verbose_name = _('Commune')
verbose_name_plural = _('Communes')
verbose_name = _("Commune")
verbose_name_plural = _("Communes")
class LandCover(models.Model):
id = models.AutoField(primary_key=True)
code = models.ForeignKey(LandCoverCLC, verbose_name=_("Code"), blank=True, null=True)
geom = models.MultiPolygonField(srid=settings.GEODATA_SRID, verbose_name=_("Géométries"), spatial_index=True)
code = models.ForeignKey(
LandCoverCLC, verbose_name=_("Code"), blank=True, null=True
)
geom = models.MultiPolygonField(
srid=settings.GEODATA_SRID,
verbose_name=_("Géométries"),
spatial_index=True,
)
def __str__(self):
return "%s %s" % (self.code, self.code_descr.descr)
# TODO Créer model dico CLC12
class Meta:
verbose_name = _('Occupation du sol')
verbose_name_plural = _('Occupation du sol')
verbose_name = _("Occupation du sol")
verbose_name_plural = _("Occupation du sol")
class Elevation(models.Model):
name = models.CharField(max_length=100)
rast = models.RasterField(srid=settings.GEODATA_SRID, spatial_index=True)
rast = models.RasterField(srid=settings.GEODATA_SRID, spatial_index=True)
class Meta:
verbose_name = _('Altitude')
\ No newline at end of file
verbose_name = _("Altitude")
This diff is collapsed.
import datetime
import os.path
import uuid
from django.conf import settings
from django.contrib.auth.models import User
from django.contrib.gis.db import models as gismodels
......@@ -23,6 +23,7 @@ fs = FileSystemStorage()
class Place(models.Model):
id_place = models.AutoField(primary_key=True, db_index=True)
uuid = models.UUIDField(default=uuid.uuid4, unique=True, editable=False)
name = models.CharField(max_length=255, db_index=True,
verbose_name='nom du lieu')
is_hidden = models.BooleanField(
......@@ -409,6 +410,7 @@ class Cave(models.Model):
class Session(models.Model):
id_session = models.AutoField(primary_key=True)
uuid = models.UUIDField(default=uuid.uuid4, unique=True, editable=False)
name = models.CharField(
max_length=150, blank=True, verbose_name='Intitulé de la session')
contact = models.ForeignKey(
......@@ -479,6 +481,7 @@ class Session(models.Model):
class Sighting(models.Model):
id_sighting = models.AutoField(_('id unique'), primary_key=True)
uuid = models.UUIDField(default=uuid.uuid4, unique=True, editable=False)
session = models.ForeignKey(
Session, on_delete=models.CASCADE, verbose_name=_('Session associée'))
period = models.CharField(max_length=50, blank=True, null=True, verbose_name=_('Période d\'observation'))
......@@ -559,6 +562,7 @@ class Device(models.Model):
class CountDetail(models.Model):
id_countdetail = models.AutoField(primary_key=True)
uuid = models.UUIDField(default=uuid.uuid4, unique=True, editable=False)
sighting = models.ForeignKey(Sighting,
on_delete=models.CASCADE, related_name='countdetail_sighting')
method = models.ForeignKey(Method, on_delete=models.DO_NOTHING, verbose_name=_('Méthode'), blank=True,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment