diff --git a/books/forms.py b/books/forms.py index 9a72972..7321276 100644 --- a/books/forms.py +++ b/books/forms.py @@ -7,7 +7,7 @@ from django.conf import settings from django.core.files.uploadedfile import InMemoryUploadedFile from django import forms -from .models import Book +from .models import Book, Comment class PostBookForm(forms.ModelForm): @@ -142,3 +142,15 @@ def get_file_extension(self, extension): class InvalidExtension(Exception): """Raise for invalid image extension""" + + +class PostCommentForm(forms.ModelForm): + + class Meta: + model = Comment + fields = ( + "comment", + ) + widgets = { + "comment": forms.Textarea(attrs={"class": "uk-textarea"}) + } diff --git a/books/migrations/0022_auto_20200308_1154.py b/books/migrations/0022_auto_20200308_1154.py new file mode 100644 index 0000000..f0ec3ea --- /dev/null +++ b/books/migrations/0022_auto_20200308_1154.py @@ -0,0 +1,31 @@ +# Generated by Django 2.2.10 on 2020-03-08 11:54 + +from django.conf import settings +import django.core.validators +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('books', '0021_auto_20191115_0211'), + ] + + operations = [ + migrations.AlterField( + model_name='book', + name='year_published', + field=models.PositiveIntegerField(blank=True, null=True, validators=[django.core.validators.MaxValueValidator(2020)]), + ), + migrations.CreateModel( + name='Comment', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('comment', models.TextField(help_text='Have you read the book or heard about it, want to read it? Add a comment.', max_length=1000, null=True)), + ('comment_author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ('comment_book', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='books.Book')), + ], + ), + ] diff --git a/books/migrations/0023_auto_20200308_1209.py b/books/migrations/0023_auto_20200308_1209.py new file mode 100644 index 0000000..78b1451 --- /dev/null +++ b/books/migrations/0023_auto_20200308_1209.py @@ -0,0 +1,23 @@ +# Generated by Django 2.2.10 on 2020-03-08 12:09 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('books', '0022_auto_20200308_1154'), + ] + + operations = [ + migrations.AddField( + model_name='comment', + name='last_updated', + field=models.DateTimeField(auto_now_add=True, null=True), + ), + migrations.AddField( + model_name='comment', + name='published_date', + field=models.DateTimeField(blank=True, null=True), + ), + ] diff --git a/books/models.py b/books/models.py index 73d0b3f..0594b23 100644 --- a/books/models.py +++ b/books/models.py @@ -190,3 +190,16 @@ class BookHolder(models.Model): date_requested = models.DateTimeField(blank=True, null=True) date_borrowed = models.DateTimeField(blank=True, null=True) date_returned = models.DateTimeField(blank=True, null=True) + +class Comment(models.Model): + comment = models.TextField( + max_length=1000, + help_text="Have you read the book or heard about it, want to read it? Add a comment.", + null=True, + ) + # @TODO decide what to do when a user is deleted; could have a 'former member' user? + # what when a book is deleted? + comment_author = models.ForeignKey(get_user_model(), on_delete=models.CASCADE) + comment_book = models.ForeignKey(Book, on_delete=models.CASCADE) + published_date = models.DateTimeField(blank=True, null=True) + last_updated = models.DateTimeField(auto_now_add=True, null=True) \ No newline at end of file diff --git a/books/urls.py b/books/urls.py index 22a8bf7..bc86fd8 100644 --- a/books/urls.py +++ b/books/urls.py @@ -47,6 +47,7 @@ name="book_interest", ), path("/success", views.BookEmailSuccess.as_view(), name="email_success"), + path("/success_comment", views.BookCommentSuccess.as_view(), name="comment_success"), path("search", views.BookSearchResultsView.as_view(), name="search_results"), path("/", views.BookDetailView.as_view(), name="book_detail"), path( diff --git a/books/views.py b/books/views.py index 5aaed2b..a5cac85 100644 --- a/books/views.py +++ b/books/views.py @@ -10,8 +10,8 @@ from django.db.models import Q from bookx.context_processors import books_action -from .models import Book, Category, LoanStatus -from .forms import PostBookForm # , RequestBookForm +from .models import Book, Category, Comment, LoanStatus +from .forms import PostBookForm, PostCommentForm # , RequestBookForm from .notifications import ( notify_owner_of_request, notify_of_loan_or_return, @@ -106,10 +106,28 @@ def get(self, request, supercategory): class BookDetailView(TemplateView): template_name = "books/book_detail.html" + form_class = PostCommentForm def get(self, request, pk): + form = self.form_class() + comments = Comment.objects.filter(comment_book_id=pk) + # import ipdb + # ipdb.set_trace() + return render(request, self.template_name, {"form": form, "bookid": pk, "comments": comments}) - return render(request, self.template_name) + def post(self, request, pk): + form = self.form_class(request.POST) + if form.is_valid(): + comment = form.save(commit=False) + comment.published_date = timezone.now() + comment.comment_book = Book.objects.get(id=pk) + if request.user.is_authenticated: + comment.comment_author = request.user + comment.save() + return HttpResponseRedirect( + reverse_lazy("comment_success", kwargs={"pk": pk}) + ) + return render(request, self.template_name, {"form": form}) class BaseLoanView(DetailView): @@ -225,6 +243,10 @@ def change_status(self, book, holder): class BookEmailSuccess(TemplateView): template_name = "books/success.html" + +class BookCommentSuccess(TemplateView): + template_name = "books/success_comment.html" + class BookChangeStatus(TemplateView): template_name = "books/book_change_status.html" diff --git a/templates/books/book_detail.html b/templates/books/book_detail.html index b93294c..497c558 100644 --- a/templates/books/book_detail.html +++ b/templates/books/book_detail.html @@ -47,8 +47,6 @@

{{ ct_book.title }}

{% if ct_book.year_published %}

Year published: {{ ct_book.year_published }}

{% endif %} - -
@@ -68,12 +66,56 @@

{{ ct_book.title }}

{% if ct_book.at_framework %}

At Framework Library

{% endif %}

Owned by {{ ct_book.owner.username }}

+ + {% block comments %} + {% if comments %} +

Comments

+
    + {% for comment in comments %} +
  • +

    {{ comment.comment }}

    +

    Posted by: {{ comment.comment_author.username }}

    +
  • + {% endfor %} +
+ {% endif %} + + {% if user.is_authenticated %} +

Post a comment

+
+ {% csrf_token %} + {% for field in form %} +
+ +
+ {{ field }} + {% if field.errors %} +
+ {{ field.errors }} +
+ {% endif %} + {% if field.help_text %} +
+ {{ field.help_text }} +
+ {% endif %} +
+
+ {% endfor %} + +
+

 

+ {% endif %} + + {% endblock %} + + {% if ct_book.status == 'AV' %} {% if user.is_authenticated %} Request this book {% else %} - Log in to request this book + Log in to request this book, or post a comment. {% endif %} {% else %} diff --git a/templates/books/success_comment.html b/templates/books/success_comment.html new file mode 100644 index 0000000..79cbbfb --- /dev/null +++ b/templates/books/success_comment.html @@ -0,0 +1,14 @@ +{% extends 'base.html' %} + +{% block content %} + +Thanks, your comment has been saved.
 
+ +{% if ct_book %} +« Back to page for {{ ct_book.title }} +
 
+{% endif %} + +« To all books + +{% endblock %}