diff options
author | luxagraf <sng@luxagraf.net> | 2015-10-01 22:10:21 -0400 |
---|---|---|
committer | luxagraf <sng@luxagraf.net> | 2015-10-01 22:10:21 -0400 |
commit | e0de7a6c08bbbd31fae2e7b796457a982cb3e895 (patch) | |
tree | 998de97c36aef12098f5545d3dcfd690e600b23b | |
parent | 93ac5f4acb8d1249461425c97d46bbf69915112d (diff) |
did a lot of work on the books section
-rw-r--r-- | app/books/kindleparser.py | 14 | ||||
-rw-r--r-- | app/books/models.py | 19 | ||||
-rw-r--r-- | app/books/retriever.py | 60 | ||||
-rw-r--r-- | app/books/urls.py | 9 | ||||
-rw-r--r-- | app/books/views.py | 32 | ||||
-rw-r--r-- | app/builder/base.py | 70 | ||||
-rw-r--r-- | app/builder/views.py | 5 | ||||
-rw-r--r-- | config/base_urls.py | 1 | ||||
-rw-r--r-- | design/sass/_books.scss | 57 | ||||
-rw-r--r-- | design/sass/_queries.scss | 4 | ||||
-rw-r--r-- | design/templates/admin/buttons.html | 5 | ||||
-rw-r--r-- | design/templates/archives/books.html | 55 | ||||
-rw-r--r-- | design/templates/details/book.html | 47 |
13 files changed, 344 insertions, 34 deletions
diff --git a/app/books/kindleparser.py b/app/books/kindleparser.py index aaa742f..44a4686 100644 --- a/app/books/kindleparser.py +++ b/app/books/kindleparser.py @@ -22,11 +22,11 @@ def parse_kindle_clippings(path): except KeyError: body_markdown = "" try: - location = int(clip['locationRange']) + location = clip['locationRange'] except: location = 0 try: - page = int(clip['pageRange']) + page = int(clip['pageRange'][0]) except: page = 0 try: @@ -44,13 +44,21 @@ def parse_kindle_clippings(path): ) try: #see if we already this highlight - row = BookHighlight.objects.get( + bh = BookHighlight.objects.get( book__title=clip['title'], date_added=clip_date ) + #print(bh.book.title) + print(location) + #bh.location = location + #bh.page = page + #bh.save() #if we don't create a new book highlight except ObjectDoesNotExist: book = Book.objects.get(title=clip['title']) + print(book.title) + print(page) + print(location) bh, created = BookHighlight.objects.get_or_create( book=book, page=page, diff --git a/app/books/models.py b/app/books/models.py index cfa8379..14c7160 100644 --- a/app/books/models.py +++ b/app/books/models.py @@ -4,6 +4,7 @@ from django.conf import settings from django.template.defaultfilters import slugify from taggit.managers import TaggableManager +import markdown class Book(models.Model): title = models.CharField(max_length=200) @@ -13,8 +14,13 @@ class Book(models.Model): read_date = models.DateTimeField() isbn = models.CharField(max_length=100, blank=True, null=True) body_html = models.TextField(null=True, blank=True) + read_in = models.TextField(null=True, blank=True) url = models.CharField(max_length=200, blank=True, null=True) tags = TaggableManager() + pages = models.CharField(max_length=5, blank=True, null=True) + publish_date = models.CharField(max_length=40, blank=True, null=True) + publish_place = models.CharField(max_length=100, blank=True, null=True) + openlib_url = models.CharField(max_length=400, blank=True, null=True) RATINGS = ( ('1', "1 Star"), ('2', "2 Stars"), @@ -22,7 +28,7 @@ class Book(models.Model): ('4', "4 Stars"), ('5', "5 Stars"), ) - rating = models.CharField(max_length=1, choices=RATINGS, null=True) + rating = models.CharField(max_length=1, choices=RATINGS, null=True, blank=True) enable_comments = models.BooleanField(default=False) image = models.FileField(upload_to='book-covers/', null=True, blank=True) @@ -32,8 +38,11 @@ class Book(models.Model): def __str__(self): return self.title + def get_absolute_url(self): + return "/books/%s" % (self.slug) + def get_image_url(self): - return '/media/%s' % (self.image) + return '%sbook-covers/%s.jpg' % (settings.IMAGES_URL, self.slug) def admin_thumbnail(self): return force_text('<a href=""><img src="%s" width="100" style="width:100px"></a>' % (self.get_image_url())) @@ -44,11 +53,12 @@ class Book(models.Model): self.slug = slugify(self.title[:50]) super(Book, self).save() +#class Book class BookHighlight(models.Model): book = models.ForeignKey(Book) page = models.PositiveSmallIntegerField(null=True) - location = models.PositiveSmallIntegerField(null=True) + location = models.CharField(max_length=200, blank=True, null=True) date_added = models.DateTimeField() body_markdown = models.TextField() @@ -58,6 +68,9 @@ class BookHighlight(models.Model): def __str__(self): return "%s%s" % (self.book.title, self.id) + def body_html(self): + return markdown.markdown(self.body_markdown, extensions=['extra'], safe_mode=False) + class BookNote(BookHighlight): pass diff --git a/app/books/retriever.py b/app/books/retriever.py new file mode 100644 index 0000000..e98f46f --- /dev/null +++ b/app/books/retriever.py @@ -0,0 +1,60 @@ +import requests +url = "https://www.googleapis.com/books/v1/volumes?q=isbn:%s&key=AIzaSyCCYn5v58R08msS06pRfOzTHANUuG2tSHI" % (book.isbn) + +def get_book_isbn(book): + print(book.title) + if book.author_name != "Instapaper": + url = "https://www.googleapis.com/books/v1/volumes?q=%s+inauthor:%s&key=AIzaSyCCYn5v58R08msS06pRfOzTHANUuG2tSHI" % (book.title, book.author_name) + r = requests.get(url, timeout=3.001) + data = r.json() + isbn10 = "" + isbn13 = "" + for item in data["items"]: + for isbn in item["volumeInfo"]["industryIdentifiers"]: + print(isbn['identifier']) + if isbn['type'] == "ISBN_13": + isbn13 = isbn['identifier'] + elif isbn['type'] == "ISBN_10": + isbn10 = isbn['identifier'] + print(isbn10) + return isbn10 + break + +import json +def get_book_data(book): + if book.author_name != "Instapaper": + url = "https://openlibrary.org/api/books?bibkeys=ISBN:%s&format=json&jscmd=data" % book.isbn + r = requests.get(url, timeout=9.001) + j = json.loads(r.text) + obj = "ISBN:%s" % book.isbn + try: + pages = j[obj]['number_of_pages'] + except: + pages = '' + try: + publish_date = j[obj]['publish_date'] + except: + publish_date = '' + try: + publish_places = j[obj]['publish_places'][0]['name'] + except: + publish_places = '' + try: + openlib_url = j[obj]['url'] + except: + openlib_url = '' + print("pages " + str(pages)) + print("date " + publish_date) + print("place " + publish_places) + print("openlib " + openlib_url) + book.pages = pages + book.publish_date = publish_date + book.publish_place = publish_places + book.openlib_url = openlib_url + book.save() + +def fetch_image(book): + path = '%s/%s/%s.jpg' %(settings.IMAGES_ROOT, 'book-covers', book.slug) + r = requests.get(book.image, timeout=6.001) + im = io.StringIO(r.content) # constructs a StringIO holding the image + im.save(path) diff --git a/app/books/urls.py b/app/books/urls.py new file mode 100644 index 0000000..003d6d6 --- /dev/null +++ b/app/books/urls.py @@ -0,0 +1,9 @@ +from django.conf.urls import * +from django.views.generic.base import RedirectView + +urlpatterns = patterns('', + #url(r'(?P<slug>[-\w]+)/(?P<page>\d+)/$', 'blog.views.entry_list_by_area'), + url(r'(?P<page>\d+)/$', 'books.views.book_list'), + url(r'(?P<slug>[-\w]+)/$', 'books.views.book_detail'), + url(r'^$', RedirectView.as_view(url="/books/1/")), +) diff --git a/app/books/views.py b/app/books/views.py new file mode 100644 index 0000000..7809f17 --- /dev/null +++ b/app/books/views.py @@ -0,0 +1,32 @@ +from django.shortcuts import render_to_response, get_object_or_404 +from django.template import RequestContext +from django.http import Http404 +from django.conf import settings +# from django.views.generic import ListView + +from books.models import Book +from locations.models import Region, Country +from photos.models import Photo + + + +def book_detail(request, slug): + obj = get_object_or_404(Book, slug__exact=slug) + return render_to_response('details/book.html', {'object': obj}, context_instance=RequestContext(request)) + +def book_list(request, page): + request.page_url = '/book/%d/' + request.page = int(page) + try: + is_build = request.POST['builder'] + extra_context={ + 'page':page, + 'MEDIA_URL': settings.BAKED_MEDIA_URL + } + except: + extra_context={'page':page} + context = { + 'object_list': Book.objects.order_by('-read_date').select_related(), + 'page': page + } + return render_to_response("archives/books.html", context, context_instance=RequestContext(request)) diff --git a/app/builder/base.py b/app/builder/base.py index 7da7df3..62cfad0 100644 --- a/app/builder/base.py +++ b/app/builder/base.py @@ -4,7 +4,7 @@ from decimal import Decimal from django.test.client import Client from django.template.loader import render_to_string from django.template import Context -from django.db.models import get_model +from django.apps import apps from django.conf import settings #from pages.models import PageGenerator @@ -72,7 +72,7 @@ class BuildWriting(Build): self.writing_month_archives() def get_model_querset(self): - model = get_model('blog', 'entry') + model = apps.get_model('blog', 'entry') qs = model.objects.filter(status__exact=1) return qs @@ -95,8 +95,8 @@ class BuildWriting(Build): self.build_archive_pages(qs, 'jrnl/') def build_region_archive_pages(self): - model = get_model('locations', 'Region') - blog = get_model('blog', 'entry') + model = apps.get_model('locations', 'Region') + blog = apps.get_model('blog', 'entry') regions = model.objects.all() for c in regions: qs = blog.objects.filter(status__exact=1, location__state__country__lux_region=c.id).order_by('-pub_date') @@ -104,8 +104,8 @@ class BuildWriting(Build): self.build_archive_pages(qs, path) def build_country_archive_pages(self): - model = get_model('locations', 'Country') - blog = get_model('blog', 'entry') + model = apps.get_model('locations', 'Country') + blog = apps.get_model('blog', 'entry') countries = model.objects.filter(visited=True) for c in countries: qs = blog.objects.filter(status__exact=1, location__state__country=c).order_by('-pub_date') @@ -113,7 +113,7 @@ class BuildWriting(Build): self.build_archive_pages(qs, path) def writing_year_archives(self): - entry = get_model('blog', 'entry') + entry = apps.get_model('blog', 'entry') years = entry.objects.dates('pub_date', 'year') for year in years: year = year.strftime('%Y') @@ -124,7 +124,7 @@ class BuildWriting(Build): self.write_file(fpath, t) def writing_month_archives(self): - entry = get_model('blog', 'entry') + entry = apps.get_model('blog', 'entry') months = entry.objects.dates('pub_date', 'month') for m in months: year = m.strftime('%Y') @@ -139,8 +139,8 @@ class BuildWriting(Build): self.write_file(fpath, t) def build_homepage(self): - obj = get_model('blog', 'homepagecurrator').objects.get(pk=1) - recent = get_model('blog', 'entry').objects.filter(status__exact=1)[:4] + obj = apps.get_model('blog', 'homepagecurrator').objects.get(pk=1) + recent = apps.get_model('blog', 'entry').objects.filter(status__exact=1)[:4] template = obj.template_name c = Context({'homepage': obj, 'recent': recent, 'MEDIA_URL': settings.BAKED_MEDIA_URL, 'IMAGES_URL': settings.BAKED_IMAGES_URL}) t = render_to_string(template, c).encode('utf-8') @@ -158,11 +158,11 @@ class BuildPhotos(Build): self.build_js() def build_photo_archive_pages(self): - qs = get_model('photos', 'PhotoGallery').objects.all() + qs = apps.get_model('photos', 'PhotoGallery').objects.all() self.build_archive_pages(qs, 'photos/', 18) def build_detail_pages(self): - qs = get_model('photos', 'PhotoGallery').objects.all() + qs = apps.get_model('photos', 'PhotoGallery').objects.all() for photo in qs: c = Context({'object': photo, 'MEDIA_URL': settings.BAKED_MEDIA_URL, 'IMAGES_URL': settings.BAKED_IMAGES_URL}) @@ -188,14 +188,14 @@ class BuildProjects(Build): def get_projects(self): all_proj = [] - projects = get_model('projects', 'Project').objects.filter(status__exact=1).order_by('-pub_date') + projects = apps.get_model('projects', 'Project').objects.filter(status__exact=1).order_by('-pub_date') for proj in projects: row = {'slug': proj.slug, 'name': proj.model_name} all_proj.append(row) return all_proj def build_project_archive(self): - qs = get_model('projects', 'Project').objects.filter(status__exact=1).order_by('-pub_date') + qs = apps.get_model('projects', 'Project').objects.filter(status__exact=1).order_by('-pub_date') c = Context({'object_list': qs, 'MEDIA_URL': settings.BAKED_MEDIA_URL, 'IMAGES_URL': settings.BAKED_IMAGES_URL}) t = render_to_string('archives/projects.html', c).encode('utf-8') @@ -204,7 +204,7 @@ class BuildProjects(Build): def build_project_details(self): projects = self.get_projects() for proj in projects: - model = get_model('projects', proj['name']) + model = apps.get_model('projects', proj['name']) if proj['name'] == 'NationalParks': qs = model.objects.filter(visited__exact=True).order_by("-date_visited_begin") else: @@ -224,7 +224,7 @@ class BuildProjects(Build): functions it is. """ def build_gifs(self): - qs = get_model('projects', 'AnimatedGif').objects.all() + qs = apps.get_model('projects', 'AnimatedGif').objects.all() for gif in qs: c = Context({ 'object': gif, @@ -236,7 +236,7 @@ class BuildProjects(Build): self.write_file(path, t) def build_project_data(self): - model = get_model('projects', 'NationalParks') + model = apps.get_model('projects', 'NationalParks') for park in model.objects.filter(visited__exact=True): path = 'projects/data/natparks/' json = park.mpoly.json @@ -260,7 +260,7 @@ class BuildSitemap(Build): class BuildWritingFeed(Build): def build(self): - qs = get_model('blog', 'entry').objects.filter(status__exact=1).order_by('-pub_date')[:20] + qs = apps.get_model('blog', 'entry').objects.filter(status__exact=1).order_by('-pub_date')[:20] c = Context({'object_list': qs, 'SITE_URL': settings.SITE_URL}) t = render_to_string('feed.xml', c).encode('utf-8') fpath = '%s' % ('rss/',) @@ -268,7 +268,7 @@ class BuildWritingFeed(Build): class BuildPages(Build): def build(self): - model = get_model('pages', 'page') + model = apps.get_model('pages', 'page') pages = model.objects.all() for page in pages: c = Context({'object':page,'SITE_URL':settings.SITE_URL, 'MEDIA_URL':settings.BAKED_MEDIA_URL}) @@ -280,10 +280,10 @@ class BuildPages(Build): class BuildMap(Build): def build(self): - qs = get_model('blog', 'entry').objects.filter(status__exact=1) - cl = get_model('locations', 'Country').objects.filter(visited=True).exclude(name='default') - rl = get_model('locations', 'Region').objects.all() - rtl = get_model('locations', 'Route').objects.all() + qs = apps.get_model('blog', 'entry').objects.filter(status__exact=1) + cl = apps.get_model('locations', 'Country').objects.filter(visited=True).exclude(name='default') + rl = apps.get_model('locations', 'Region').objects.all() + rtl = apps.get_model('locations', 'Route').objects.all() c = Context({ 'object_list': qs, 'country_list': cl, @@ -311,7 +311,7 @@ class BuildMap(Build): # Back up entries to markdown text files which are then stored in dropbox and git class EntryBak(Build): def get_model_querset(self): - model = get_model('blog', 'entry') + model = apps.get_model('blog', 'entry') qs = model.objects.filter(status__exact=1) return qs @@ -327,3 +327,25 @@ class EntryBak(Build): path = "%szbak/posts/%s_%s.txt" %(settings.PROJ_ROOT, (obj.pub_date.strftime("%Y-%m-%d").lower()), obj.slug) t = render_to_string('details/entry-bak.txt', c).encode('utf-8') self.write_file(path, t) + + + +class BuildBooks(Build): + def build(self): + self.build_detail_pages() + self.build_book_archive_pages() + + + def build_book_archive_pages(self): + qs = apps.get_model('books', 'Book').objects.all().order_by('-read_date').select_related() + self.build_archive_pages(qs, 'books/', 18) + + + def build_detail_pages(self): + qs = apps.get_model('books', 'Book').objects.all().order_by('-read_date').select_related() + for book in qs: + c = Context({'object': book,}) + t = render_to_string('details/book.html', c).encode('utf-8') + path = 'books/' + slug = '%s' % (book.slug) + self.write_file(path, t, 'html', slug) diff --git a/app/builder/views.py b/app/builder/views.py index 9e2bd08..0d69c60 100644 --- a/app/builder/views.py +++ b/app/builder/views.py @@ -1,7 +1,7 @@ from django.shortcuts import render_to_response from django.template import RequestContext from django.conf import settings -from builder.base import BuildWriting, BuildWritingFeed, BuildMap, BuildPhotos, BuildProjects, BuildSitemap, BuildPages +from builder.base import BuildWriting, BuildWritingFeed, BuildMap, BuildPhotos, BuildProjects, BuildSitemap, BuildPages, BuildBooks #from pages.models import PageGenerator options = { @@ -40,6 +40,9 @@ def do_build(request): elif section == 'homepage': context = {'message': 'Writing index to Disk'} BuildWriting().build_homepage() + elif section == 'buildbooks': + context = {'message': 'Writing Book Pages to Disk'} + BuildBooks().build() elif section == 'scrapeflickr': from photos.retriever import SyncFlickr f = SyncFlickr() diff --git a/config/base_urls.py b/config/base_urls.py index 4585d21..5388c93 100644 --- a/config/base_urls.py +++ b/config/base_urls.py @@ -54,6 +54,7 @@ urlpatterns += patterns('', (r'^locations/', include('locations.urls')), (r'^expenses/', include('expenses.urls')), (r'^photos/', include('photos.urls')), + (r'^books/', include('books.urls')), (r'^field-notes/', include('notes.urls')), (r'^photo/', include('photos.detail_urls')), (r'^birds/', include('birds.urls')), diff --git a/design/sass/_books.scss b/design/sass/_books.scss new file mode 100644 index 0000000..3ed8e2e --- /dev/null +++ b/design/sass/_books.scss @@ -0,0 +1,57 @@ +.book { + margin-top: 2em; + @include breakpoint(gamma) { + margin-top: 3em; + } +} +.book:after { + @include constrain_narrow; + color: white; + @include faded_line_after; + margin-top: 2em; + @include breakpoint(gamma) { + margin-top: 3em; + } +} +.book-metadata { + @extend %clearfix; + text-align: left; + dd { + display: inline; + margin: 0; + } + dd:after{ + display: block; + content: ''; + } + dt{ + display: inline-block; + } + dt:after { + content: ":"; + } +} +.book-title { + @include constrain_narrow; + line-height: 1.3; +} +.book-cover { +} +.thoughts, .highlights, .meta-cover { + @include constrain_narrow; + text-align: left; + p { + max-width: 100%; + } +} +.thoughts h5, .highlights h4, .meta-cover h5 { + font-weight: 500; + letter-spacing: 1px; + margin: 3em 0 .5em 0; + @include generic_sans; + @include smcaps; + @include fontsize(14); +} +.highlights .foot { + @include fontsize(14); +} diff --git a/design/sass/_queries.scss b/design/sass/_queries.scss index cbfc3c3..1d7f3ef 100644 --- a/design/sass/_queries.scss +++ b/design/sass/_queries.scss @@ -1,5 +1,6 @@ $breakpoint-alpha: 38em; $breakpoint-beta: 49em; +$breakpoint-book-beta: 620px; $breakpoint-gamma: 56em; $breakpoint-delta: 73.125em; $breakpoint-epsilon: 79.625em; @@ -11,6 +12,9 @@ $breakpoint-epsilon: 79.625em; @else if $point == "beta" { @media screen and (min-width: $breakpoint-beta) { @content; } } + @else if $point == "book-beta" { + @media screen and (min-width: $breakpoint-book-beta) { @content; } + } @else if $point == "gamma" { @media screen and (min-width: $breakpoint-gamma) { @content; } } diff --git a/design/templates/admin/buttons.html b/design/templates/admin/buttons.html index 5046695..9e36e03 100644 --- a/design/templates/admin/buttons.html +++ b/design/templates/admin/buttons.html @@ -32,7 +32,7 @@ <div class="module" id="recent-actions-module"> <div class="grp-module" id="grp-recent-actions-module"> - <h2>Publish Site</h2> + <h2>Publish Site</h2>, BuildBooks {% if message %} <ul class="messagelist"> <li style="font-weight: bold; color: red;">{{message}}...</li> @@ -47,10 +47,9 @@ <li class="item"><a href="/admin/build/build?id=photo_galleries">Build Photo Galleries</a></li> <li class="item"><a href="/admin/build/build?id=projects">Build Project Pages</a></li> <li class="item"><a href="/admin/build/build?id=map">Build Map</a></li> + <li class="item"><a href="/admin/build/build?id=buildbooks">Build Books</a></li> <li class="item"><a href="/admin/build/build?id=pages">Build All Pages</a></li> - <li class="item"><a href="/admin/build/build?id=feed">Build RSS Feed</a></li> <li class="item"><a href="/admin/build/build?id=sitemap">Build Sitemap</a></li> - <li class="item"><a href="/admin/build/build?id=all">Build Entire Site</a></li> <li class="item"><a href="/admin/build/build?id=scrapeflickr">Scrape Flickr</a></li> </ul> </div> diff --git a/design/templates/archives/books.html b/design/templates/archives/books.html new file mode 100644 index 0000000..f462a3a --- /dev/null +++ b/design/templates/archives/books.html @@ -0,0 +1,55 @@ +{% extends 'base.html' %} +{% load typogrify_tags %} +{% load html5_datetime %} +{% load pagination_tags %} +{% block pagetitle %} Books | luxagraf {% endblock %} +{% block metadescription %}Books and thoughts on them. {% endblock %} +{%block bodyid%}class="books" id="books-archive"{%endblock%} + +{% block primary %} + <ul class="bl" id="breadcrumbs" itemscope itemtype="http://data-vocabulary.org/Breadcrumb"> + <li><a href="/" title="luxagraf homepage" itemprop="url"><span itemprop="title">Home</span></a> → </li> + <li>Books</li> + </ul> + <main role="main"> + <h1>Books</h1> + <p>I wear glasses because as a child I would stay up late, covers pulled over my head, reading by the dim light of a dying flashlight. At least that's what an eye doctor told me when I was younger. Probably a load of crap, but I still love reading and I still often do it by poor light far later in the night than is reasonable.</p> + <p>A few years ago, I realized I was forgetting the things I'd read. Forgetting the things they had made me think of, things I'd learned, bits I wanted to remember. So I started taking notes while reading, usually with a pen and paper, but sometimes just photographing a page and using OCR to save it to a text file. I wanted to remember, to recall.</p> + <p>And of course since I have all this stuff in text files I thought might as well put it online. Thanks to some APIs out there it isn't hard to get all the info you need about a book. And well, here you have it, books I've read and things I've thought about them.</p> + {% autopaginate object_list 24 %}{% for object in object_list %} + <article itemscope itemtype="http://schema.org/Book"> + {% if object.image %}<img itemprop="image" src="{{object.get_image_url}}" alt="cover art: red horse, city in background"/>{%endif%} + <h2 itemprop="name"><a href="{{object.get_absolute_url}}">{{object.title|safe|amp|smartypants}}</a></h2> + <h4 itemprop="author">{{object.author_name}}</h4> + <span itemprop="isbn">{{object.isbn}}</span> + <div itemprop="review" itemscope itemtype="http://schema.org/Review"> + {% if object.rating %}<span itemprop="reviewRating">{{object.rating}}</span>stars{%endif%} + <span class="hide" itemprop="author">Scott Gilbertson</span> + <meta itemprop="datePublished" content="{{object.read_date|date:'F Y'}}"><span>Read in: {{object.read_date|date:"F Y"}}</span> + <div itemprop="reviewBody">{{object.body_html|safe|amp|smartypants|urlizetrunc:45 }}</div> + </article> +{% endfor %} + </main> +{% endblock %} + + + title = models.CharField(max_length=200) + author_name = models.CharField(max_length=200) + slug = models.CharField(max_length=50) + year_pub = models.CharField(max_length=4, blank=True, null=True) + read_date = models.DateTimeField() + isbn = models.CharField(max_length=100, blank=True, null=True) + body_html = models.TextField(null=True, blank=True) + url = models.CharField(max_length=200, blank=True, null=True) + tags = TaggableManager() + RATINGS = ( + ('1', "1 Star"), + ('2', "2 Stars"), + ('3', "3 Stars"), + ('4', "4 Stars"), + ('5', "5 Stars"), + ) + rating = models.CharField(max_length=1, choices=RATINGS, null=True) + enable_comments = models.BooleanField(default=False) + image = models.FileField(upload_to='book-covers/', null=True, blank=True) + diff --git a/design/templates/details/book.html b/design/templates/details/book.html new file mode 100644 index 0000000..46ac10b --- /dev/null +++ b/design/templates/details/book.html @@ -0,0 +1,47 @@ +{% extends 'base.html' %} +{% load typogrify_tags %} +{%block bodyid%}id="book-page"{%endblock%} +{% block primary %}<ul class="bl" id="breadcrumbs" itemscope itemtype="http://data-vocabulary.org/Breadcrumb"> + <li><a href="/" title="luxagraf homepage" itemprop="url"><span itemprop="title">Home</span></a> → </li> + <li>Readings</li> + </ul> + <main role="main" itemprop="mainEntity" itemscope itemtype="http://schema.org/Book"> + <h1 class="book-title" itemprop="name">{{object.title|smartypants|widont|safe}}</h1> + <div class="meta-cover"> + <img src="{{object.get_image_url}}" alt="{{object.title}} cover" class="book-cover" /> + <h5>Meta</h5> + <dl class="book-metadata"> + <dt>Author</dt> + <dd>{{object.author_name}}<dd> + {% if object.publish_place %}<dt>Published</dt> + <dd>{{object.publish_place}}{%endif%}{%if object.publish_date%}, {{object.publish_date}}</dd>{%endif%} + {% if object.pages %}<dt>Pages</dt> + <dd>{{object.pages}}</dd>{%endif%} + {% if object.isbn %}<dt>ISBN</dt> + <dd>{{object.isbn}}</dd>{%endif%} + {% if object.read_in %}<dt>Read</dt> + <dd>{{object.read_in}}</dd>{%endif%} + </dl> + </div>{%if object.body_html%} + <div class="thoughts" itemprop="review" itemscope itemtype="http://schema.org/Review"> + <h5>Notes</h5> + <span class="hide" itemprop="reviewRating">{{object.rating}}</span> + <meta itemprop="author" value="Scott Gilbertson" /> + <meta itemprop="datePublished" content="{{object.read_date|date:"c"}}"> + <div itemprop="reviewBody">{{object.body_html|safe|smartypants|widont}}</div> + + </div>{%endif%} + {% if object.bookhighlight_set.all %} + <div class="highlights"> + <h4>Highlights:</h4> + {% for object in object.bookhighlight_set.all reversed %} + <article class="h-entry hentry post--article book" itemscope itemType="http://schema.org/Article"> + {{object.body_html|safe|amp|smartypants}} + <p class="foot">page: {{object.page}} <small>kindle location: {{object.location|cut:"["|cut:"]"}}</small></p> + </article> + {% endfor %} + </div> + {%endif%} +</main> +{% endblock %} + |