From 981a684f7d10e4f3dbe06fbadfb1a5c68ad7b97b Mon Sep 17 00:00:00 2001 From: Aleksei Pirogov Date: Wed, 10 Mar 2021 21:13:38 +0300 Subject: [PATCH] add item dropping --- djaif/book/admin.py | 2 + djaif/book/migrations/0014_droppeditem.py | 23 +++++++++ djaif/book/migrations/0015_droppeditemsave.py | 23 +++++++++ djaif/book/models.py | 35 ++++++++++++- djaif/book/templates/page.html | 16 ++++++ djaif/book/urls.py | 8 ++- djaif/book/views.py | 50 +++++++++++++++++-- 7 files changed, 151 insertions(+), 6 deletions(-) create mode 100644 djaif/book/migrations/0014_droppeditem.py create mode 100644 djaif/book/migrations/0015_droppeditemsave.py diff --git a/djaif/book/admin.py b/djaif/book/admin.py index a154276..ae46127 100644 --- a/djaif/book/admin.py +++ b/djaif/book/admin.py @@ -15,4 +15,6 @@ class BookAdmin(admin.ModelAdmin): admin.site.register(models.BookPage, Admin) admin.site.register(models.PageLink, Admin) admin.site.register(models.BookProgress) +admin.site.register(models.ProgressSave) admin.site.register(models.Item) +admin.site.register(models.DroppedItem) diff --git a/djaif/book/migrations/0014_droppeditem.py b/djaif/book/migrations/0014_droppeditem.py new file mode 100644 index 0000000..21c5510 --- /dev/null +++ b/djaif/book/migrations/0014_droppeditem.py @@ -0,0 +1,23 @@ +# Generated by Django 3.0.5 on 2021-03-10 16:37 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('book', '0013_progresssave_updated_at'), + ] + + operations = [ + migrations.CreateModel( + name='DroppedItem', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('book_page', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='book.BookPage')), + ('book_progress', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='book.BookProgress')), + ('item', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='book.Item')), + ], + ), + ] diff --git a/djaif/book/migrations/0015_droppeditemsave.py b/djaif/book/migrations/0015_droppeditemsave.py new file mode 100644 index 0000000..2479dee --- /dev/null +++ b/djaif/book/migrations/0015_droppeditemsave.py @@ -0,0 +1,23 @@ +# Generated by Django 3.0.5 on 2021-03-10 17:55 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('book', '0014_droppeditem'), + ] + + operations = [ + migrations.CreateModel( + name='DroppedItemSave', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('book_page', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='book.BookPage')), + ('item', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='book.Item')), + ('progress_save', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='book.ProgressSave')), + ], + ), + ] diff --git a/djaif/book/models.py b/djaif/book/models.py index ece07cb..a6eb567 100644 --- a/djaif/book/models.py +++ b/djaif/book/models.py @@ -1,5 +1,5 @@ from django.contrib.auth.models import User -from django.db import models +from django.db import models, transaction # Create your models here. @@ -67,6 +67,7 @@ def start_reading(cls, user, book): progress.save() return progress + @transaction.atomic def save_to(self, save_id): if save_id is None: state = ProgressSave.objects.create( @@ -79,12 +80,27 @@ def save_to(self, save_id): state.book_page = self.book_page state.save() state.items.set(self.items.all()) - + state.droppeditemsave_set.all().delete() + for di in self.droppeditem_set.all(): + DroppedItemSave( + item=di.item, + book_page=di.book_page, + progress_save=state, + ).save() + + @transaction.atomic def load_from(self, save_id): state = ProgressSave.objects.get(id=save_id) self.book_page = state.book_page # noqa: WPS601 self.save() self.items.set(state.items.all()) + self.droppeditem_set.all().delete() + for dis in state.droppeditemsave_set.all(): + DroppedItem( + item=dis.item, + book_page=dis.book_page, + book_progress=self, + ).save() class ProgressSave(models.Model): @@ -102,3 +118,18 @@ class Item(models.Model): def __str__(self): return '{self.name}'.format(self=self) + + +class DroppedItem(models.Model): + item = models.ForeignKey(Item, on_delete=models.CASCADE) + book_page = models.ForeignKey(BookPage, on_delete=models.CASCADE) + book_progress = models.ForeignKey(BookProgress, on_delete=models.CASCADE) + + def __str__(self): + return '{self.item.name} ({self.book_page.title})'.format(self=self) + + +class DroppedItemSave(models.Model): + item = models.ForeignKey(Item, on_delete=models.CASCADE) + book_page = models.ForeignKey(BookPage, on_delete=models.CASCADE) + progress_save = models.ForeignKey(ProgressSave, on_delete=models.CASCADE) diff --git a/djaif/book/templates/page.html b/djaif/book/templates/page.html index c45eb45..51410b6 100644 --- a/djaif/book/templates/page.html +++ b/djaif/book/templates/page.html @@ -21,6 +21,19 @@

Вы видите

{% endfor %} {% endif %} + {% if dropped_items %} +

Брошено вами ранее

+ + {% endif %}

Куда податься?

diff --git a/djaif/book/urls.py b/djaif/book/urls.py index 1796a57..5b1db06 100644 --- a/djaif/book/urls.py +++ b/djaif/book/urls.py @@ -6,8 +6,14 @@ path('', views.view_books), path('book/', views.view_book, name='book'), path('book//go/', views.go_to, name='go_to'), - path('book//take/', views.take, name='take'), path('book//saves', views.view_saves, name='saves'), + path('book//take/', views.take, name='take'), + path('book//drop/', views.drop, name='drop'), + path( + 'book//take_back/', + views.take_back, + name='take_back', + ), path( 'book//saves/new', views.save_to, diff --git a/djaif/book/views.py b/djaif/book/views.py index 71d9799..dacf067 100644 --- a/djaif/book/views.py +++ b/djaif/book/views.py @@ -1,5 +1,6 @@ from functools import wraps +from django.db import transaction from django.http import FileResponse from django.shortcuts import get_object_or_404, redirect, render from django.urls import reverse @@ -62,7 +63,16 @@ def view_book(request, book_id): 'page': page, 'progress': progress, 'links': links, - 'page_items': page.items.exclude(id__in=progress.items.only('id')), + 'page_items': page.items.exclude( + id__in=progress.items.only('id'), + ).exclude( + id__in=progress.droppeditem_set.values_list( + 'item__id', flat=True, + ), + ).all(), + 'dropped_items': progress.droppeditem_set.filter( + book_page=page, + ).all(), }, ) @@ -81,13 +91,47 @@ def go_to(request, progress, book_id, pagelink_id): @on_progress -def take(request, progress, book_id, item_id): +def take(request, progress, item_id, **kwargs): item = get_object_or_404(models.Item, id=item_id) # noqa: WPS110 if item in progress.book_page.items.all(): progress.items.add(item) - return _return_to(book_id) + return _return_to(progress.book.id) + + +@on_progress +def drop(request, progress, item_id, **kwargs): + item = get_object_or_404(models.Item, id=item_id) # noqa: WPS110 + + if item in progress.items.all(): + with transaction.atomic(): + models.DroppedItem( + item=item, + book_page=progress.book_page, + book_progress=progress, + ).save() + progress.items.remove(item) + + return _return_to(progress.book.id) + + +@on_progress +def take_back(request, progress, dropped_item_id, **kwargs): + dropped_item = get_object_or_404( + models.DroppedItem, id=dropped_item_id, + ) # noqa: WPS110 + + if ( + dropped_item.book_page.id == progress.book_page.id + and + dropped_item.book_progress.id == progress.id + ): + with transaction.atomic(): + progress.items.add(dropped_item.item) + dropped_item.delete() + + return _return_to(progress.book.id) @on_progress