]> gitweb.fperrin.net Git - djsite.git/commitdiff
Better implement tags, with separate namespaces
authorFrédéric Perrin <frederic.perrin@resel.fr>
Tue, 1 Nov 2016 00:04:15 +0000 (00:04 +0000)
committerFrédéric Perrin <frederic.perrin@resel.fr>
Tue, 1 Nov 2016 00:04:15 +0000 (00:04 +0000)
quotes/admin.py
quotes/migrations/0001_initial.py
quotes/migrations/0002_auto_20161031_2318.py [new file with mode: 0644]
quotes/migrations/0002_context_author.py [deleted file]
quotes/migrations/0003_auto_20161009_2254.py [deleted file]
quotes/migrations/0004_auto_20161009_2255.py [deleted file]
quotes/models.py
quotes/tests.py
quotes/views.py

index 7e8f1adfb3a778ba4174032b6b06b8215e300ecd..4e225dc04af88764bac5b4283c33bcc5cc44b870 100644 (file)
@@ -1,8 +1,26 @@
 from django.contrib import admin
 
 # Register your models here.
 from django.contrib import admin
 
 # Register your models here.
-from .models import Tag, Author, Work, Quote
-admin.site.register(Tag)
-admin.site.register(Author)
-admin.site.register(Work)
-admin.site.register(Quote)
+from .models import AuthorTag, WorkTag, QuoteTag, Author, Work, Quote
+
+@admin.register(Author)
+class AuthorAdmin(admin.ModelAdmin):
+    fields = ('name', 'birth_date', 'death_date', 'tags',
+              'notes', 'pvt_notes', 'creation_date', 'last_modification')
+    readonly_fields = ('creation_date', 'last_modification')
+
+@admin.register(Work)
+class WorkAdmin(admin.ModelAdmin):
+    fields = ('name', 'author', 'date', 'tags',
+              'notes', 'pvt_notes', 'creation_date', 'last_modification')
+    readonly_fields = ('creation_date', 'last_modification')
+
+@admin.register(Quote)
+class QuoteAdmin(admin.ModelAdmin):
+    fields = ('text', 'work', 'tags',
+              'notes', 'pvt_notes', 'creation_date', 'last_modification')
+    readonly_fields = ('creation_date', 'last_modification')
+
+admin.site.register(AuthorTag)
+admin.site.register(WorkTag)
+admin.site.register(QuoteTag)
index c7f97c4a58b7a20b0ae950315b5a987e161ac993..970ae11b4a5eb22cfd7ca919d7cb1931999a5888 100644 (file)
@@ -1,11 +1,16 @@
 # -*- coding: utf-8 -*-
 # -*- coding: utf-8 -*-
+# Generated by Django 1.10.2 on 2016-10-31 23:03
 from __future__ import unicode_literals
 
 from django.db import migrations, models
 from __future__ import unicode_literals
 
 from django.db import migrations, models
+import django.db.models.deletion
+import quotes.localmodels
 
 
 class Migration(migrations.Migration):
 
 
 
 class Migration(migrations.Migration):
 
+    initial = True
+
     dependencies = [
     ]
 
     dependencies = [
     ]
 
@@ -13,54 +18,82 @@ class Migration(migrations.Migration):
         migrations.CreateModel(
             name='Author',
             fields=[
         migrations.CreateModel(
             name='Author',
             fields=[
-                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
-                ('name', models.CharField(help_text=b'Name of the author', max_length=100)),
-                ('notes', models.TextField(help_text=b'Notes about the author; may be left blank. Will                               not be HTML-escaped.', blank=True)),
-                ('pvt_notes', models.TextField(help_text=b'Notes about the author; not displayed on                                   the public interface', blank=True)),
-                ('birth_date', models.DateField(help_text=b'Date of birth', null=True, blank=True)),
-                ('death_date', models.DateField(help_text=b'Date of death (leave blank                                   if still alive!)', null=True, blank=True)),
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('name', models.CharField(help_text=b'Name of the author', max_length=100, unique=True)),
+                ('notes', quotes.localmodels.HTMLField(blank=True, help_text=b'Notes about the author; may be left blank. Will                       not be HTML-escaped.')),
+                ('pvt_notes', quotes.localmodels.HTMLField(blank=True, help_text=b'Notes about the author; not displayed on                           the public interface')),
+                ('birth_date', models.DateField(blank=True, help_text=b'Date of birth', null=True)),
+                ('death_date', models.DateField(blank=True, help_text=b'Date of death (leave blank                                   if still alive!)', null=True)),
             ],
         ),
         migrations.CreateModel(
             ],
         ),
         migrations.CreateModel(
-            name='Context',
+            name='AuthorTag',
             fields=[
             fields=[
-                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
-                ('name', models.CharField(help_text=b'Name of the context for the quote                             (title of the work or speech it appears in)', max_length=100)),
-                ('date', models.DateField(help_text=b'Date of the quote', null=True, blank=True)),
-                ('notes', models.TextField(help_text=b'Notes about the work; may be left blank. Will                               not be HTML-escaped. XXX: offer a WYSIWYG editor', blank=True)),
-                ('pvt_notes', models.TextField(help_text=b'Notes about the work; not displayed on                                   the public interface', blank=True)),
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('tag', models.CharField(max_length=100, unique=True)),
             ],
             ],
+            options={
+                'abstract': False,
+            },
         ),
         migrations.CreateModel(
             name='Quote',
             fields=[
         ),
         migrations.CreateModel(
             name='Quote',
             fields=[
-                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
-                ('text', models.TextField()),
-                ('notes', models.TextField(help_text=b'Notes about the quote; may be left blank. Will                               not be HTML-escaped. XXX: offer a WYSIWYG editor', blank=True)),
-                ('pvt_notes', models.TextField(help_text=b'Notes about the quote; not displayed on                                   the public interface', blank=True)),
-                ('context', models.ForeignKey(to='quotes.Context')),
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('text', quotes.localmodels.HTMLField()),
+                ('notes', quotes.localmodels.HTMLField(blank=True, help_text=b'Notes about the quote; may be left blank. Will                       not be HTML-escaped. XXX: offer a WYSIWYG editor')),
+                ('pvt_notes', quotes.localmodels.HTMLField(blank=True, help_text=b'Notes about the quote; not displayed on                           the public interface')),
+            ],
+        ),
+        migrations.CreateModel(
+            name='QuoteTag',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('tag', models.CharField(max_length=100, unique=True)),
+            ],
+            options={
+                'abstract': False,
+            },
+        ),
+        migrations.CreateModel(
+            name='Work',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('name', models.CharField(help_text=b'Name of the context for the quote                             (title of the work or speech it appears in)', max_length=100, unique=True)),
+                ('date', models.DateField(blank=True, help_text=b'Date of the quote', null=True)),
+                ('notes', quotes.localmodels.HTMLField(blank=True, help_text=b'Notes about the work; may be left blank. Will                       not be HTML-escaped. XXX: offer a WYSIWYG editor')),
+                ('pvt_notes', quotes.localmodels.HTMLField(blank=True, help_text=b'Notes about the work; not displayed on                           the public interface')),
+                ('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='quotes.Author')),
             ],
         ),
         migrations.CreateModel(
             ],
         ),
         migrations.CreateModel(
-            name='Tag',
+            name='WorkTag',
             fields=[
             fields=[
-                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
-                ('tag', models.CharField(max_length=100)),
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('tag', models.CharField(max_length=100, unique=True)),
             ],
             ],
+            options={
+                'abstract': False,
+            },
         ),
         migrations.AddField(
         ),
         migrations.AddField(
-            model_name='quote',
+            model_name='work',
             name='tags',
             name='tags',
-            field=models.ManyToManyField(to='quotes.Tag', blank=True),
+            field=models.ManyToManyField(blank=True, to='quotes.WorkTag'),
         ),
         migrations.AddField(
         ),
         migrations.AddField(
-            model_name='context',
+            model_name='quote',
             name='tags',
             name='tags',
-            field=models.ManyToManyField(to='quotes.Tag', blank=True),
+            field=models.ManyToManyField(blank=True, to='quotes.QuoteTag'),
+        ),
+        migrations.AddField(
+            model_name='quote',
+            name='work',
+            field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='quotes.Work'),
         ),
         migrations.AddField(
             model_name='author',
             name='tags',
         ),
         migrations.AddField(
             model_name='author',
             name='tags',
-            field=models.ManyToManyField(to='quotes.Tag', blank=True),
+            field=models.ManyToManyField(blank=True, to='quotes.AuthorTag'),
         ),
     ]
         ),
     ]
diff --git a/quotes/migrations/0002_auto_20161031_2318.py b/quotes/migrations/0002_auto_20161031_2318.py
new file mode 100644 (file)
index 0000000..1fbd522
--- /dev/null
@@ -0,0 +1,90 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.10.2 on 2016-10-31 23:18
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+import django.utils.timezone
+import quotes.localmodels
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('quotes', '0001_initial'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='author',
+            name='creation_date',
+            field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now),
+            preserve_default=False,
+        ),
+        migrations.AddField(
+            model_name='author',
+            name='last_modification',
+            field=models.DateTimeField(auto_now=True),
+        ),
+        migrations.AddField(
+            model_name='quote',
+            name='creation_date',
+            field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now),
+            preserve_default=False,
+        ),
+        migrations.AddField(
+            model_name='quote',
+            name='last_modification',
+            field=models.DateTimeField(auto_now=True),
+        ),
+        migrations.AddField(
+            model_name='work',
+            name='creation_date',
+            field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now),
+            preserve_default=False,
+        ),
+        migrations.AddField(
+            model_name='work',
+            name='last_modification',
+            field=models.DateTimeField(auto_now=True),
+        ),
+        migrations.AlterField(
+            model_name='author',
+            name='notes',
+            field=quotes.localmodels.HTMLField(blank=True, help_text=b'Notes about the entry; may be left blank. Displayed                       on the public pages'),
+        ),
+        migrations.AlterField(
+            model_name='author',
+            name='pvt_notes',
+            field=quotes.localmodels.HTMLField(blank=True, help_text=b'Notes about the entry; not displayed on                           the public interface'),
+        ),
+        migrations.AlterField(
+            model_name='author',
+            name='tags',
+            field=models.ManyToManyField(blank=True, help_text=b'Not implemented yet', to='quotes.AuthorTag'),
+        ),
+        migrations.AlterField(
+            model_name='quote',
+            name='notes',
+            field=quotes.localmodels.HTMLField(blank=True, help_text=b'Notes about the entry; may be left blank. Displayed                       on the public pages'),
+        ),
+        migrations.AlterField(
+            model_name='quote',
+            name='pvt_notes',
+            field=quotes.localmodels.HTMLField(blank=True, help_text=b'Notes about the entry; not displayed on                           the public interface'),
+        ),
+        migrations.AlterField(
+            model_name='work',
+            name='notes',
+            field=quotes.localmodels.HTMLField(blank=True, help_text=b'Notes about the entry; may be left blank. Displayed                       on the public pages'),
+        ),
+        migrations.AlterField(
+            model_name='work',
+            name='pvt_notes',
+            field=quotes.localmodels.HTMLField(blank=True, help_text=b'Notes about the entry; not displayed on                           the public interface'),
+        ),
+        migrations.AlterField(
+            model_name='work',
+            name='tags',
+            field=models.ManyToManyField(blank=True, help_text=b'Not implemented yet', to='quotes.WorkTag'),
+        ),
+    ]
diff --git a/quotes/migrations/0002_context_author.py b/quotes/migrations/0002_context_author.py
deleted file mode 100644 (file)
index 79ca5e3..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('quotes', '0001_initial'),
-    ]
-
-    operations = [
-        migrations.AddField(
-            model_name='context',
-            name='author',
-            field=models.ForeignKey(default=1, to='quotes.Author'),
-            preserve_default=False,
-        ),
-    ]
diff --git a/quotes/migrations/0003_auto_20161009_2254.py b/quotes/migrations/0003_auto_20161009_2254.py
deleted file mode 100644 (file)
index b3b0366..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('quotes', '0002_context_author'),
-    ]
-
-    operations = [
-        migrations.CreateModel(
-            name='Work',
-            fields=[
-                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
-                ('name', models.CharField(help_text=b'Name of the context for the quote                             (title of the work or speech it appears in)', max_length=100)),
-                ('date', models.DateField(help_text=b'Date of the quote', null=True, blank=True)),
-                ('notes', models.TextField(help_text=b'Notes about the work; may be left blank. Will                               not be HTML-escaped. XXX: offer a WYSIWYG editor', blank=True)),
-                ('pvt_notes', models.TextField(help_text=b'Notes about the work; not displayed on                                   the public interface', blank=True)),
-                ('author', models.ForeignKey(to='quotes.Author')),
-                ('tags', models.ManyToManyField(to='quotes.Tag', blank=True)),
-            ],
-        ),
-        migrations.RemoveField(
-            model_name='context',
-            name='author',
-        ),
-        migrations.RemoveField(
-            model_name='context',
-            name='tags',
-        ),
-        migrations.AlterField(
-            model_name='quote',
-            name='context',
-            field=models.ForeignKey(to='quotes.Work'),
-        ),
-        migrations.DeleteModel(
-            name='Context',
-        ),
-    ]
diff --git a/quotes/migrations/0004_auto_20161009_2255.py b/quotes/migrations/0004_auto_20161009_2255.py
deleted file mode 100644 (file)
index cf435ab..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
-    dependencies = [
-        ('quotes', '0003_auto_20161009_2254'),
-    ]
-
-    operations = [
-        migrations.RenameField(
-            model_name='quote',
-            old_name='context',
-            new_name='work',
-        ),
-    ]
index 0fa66afd0ed91e8e076bd7d674c068246ef09b46..e23fde52a0a1475496212a1bc421534ce5296028 100644 (file)
@@ -2,21 +2,40 @@ from django.db import models
 from localmodels import HTMLField
 
 # Create your models here.
 from localmodels import HTMLField
 
 # Create your models here.
-class Tag(models.Model):
-    tag = models.CharField(max_length=100)
+class BaseTag(models.Model):
+    tag = models.CharField(max_length=100, unique=True)
+
     def __unicode__(self):
         return self.tag
 
     def __unicode__(self):
         return self.tag
 
-class Author(models.Model):
-    name = models.CharField(max_length=100,
-                            help_text="Name of the author")
+    class Meta(object):
+        abstract = True
+
+class AuthorTag(BaseTag): pass
+class WorkTag(BaseTag): pass
+class QuoteTag(BaseTag): pass
+
+class CommonData(models.Model):
+    creation_date = models.DateTimeField(auto_now_add=True)
+    last_modification = models.DateTimeField(auto_now=True)
+
     notes = HTMLField(blank=True, help_text= \
     notes = HTMLField(blank=True, help_text= \
-                      "Notes about the author; may be left blank. Will \
-                      not be HTML-escaped.",)
+                      "Notes about the entry; may be left blank. Displayed \
+                      on the public pages")
     pvt_notes = HTMLField(blank=True, help_text= \
     pvt_notes = HTMLField(blank=True, help_text= \
-                          "Notes about the author; not displayed on \
-                          the public interface",)
-    tags = models.ManyToManyField(Tag, blank=True)
+                          "Notes about the entry; not displayed on \
+                          the public interface")
+
+    class Meta(object):
+        abstract = True
+
+class Author(CommonData):
+    name = models.CharField(max_length=100,
+                            help_text="Name of the author",
+                            unique=True)
+
+    tags = models.ManyToManyField(AuthorTag, blank=True,
+                                  help_text='Not implemented yet')
 
     birth_date = models.DateField(blank=True, null=True,
                                   help_text="Date of birth")
 
     birth_date = models.DateField(blank=True, null=True,
                                   help_text="Date of birth")
@@ -46,36 +65,24 @@ class Author(models.Model):
 #         models.CharField(max_length=1, choices=self.PRECISION_CHOICES,
 #                          default=self.DAY, **kwargs)
 
 #         models.CharField(max_length=1, choices=self.PRECISION_CHOICES,
 #                          default=self.DAY, **kwargs)
 
-class Work(models.Model):
+class Work(CommonData):
     name = models.CharField(max_length=100,
                             help_text="Name of the context for the quote \
     name = models.CharField(max_length=100,
                             help_text="Name of the context for the quote \
-                            (title of the work or speech it appears in)")
+                            (title of the work or speech it appears in)",
+                            unique=True)
     author = models.ForeignKey(Author)
     date = models.DateField(blank=True, null=True,
                             help_text="Date of the quote")
     author = models.ForeignKey(Author)
     date = models.DateField(blank=True, null=True,
                             help_text="Date of the quote")
-    tags = models.ManyToManyField(Tag, blank=True)
-
-    notes = HTMLField(blank=True, help_text= \
-                      "Notes about the work; may be left blank. Will \
-                      not be HTML-escaped. XXX: offer a WYSIWYG editor")
-    pvt_notes = HTMLField(blank=True, help_text= \
-                          "Notes about the work; not displayed on \
-                          the public interface")
+    tags = models.ManyToManyField(WorkTag, blank=True,
+                                  help_text='Not implemented yet')
 
     def __str__(self):
         return "%s: %s (%s)" % (self.author.name, self.name, self.date)
 
 
     def __str__(self):
         return "%s: %s (%s)" % (self.author.name, self.name, self.date)
 
-class Quote(models.Model):
+class Quote(CommonData):
     text = HTMLField()
     text = HTMLField()
-    tags = models.ManyToManyField(Tag, blank=True)
+    tags = models.ManyToManyField(QuoteTag, blank=True)
     work = models.ForeignKey(Work)
 
     work = models.ForeignKey(Work)
 
-    notes = HTMLField(blank=True, help_text= \
-                      "Notes about the quote; may be left blank. Will \
-                      not be HTML-escaped. XXX: offer a WYSIWYG editor")
-    pvt_notes = HTMLField(blank=True, help_text= \
-                          "Notes about the quote; not displayed on \
-                          the public interface")
-
     def __str__(self):
         return self.work.author.name + ": " + self.text
     def __str__(self):
         return self.work.author.name + ": " + self.text
index 4fbe4776757864f14ad078e4e17cb538e422e867..36dcc1d1cd1aa3d7cd84f40ad40d0a3e1571b424 100644 (file)
@@ -1,7 +1,7 @@
 from django.test import TestCase, Client
 
 # Create your tests here.
 from django.test import TestCase, Client
 
 # Create your tests here.
-from .models import Tag, Author, Work, Quote
+from .models import QuoteTag, Author, Work, Quote
 import re
 import lxml.etree
 
 import re
 import lxml.etree
 
@@ -42,8 +42,8 @@ class ViewsTest(TestCase):
         q1 = Quote.objects.create(text="<p>Quote01, two tags</p>",
                                   work=w1,
                                   notes="<p>Some notes for the quote</p>")
         q1 = Quote.objects.create(text="<p>Quote01, two tags</p>",
                                   work=w1,
                                   notes="<p>Some notes for the quote</p>")
-        t1 = Tag.objects.create(tag="tag01-1")
-        t2 = Tag.objects.create(tag="tag01-2")
+        t1 = QuoteTag.objects.create(tag="tag01-1")
+        t2 = QuoteTag.objects.create(tag="tag01-2")
         q1.tags.add(t1, t2)
 
         a2 = Author.objects.create(name="Author without notes")
         q1.tags.add(t1, t2)
 
         a2 = Author.objects.create(name="Author without notes")
index df4081d5b79b251ff5523b98d283dd470b2367d2..9bed533b045f73e0385f32c934e5c780d3cc2b70 100644 (file)
@@ -2,7 +2,7 @@ from django.shortcuts import render
 
 from random import randint
 
 
 from random import randint
 
-from .models import Author, Work, Quote, Tag
+from .models import Author, Work, Quote, QuoteTag
 
 # Create your views here.
 def onequote(request, quote_id):
 
 # Create your views here.
 def onequote(request, quote_id):
@@ -15,7 +15,7 @@ def random(request):
     return onequote(request, randint(1, count))
 
 def tags(request, tag_id):
     return onequote(request, randint(1, count))
 
 def tags(request, tag_id):
-    tag = Tag.objects.get(id=tag_id)
+    tag = QuoteTag.objects.get(id=tag_id)
     context = { 'tag' : tag }
     return render(request, 'quotes/tag.html', context)
 
     context = { 'tag' : tag }
     return render(request, 'quotes/tag.html', context)