From a0351eb0539df2aef0bfc3b0f0648aa073cda06a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Schweigh=C3=B6fer?= Date: Tue, 6 Jun 2017 13:25:35 +0200 Subject: [PATCH] Fix literature import (for now) --- pyBuchaktion/admin.py | 79 ++++++++++++++++--- .../migrations/0010_auto_20170605_2324.py | 49 ++++++++++++ .../migrations/0011_auto_20170605_2328.py | 25 ++++++ .../migrations/0012_auto_20170605_2329.py | 24 ++++++ .../0013_remove_module_literature_save.py | 19 +++++ pyBuchaktion/models.py | 30 ++++++- setup.py | 2 +- 7 files changed, 214 insertions(+), 14 deletions(-) create mode 100644 pyBuchaktion/migrations/0010_auto_20170605_2324.py create mode 100644 pyBuchaktion/migrations/0011_auto_20170605_2328.py create mode 100644 pyBuchaktion/migrations/0012_auto_20170605_2329.py create mode 100644 pyBuchaktion/migrations/0013_remove_module_literature_save.py diff --git a/pyBuchaktion/admin.py b/pyBuchaktion/admin.py index df5e004..bd9af88 100644 --- a/pyBuchaktion/admin.py +++ b/pyBuchaktion/admin.py @@ -6,6 +6,7 @@ from django.contrib.admin import ModelAdmin, register, helpers from django.db.models import Count +from django.db.models.query import Prefetch from django.utils.translation import ugettext_lazy as _ from django.utils.text import Truncator from django.http import HttpResponse @@ -14,17 +15,17 @@ from import_export.resources import ModelResource from import_export.admin import ImportExportMixin -from import_export.widgets import ManyToManyWidget, ForeignKeyWidget +from import_export.widgets import ManyToManyWidget, ForeignKeyWidget, Widget from import_export.fields import Field -from .models import Book, Order, Student, OrderTimeframe, Module, Semester, ModuleCategory, DisplayMessage +from .models import Book, Order, Student, OrderTimeframe, Module, Literature, Semester, ModuleCategory, DisplayMessage from .mixins import ForeignKeyImportResourceMixin from .data import net_library_csv from .mail import OrderAcceptedMessage, OrderArrivedMessage, OrderRejectedMessage, CustomMessage from .templatetags.buchaktion_tags import isbn class BookResource(ModelResource): - + def init_instance(self, row): return Book(state = Book.PROPOSED) @@ -369,17 +370,42 @@ class SemesterAdmin(ModelAdmin): pass +class TUCaNLiteratureWidget(ManyToManyWidget): + + def __init__(self): + super().__init__(Book, separator = '|', field = 'isbn_13') + +class TUCaNLiteratureField(Field): + + def __init__(self): + super().__init__(column_name='books', attribute='literature', widget=TUCaNLiteratureWidget()) + + def save(self, obj, data): + ids = [] + for book in self.clean(data): + literature, created = Literature.objects.get_or_create( + book=book, module=obj, source__in=(Literature.TUCAN, Literature.STAFF) + ) + ids.append(literature.pk) + obj.refresh_from_db(fields=['literature',]) + Literature.objects.filter(source=Literature.TUCAN).exclude(pk__in=ids).delete() + + def get_value(self, obj): + return Book.objects.filter( + literature_info__module=obj, + literature_info__source__in=[Literature.TUCAN, Literature.STAFF], + ) + + class ModuleResource(ForeignKeyImportResourceMixin, ModelResource): - books = Field( - column_name = 'books', - attribute = 'literature', - widget = ManyToManyWidget( - Book, - separator = '|', - field = 'isbn_13', - ), - ) + + def get_queryset(self): + queryset = super().get_queryset() + queryset.prefetch_related(Prefetch('literature')) + return queryset + + books = TUCaNLiteratureField() category = Field( column_name = 'category__name_de', attribute = 'category', @@ -431,6 +457,35 @@ class ModuleAdmin(ImportExportMixin, ModelAdmin): ) +@register(Literature) +class LiteratureAdmin(ModelAdmin): + + def get_queryset(self, request): + queryset = super().get_queryset(request) + queryset = queryset.prefetch_related(Prefetch('book')) + queryset = queryset.prefetch_related(Prefetch('module')) + return queryset + + + list_display = ( + 'title', + 'module_name', + 'source', + ) + + list_filter = ( + 'source', + ) + + def title(self, obj): + return Truncator(obj.book.title).chars(50) + title.short_description = _("title") + + def module_name(self, obj): + return Truncator(obj.module.name).chars(50) + module_name.short_description = _("module") + + class ModuleCategoryResource(ModelResource): class Meta: diff --git a/pyBuchaktion/migrations/0010_auto_20170605_2324.py b/pyBuchaktion/migrations/0010_auto_20170605_2324.py new file mode 100644 index 0000000..080737e --- /dev/null +++ b/pyBuchaktion/migrations/0010_auto_20170605_2324.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.7 on 2017-06-05 21:24 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('pyBuchaktion', '0009_auto_20170601_1559'), + ] + + operations = [ + migrations.CreateModel( + name='Literature', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('source', models.CharField(choices=[('TC', 'TUCaN Export'), ('SF', 'Module Staff'), ('SD', 'Student')], default='TC', max_length=2, verbose_name='source')), + ], + options={ + 'verbose_name': 'literature', + }, + ), + migrations.AlterModelOptions( + name='book', + options={'ordering': ['title'], 'verbose_name': 'book', 'verbose_name_plural': 'books'}, + ), + migrations.AlterModelOptions( + name='module', + options={'ordering': ['module_id'], 'verbose_name': 'module', 'verbose_name_plural': 'modules'}, + ), + migrations.RenameField( + model_name='module', + old_name='literature', + new_name='literature_save', + ), + migrations.AddField( + model_name='literature', + name='book', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='literature_info', to='pyBuchaktion.Book'), + ), + migrations.AddField( + model_name='literature', + name='module', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='literature_info', to='pyBuchaktion.Module'), + ), + ] diff --git a/pyBuchaktion/migrations/0011_auto_20170605_2328.py b/pyBuchaktion/migrations/0011_auto_20170605_2328.py new file mode 100644 index 0000000..d0a80a2 --- /dev/null +++ b/pyBuchaktion/migrations/0011_auto_20170605_2328.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.7 on 2017-06-05 21:28 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('pyBuchaktion', '0010_auto_20170605_2324'), + ] + + operations = [ + migrations.AddField( + model_name='module', + name='literature', + field=models.ManyToManyField(through='pyBuchaktion.Literature', to='pyBuchaktion.Book', verbose_name='literature'), + ), + migrations.AlterField( + model_name='module', + name='literature_save', + field=models.ManyToManyField(related_name='modules_save', to='pyBuchaktion.Book', verbose_name='literature'), + ), + ] diff --git a/pyBuchaktion/migrations/0012_auto_20170605_2329.py b/pyBuchaktion/migrations/0012_auto_20170605_2329.py new file mode 100644 index 0000000..6a02e6c --- /dev/null +++ b/pyBuchaktion/migrations/0012_auto_20170605_2329.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.7 on 2017-06-05 21:29 +from __future__ import unicode_literals + +from django.db import migrations + +def move_literature(apps, schema_editor): + Module = apps.get_model("pyBuchaktion", "Module") + Literature = apps.get_model("pyBuchaktion", "Literature") + + for module in Module.objects.all(): + for book in module.literature_save.all(): + m2 = Literature(module=module, book=book) + m2.save() + +class Migration(migrations.Migration): + + dependencies = [ + ('pyBuchaktion', '0011_auto_20170605_2328'), + ] + + operations = [ + migrations.RunPython(move_literature) + ] diff --git a/pyBuchaktion/migrations/0013_remove_module_literature_save.py b/pyBuchaktion/migrations/0013_remove_module_literature_save.py new file mode 100644 index 0000000..e1a8c30 --- /dev/null +++ b/pyBuchaktion/migrations/0013_remove_module_literature_save.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.7 on 2017-06-05 21:33 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('pyBuchaktion', '0012_auto_20170605_2329'), + ] + + operations = [ + migrations.RemoveField( + model_name='module', + name='literature_save', + ), + ] diff --git a/pyBuchaktion/models.py b/pyBuchaktion/models.py index 4f1d605..16703e9 100644 --- a/pyBuchaktion/models.py +++ b/pyBuchaktion/models.py @@ -486,7 +486,7 @@ class Module(models.Model): last_offered = models.ForeignKey('Semester', on_delete=models.CASCADE, verbose_name=_("last offered")) # The literature that is recommended by this module - literature = models.ManyToManyField('Book', verbose_name=_("literature")) + literature = models.ManyToManyField('Book', through='Literature', verbose_name=_("literature")) # The category that this module will appear in category = models.ForeignKey('ModuleCategory', on_delete=models.SET_NULL, null=True, blank=True, verbose_name=_('category')) @@ -510,6 +510,34 @@ class Meta: ordering = ['module_id'] +class Literature(models.Model): + module = models.ForeignKey(Module, on_delete=models.CASCADE, related_name='literature_info') + book = models.ForeignKey(Book, on_delete=models.CASCADE, related_name='literature_info') + + TUCAN='TC' + STAFF='SF' + STUDENT='SD' + + # The options for seasons available + SOURCE_CHOICES = ( + (TUCAN, _('TUCaN Export')), + (STAFF, _('Module Staff')), + (STUDENT, _('Student')), + ) + + # The season for this semester + source = models.CharField( + max_length=2, + choices=SOURCE_CHOICES, + default=TUCAN, + verbose_name=_("source"), + ) + + class Meta: + verbose_name = _("literature") + verbose_name_plural = _("literature") + + class ModuleCategory(models.Model): # The name for this category diff --git a/setup.py b/setup.py index 2de4934..2e8584d 100644 --- a/setup.py +++ b/setup.py @@ -42,7 +42,7 @@ def run(self): setup( name='pyBuchaktion', - version='0.10', + version='1.0', packages=find_packages(), include_package_data=True, license='AGPL-3.0',