metadata mod in project src
authorOlivier Larchevêque <olivier.larcheveque@auf.org>
Mon, 6 Feb 2012 21:34:42 +0000 (16:34 -0500)
committerOlivier Larchevêque <olivier.larcheveque@auf.org>
Mon, 6 Feb 2012 21:34:42 +0000 (16:34 -0500)
30 files changed:
src/auf.django.metadata/.gitignore [new file with mode: 0755]
src/auf.django.metadata/CHANGES [new file with mode: 0755]
src/auf.django.metadata/MANIFEST.in [new file with mode: 0755]
src/auf.django.metadata/README [new file with mode: 0755]
src/auf.django.metadata/auf.django.metadata.egg-info/PKG-INFO [new file with mode: 0755]
src/auf.django.metadata/auf.django.metadata.egg-info/SOURCES.txt [new file with mode: 0755]
src/auf.django.metadata/auf.django.metadata.egg-info/dependency_links.txt [new file with mode: 0755]
src/auf.django.metadata/auf.django.metadata.egg-info/entry_points.txt [new file with mode: 0755]
src/auf.django.metadata/auf.django.metadata.egg-info/not-zip-safe [new file with mode: 0755]
src/auf.django.metadata/auf.django.metadata.egg-info/top_level.txt [new file with mode: 0755]
src/auf.django.metadata/auf/__init__.py [new file with mode: 0755]
src/auf.django.metadata/auf/__init__.pyc [new file with mode: 0644]
src/auf.django.metadata/auf/django/__init__.py [new file with mode: 0755]
src/auf.django.metadata/auf/django/__init__.pyc [new file with mode: 0644]
src/auf.django.metadata/auf/django/metadata/__init__.py [new file with mode: 0755]
src/auf.django.metadata/auf/django/metadata/__init__.pyc [new file with mode: 0644]
src/auf.django.metadata/auf/django/metadata/admin.py [new file with mode: 0755]
src/auf.django.metadata/auf/django/metadata/admin.pyc [new file with mode: 0644]
src/auf.django.metadata/auf/django/metadata/managers.py [new file with mode: 0755]
src/auf.django.metadata/auf/django/metadata/managers.pyc [new file with mode: 0644]
src/auf.django.metadata/auf/django/metadata/models.py [new file with mode: 0755]
src/auf.django.metadata/auf/django/metadata/models.pyc [new file with mode: 0644]
src/auf.django.metadata/auf/django/metadata/tests.py [new file with mode: 0755]
src/auf.django.metadata/auf/django/metadata/views.py [new file with mode: 0755]
src/auf.django.metadata/dist/auf.django.metadata-0.1dev.tar.gz [new file with mode: 0755]
src/auf.django.metadata/dist/auf.django.metadata-0.4dev.tar.gz [new file with mode: 0755]
src/auf.django.metadata/dist/auf.django.metadata-0.5dev.tar.gz [new file with mode: 0644]
src/auf.django.metadata/dist/auf.django.metadata-0.6dev.tar.gz [new file with mode: 0644]
src/auf.django.metadata/setup.cfg [new file with mode: 0755]
src/auf.django.metadata/setup.py [new file with mode: 0755]

diff --git a/src/auf.django.metadata/.gitignore b/src/auf.django.metadata/.gitignore
new file mode 100755 (executable)
index 0000000..499a075
--- /dev/null
@@ -0,0 +1,4 @@
+*.pyc
+*egg-info
+build
+dist
diff --git a/src/auf.django.metadata/CHANGES b/src/auf.django.metadata/CHANGES
new file mode 100755 (executable)
index 0000000..54f172c
--- /dev/null
@@ -0,0 +1,38 @@
+auf.django.metadata
+===================
+
+0.6
+---
+
+* Renommage de metedata par méta-données
+
+0.5
+---
+
+* ajout des verbose_name
+
+* fix delete sur QuerySet
+
+* liste les éléments actifs par défaut dans l'admin
+
+0.4
+---
+
+* Utilisation de DateTimeField à la place de DateField
+
+0.3
+---
+
+* Ajout de managers
+
+0.2
+---
+
+* Ajout dans l'admin, d'une action pour inactiver les objets
+en masse.
+Mettre 'desactiver' dans la actions = () de la liste.
+
+0.1
+---
+
+* Création du module : modèle abstrait avec manager et admin
diff --git a/src/auf.django.metadata/MANIFEST.in b/src/auf.django.metadata/MANIFEST.in
new file mode 100755 (executable)
index 0000000..e69de29
diff --git a/src/auf.django.metadata/README b/src/auf.django.metadata/README
new file mode 100755 (executable)
index 0000000..b1b6678
--- /dev/null
@@ -0,0 +1,53 @@
+auf.django.metadata
+===================
+
+Ce module fournit un modèle abstrait en vue d'harmoniser les metadata des modèles
+utilisés dans les applications.
+
+Il s'occupe aussi de l'assignation automatique de ces metadatas à travers l'admin.
+Si les objets sont modifiés à travers un frontend, ces metadatas devront être codées
+manuellement dans les vues.
+
+Ce module fournit notemment une metadata 'supprime', qui permet de simuler une suppression
+aux yeux des utilisateurs. Toute la mécanique des de queryset pour lister et supprimer les
+objets est liée à ce modèle abstrait et n'est plus à coder dans votre application.
+
+Exemple d'utilisation
+=====================
+
+1. Vos models
+-------------
+class AyantDroit(AUFMetadata):
+    """Personne en relation avec un Employe.
+    """
+    nom = models.CharField(max_length=255)
+    prenom = models.CharField(max_length=255, verbose_name="Prénom",)
+    employe = models.ForeignKey('Employe', db_column='employe', verbose_name="Employé")
+
+2. Vos admins
+-------------
+
+# -*- encoding: utf-8 -*-
+
+from django.contrib import admin
+from auf.django.metadata.admin import AUFMetadataAdminMixin
+
+class AyantDroitAdmin(AUFMetadataAdminMixin, admin.ModelAdmin):
+    """
+    L'ajout d'un nouvel ayantdroit se fait dans l'admin de l'employé.
+    """
+
+    # Dans ce cas on ajoute d'autres champs "readonly" autrement cette déclaration
+    # est optionnelle.
+    readonly_fields = AUFMetadataAdminMixin.readonly_fields + ('employe',)
+
+    # Ajoute un premier fieldeset contenant les metadata ordonnées.
+    fieldsets = AUFMetadataAdminMixin.fieldsets + (
+        ("Lien avec l'employé", {
+            'fields': ('employe', )
+        }),
+
+        ('Identification', {
+            'fields': ('nom', 'prenom', )
+        }),
+    )
diff --git a/src/auf.django.metadata/auf.django.metadata.egg-info/PKG-INFO b/src/auf.django.metadata/auf.django.metadata.egg-info/PKG-INFO
new file mode 100755 (executable)
index 0000000..336e06c
--- /dev/null
@@ -0,0 +1,10 @@
+Metadata-Version: 1.0
+Name: auf.django.metadata
+Version: 0.6dev
+Summary: Metadata pour les modèles AUF, avec les outils qui les définissent et les exploitent.
+Home-page: http://pypi.auf.org/auf.django.metadata
+Author: Olivier Larchevêque
+Author-email: olivier.larcheveque@auf.org
+License: GPL
+Description: UNKNOWN
+Platform: UNKNOWN
diff --git a/src/auf.django.metadata/auf.django.metadata.egg-info/SOURCES.txt b/src/auf.django.metadata/auf.django.metadata.egg-info/SOURCES.txt
new file mode 100755 (executable)
index 0000000..3c8a31e
--- /dev/null
@@ -0,0 +1,18 @@
+MANIFEST.in
+README
+setup.cfg
+setup.py
+auf/__init__.py
+auf.django.metadata.egg-info/PKG-INFO
+auf.django.metadata.egg-info/SOURCES.txt
+auf.django.metadata.egg-info/dependency_links.txt
+auf.django.metadata.egg-info/entry_points.txt
+auf.django.metadata.egg-info/not-zip-safe
+auf.django.metadata.egg-info/top_level.txt
+auf/django/__init__.py
+auf/django/metadata/__init__.py
+auf/django/metadata/admin.py
+auf/django/metadata/managers.py
+auf/django/metadata/models.py
+auf/django/metadata/tests.py
+auf/django/metadata/views.py
\ No newline at end of file
diff --git a/src/auf.django.metadata/auf.django.metadata.egg-info/dependency_links.txt b/src/auf.django.metadata/auf.django.metadata.egg-info/dependency_links.txt
new file mode 100755 (executable)
index 0000000..8b13789
--- /dev/null
@@ -0,0 +1 @@
+
diff --git a/src/auf.django.metadata/auf.django.metadata.egg-info/entry_points.txt b/src/auf.django.metadata/auf.django.metadata.egg-info/entry_points.txt
new file mode 100755 (executable)
index 0000000..5d3e5f6
--- /dev/null
@@ -0,0 +1,3 @@
+
+      # -*- Entry points: -*-
+      
\ No newline at end of file
diff --git a/src/auf.django.metadata/auf.django.metadata.egg-info/not-zip-safe b/src/auf.django.metadata/auf.django.metadata.egg-info/not-zip-safe
new file mode 100755 (executable)
index 0000000..8b13789
--- /dev/null
@@ -0,0 +1 @@
+
diff --git a/src/auf.django.metadata/auf.django.metadata.egg-info/top_level.txt b/src/auf.django.metadata/auf.django.metadata.egg-info/top_level.txt
new file mode 100755 (executable)
index 0000000..dc3e357
--- /dev/null
@@ -0,0 +1 @@
+auf
diff --git a/src/auf.django.metadata/auf/__init__.py b/src/auf.django.metadata/auf/__init__.py
new file mode 100755 (executable)
index 0000000..35cf25b
--- /dev/null
@@ -0,0 +1,5 @@
+try:
+    __import__('pkg_resources').declare_namespace(__name__)
+except:
+    # bootstrapping
+    pass
diff --git a/src/auf.django.metadata/auf/__init__.pyc b/src/auf.django.metadata/auf/__init__.pyc
new file mode 100644 (file)
index 0000000..d5b3cb0
Binary files /dev/null and b/src/auf.django.metadata/auf/__init__.pyc differ
diff --git a/src/auf.django.metadata/auf/django/__init__.py b/src/auf.django.metadata/auf/django/__init__.py
new file mode 100755 (executable)
index 0000000..35cf25b
--- /dev/null
@@ -0,0 +1,5 @@
+try:
+    __import__('pkg_resources').declare_namespace(__name__)
+except:
+    # bootstrapping
+    pass
diff --git a/src/auf.django.metadata/auf/django/__init__.pyc b/src/auf.django.metadata/auf/django/__init__.pyc
new file mode 100644 (file)
index 0000000..4f5f0de
Binary files /dev/null and b/src/auf.django.metadata/auf/django/__init__.pyc differ
diff --git a/src/auf.django.metadata/auf/django/metadata/__init__.py b/src/auf.django.metadata/auf/django/metadata/__init__.py
new file mode 100755 (executable)
index 0000000..e69de29
diff --git a/src/auf.django.metadata/auf/django/metadata/__init__.pyc b/src/auf.django.metadata/auf/django/metadata/__init__.pyc
new file mode 100644 (file)
index 0000000..004482f
Binary files /dev/null and b/src/auf.django.metadata/auf/django/metadata/__init__.pyc differ
diff --git a/src/auf.django.metadata/auf/django/metadata/admin.py b/src/auf.django.metadata/auf/django/metadata/admin.py
new file mode 100755 (executable)
index 0000000..8444eac
--- /dev/null
@@ -0,0 +1,100 @@
+# -*- encoding: utf-8 -*-
+
+import datetime
+from django.contrib import admin
+from django.contrib import messages
+from django.shortcuts import redirect
+from models import AUFMetadata
+
+AUF_METADATA_READONLY_FIELDS = ('supprime',
+                       'date_creation',
+                       'user_creation',
+                       'date_modification',
+                       'user_modification',
+                       'date_activation',
+                       'user_activation',
+                       'date_desactivation',
+                       'user_desactivation', )
+
+AUF_METADATA_FIELDSET_FIELDS = ('actif', 'date_creation', 'user_creation',
+                       'date_modification', 'user_modification',
+                       'date_activation', 'user_activation',
+                       'date_desactivation', 'user_desactivation',)
+
+class AUFMetadataInlineAdminMixin(object):
+    exclude = AUF_METADATA_READONLY_FIELDS + ('actif', )
+
+
+class AUFMetadataAdminMixin(object):
+    """
+    Surcharge l'admin de base, pour setter automatiquement les metadata.
+    """
+    actions = ['desactiver', ]
+
+    readonly_fields = AUF_METADATA_READONLY_FIELDS
+    fieldsets = (
+        ('Méta-données', {
+            'classes': ('collapse',),
+            'fields': AUF_METADATA_FIELDSET_FIELDS,
+        }),
+    )
+
+    def desactiver(modeladmin, request, queryset):
+      """
+      Passe à actif = False tous les objets du QS
+      """
+      selected = request.POST.getlist(admin.ACTION_CHECKBOX_NAME)
+      queryset.update(actif=False)
+      messages.add_message(request, messages.INFO, u'Les %s ont été désactivés.' % queryset.model._meta.verbose_name_plural)
+      info = queryset.model._meta.app_label, queryset.model._meta.module_name
+      return redirect('admin:%s_%s_changelist' % info)
+    desactiver.short_description = u"Désactiver les éléments sélectionnés"
+
+    def save_model(self, request, obj, form, change):
+        if obj.user_creation is None:
+            obj.user_creation = request.user
+            obj.date_creation = datetime.datetime.now()
+        obj.user_modification = request.user
+        obj.date_modification = datetime.datetime.now()
+        initial = getattr(form, 'initial', None)
+        if initial:
+            if form.initial['actif'] is True and obj.actif is False:
+                obj.user_desactivation = request.user
+                obj.date_desactivation = datetime.datetime.now()
+            if form.initial['actif'] is False and obj.actif is True:
+                obj.user_activation = request.user
+                obj.date_activation = datetime.datetime.now()
+        obj.save()
+
+    def has_metadata(self, instance):
+        """
+        Test si une instance de modele hérite bien de AUFMetadata.
+        """
+        test = getattr(instance, 'supprime', None)
+        return test is not None
+
+    def save_formset(self, request, form, formset, change):
+        """
+        Mettre les metadata si l'objet est créé ou modifié par inline.
+        """
+        instances = formset.save(commit=False)
+        for instance in instances:
+            if self.has_metadata(instance):
+                self.save_model(request, instance, formset.form, change)           
+            else:
+                instance.save()
+        formset.save_m2m()
+
+
+    def changelist_view(self, request, extra_context=None):
+        """
+        Sans filtre sélectionné, on redirige vers les éléments actifs
+        """
+        url = request.get_full_path()
+        has_filter = "?" in url
+        if  has_filter is False:
+            q = request.GET.copy()
+            q['actif__exact'] = 1
+            return redirect("%s?%s" % (url, q.urlencode()))
+        return super(AUFMetadataAdminMixin, self).changelist_view(request, extra_context=extra_context)
+
diff --git a/src/auf.django.metadata/auf/django/metadata/admin.pyc b/src/auf.django.metadata/auf/django/metadata/admin.pyc
new file mode 100644 (file)
index 0000000..c4514bd
Binary files /dev/null and b/src/auf.django.metadata/auf/django/metadata/admin.pyc differ
diff --git a/src/auf.django.metadata/auf/django/metadata/managers.py b/src/auf.django.metadata/auf/django/metadata/managers.py
new file mode 100755 (executable)
index 0000000..61d7c4d
--- /dev/null
@@ -0,0 +1,35 @@
+# -*- encoding: utf-8 -*-
+
+from django.db import models
+
+
+class NoDeleteQuerySet(models.query.QuerySet):
+    """
+    Pas de delete, flag à supprimer sur les entrées.
+    """
+    def delete(self):
+        self.update(supprime=True)
+
+
+class NoDeleteManager(models.Manager):
+    """
+    Les entrées supprimées sont exclues des querysets.
+    """
+    def get_query_set(self):
+        return NoDeleteQuerySet(self.model, using=self._db).filter(supprime=False)
+
+
+class ActifsManager(NoDeleteManager):
+    """
+    Seulement les entrées actives
+    """
+    def get_query_set(self):
+        return super(ActifsManager, self).get_query_set().filter(actif=True)
+
+
+class InactifsManager(NoDeleteManager):
+    """
+    Seulement les entrées inactives
+    """
+    def get_query_set(self):
+        return super(InactifsManager, self).get_query_set().filter(actif=False)
diff --git a/src/auf.django.metadata/auf/django/metadata/managers.pyc b/src/auf.django.metadata/auf/django/metadata/managers.pyc
new file mode 100644 (file)
index 0000000..0588ac7
Binary files /dev/null and b/src/auf.django.metadata/auf/django/metadata/managers.pyc differ
diff --git a/src/auf.django.metadata/auf/django/metadata/models.py b/src/auf.django.metadata/auf/django/metadata/models.py
new file mode 100755 (executable)
index 0000000..417214f
--- /dev/null
@@ -0,0 +1,43 @@
+# -*- encoding: utf-8 -*-
+
+from django.db import models
+from managers import NoDeleteManager, ActifsManager, InactifsManager
+
+
+class AUFMetadata(models.Model):
+    """
+    Méta-données AUF.
+    supprime = niveau système
+    actif = niveau utilisateur
+    """
+    supprime = models.BooleanField(default=False)
+    date_creation = models.DateTimeField(null=True, blank=True, verbose_name=u"Date de création",)
+    user_creation = models.ForeignKey('auth.User', verbose_name=u"Crée par",
+                            db_column='user_creation', related_name='+',
+                            null=True, blank=True)
+    date_modification = models.DateTimeField(null=True, blank=True, verbose_name=u"Date de modification",)
+    user_modification = models.ForeignKey('auth.User', verbose_name=u"Modifié par",
+                            db_column='user_modification', related_name='+',
+                            null=True, blank=True)
+    actif = models.BooleanField(default=True)
+    date_activation = models.DateTimeField(null=True, blank=True, verbose_name=u"Date d'activation",)
+    user_activation = models.ForeignKey('auth.User',  verbose_name=u"Activé par",
+                            db_column='user_activation', related_name='+',
+                            null=True, blank=True)
+    date_desactivation = models.DateTimeField(null=True, blank=True, verbose_name=u"Date de désactivation",)
+    user_desactivation = models.ForeignKey('auth.User', verbose_name=u"Désactivé par", 
+                            db_column='user_desactivation', related_name='+',
+                            null=True, blank=True)
+
+    objects = NoDeleteManager()
+    actifs = ActifsManager()
+    inactifs = InactifsManager()
+
+    class Meta:
+        abstract = True
+
+    def delete(self):
+        self.supprime = True
+        self.save()
+
+
diff --git a/src/auf.django.metadata/auf/django/metadata/models.pyc b/src/auf.django.metadata/auf/django/metadata/models.pyc
new file mode 100644 (file)
index 0000000..bafab8d
Binary files /dev/null and b/src/auf.django.metadata/auf/django/metadata/models.pyc differ
diff --git a/src/auf.django.metadata/auf/django/metadata/tests.py b/src/auf.django.metadata/auf/django/metadata/tests.py
new file mode 100755 (executable)
index 0000000..2247054
--- /dev/null
@@ -0,0 +1,23 @@
+"""
+This file demonstrates two different styles of tests (one doctest and one
+unittest). These will both pass when you run "manage.py test".
+
+Replace these with more appropriate tests for your application.
+"""
+
+from django.test import TestCase
+
+class SimpleTest(TestCase):
+    def test_basic_addition(self):
+        """
+        Tests that 1 + 1 always equals 2.
+        """
+        self.failUnlessEqual(1 + 1, 2)
+
+__test__ = {"doctest": """
+Another way to test that 1 + 1 is equal to 2.
+
+>>> 1 + 1 == 2
+True
+"""}
+
diff --git a/src/auf.django.metadata/auf/django/metadata/views.py b/src/auf.django.metadata/auf/django/metadata/views.py
new file mode 100755 (executable)
index 0000000..60f00ef
--- /dev/null
@@ -0,0 +1 @@
+# Create your views here.
diff --git a/src/auf.django.metadata/dist/auf.django.metadata-0.1dev.tar.gz b/src/auf.django.metadata/dist/auf.django.metadata-0.1dev.tar.gz
new file mode 100755 (executable)
index 0000000..c331a30
Binary files /dev/null and b/src/auf.django.metadata/dist/auf.django.metadata-0.1dev.tar.gz differ
diff --git a/src/auf.django.metadata/dist/auf.django.metadata-0.4dev.tar.gz b/src/auf.django.metadata/dist/auf.django.metadata-0.4dev.tar.gz
new file mode 100755 (executable)
index 0000000..48e51f5
Binary files /dev/null and b/src/auf.django.metadata/dist/auf.django.metadata-0.4dev.tar.gz differ
diff --git a/src/auf.django.metadata/dist/auf.django.metadata-0.5dev.tar.gz b/src/auf.django.metadata/dist/auf.django.metadata-0.5dev.tar.gz
new file mode 100644 (file)
index 0000000..e46e072
Binary files /dev/null and b/src/auf.django.metadata/dist/auf.django.metadata-0.5dev.tar.gz differ
diff --git a/src/auf.django.metadata/dist/auf.django.metadata-0.6dev.tar.gz b/src/auf.django.metadata/dist/auf.django.metadata-0.6dev.tar.gz
new file mode 100644 (file)
index 0000000..ba9b62c
Binary files /dev/null and b/src/auf.django.metadata/dist/auf.django.metadata-0.6dev.tar.gz differ
diff --git a/src/auf.django.metadata/setup.cfg b/src/auf.django.metadata/setup.cfg
new file mode 100755 (executable)
index 0000000..01bb954
--- /dev/null
@@ -0,0 +1,3 @@
+[egg_info]
+tag_build = dev
+tag_svn_revision = true
diff --git a/src/auf.django.metadata/setup.py b/src/auf.django.metadata/setup.py
new file mode 100755 (executable)
index 0000000..e2c60ba
--- /dev/null
@@ -0,0 +1,29 @@
+# -*- encoding: utf-8 -*-
+
+from setuptools import setup, find_packages
+import sys, os
+
+name = 'auf.django.metadata'
+version = '0.6'
+
+setup(name=name,
+      version=version,
+      description="Metadata pour les modèles AUF, avec les outils qui les définissent et les exploitent.",
+      long_description="""\
+""",
+      classifiers=[], # Get strings from http://pypi.python.org/pypi?%3Aaction=list_classifiers
+      keywords='',
+      author='Olivier Larchev\xc3\xaaque',
+      author_email='olivier.larcheveque@auf.org',
+      url='http://pypi.auf.org/%s' % name,
+      license='GPL',
+      packages=find_packages(exclude=['ez_setup', 'examples', 'tests']),
+      include_package_data=True,
+      zip_safe=False,
+      install_requires=[
+          # -*- Extra requirements: -*-
+      ],
+      entry_points="""
+      # -*- Entry points: -*-
+      """,
+      )