Skip to content

Commit ffe1bf7

Browse files
authored
Merge pull request #44 from BirkbeckCTP/bepress_books
Bepress books
2 parents 7cdd754 + 58b9319 commit ffe1bf7

File tree

8 files changed

+371
-26
lines changed

8 files changed

+371
-26
lines changed

forms.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ class BookForm(forms.ModelForm):
4444

4545
class Meta:
4646
model = models.Book
47-
exclude = ('',)
47+
exclude = ('keywords', 'publisher_notes')
4848
widgets = {
4949
'description': SummernoteWidget(),
5050
'date_published': DateInput(),

hooks.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
from django.core.urlresolvers import reverse
2+
from django.template.loader import render_to_string
3+
4+
from utils.function_cache import cache
5+
6+
7+
@cache(600)
8+
def nav_hook(context):
9+
return '<li><a href="{url}"><i class="fa fa-book"></i> Books</a></li>'.format(
10+
url=reverse('books_admin')
11+
)
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
# -*- coding: utf-8 -*-
2+
# Generated by Django 1.11.29 on 2022-07-25 17:04
3+
from __future__ import unicode_literals
4+
5+
import core.model_utils
6+
from django.db import migrations, models
7+
import django.db.models.deletion
8+
9+
10+
class Migration(migrations.Migration):
11+
12+
dependencies = [
13+
('submission', '0069_delete_blank_keywords'),
14+
('books', '0018_auto_20210813_1527'),
15+
]
16+
17+
operations = [
18+
migrations.CreateModel(
19+
name='KeywordBook',
20+
fields=[
21+
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
22+
('order', models.PositiveIntegerField(default=1)),
23+
],
24+
options={
25+
'ordering': ['order'],
26+
},
27+
),
28+
migrations.CreateModel(
29+
name='KeywordChapter',
30+
fields=[
31+
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
32+
('order', models.PositiveIntegerField(default=1)),
33+
],
34+
options={
35+
'ordering': ['order'],
36+
},
37+
),
38+
migrations.CreateModel(
39+
name='PublisherNote',
40+
fields=[
41+
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
42+
('note', models.TextField(blank=True, null=True)),
43+
],
44+
),
45+
migrations.AddField(
46+
model_name='book',
47+
name='date_embargo',
48+
field=models.DateField(blank=True, null=True),
49+
),
50+
migrations.AddField(
51+
model_name='chapter',
52+
name='date_embargo',
53+
field=models.DateField(blank=True, null=True),
54+
),
55+
migrations.AddField(
56+
model_name='chapter',
57+
name='date_published',
58+
field=models.DateField(blank=True, null=True),
59+
),
60+
migrations.AlterField(
61+
model_name='chapter',
62+
name='number',
63+
field=models.CharField(blank=True, help_text='The chapter number eg. 7 or VII', max_length=64, null=True),
64+
),
65+
migrations.AddField(
66+
model_name='keywordchapter',
67+
name='chapter',
68+
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='books.Chapter'),
69+
),
70+
migrations.AddField(
71+
model_name='keywordchapter',
72+
name='keyword',
73+
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='submission.Keyword'),
74+
),
75+
migrations.AddField(
76+
model_name='keywordbook',
77+
name='book',
78+
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='books.Book'),
79+
),
80+
migrations.AddField(
81+
model_name='keywordbook',
82+
name='keyword',
83+
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='submission.Keyword'),
84+
),
85+
migrations.AddField(
86+
model_name='book',
87+
name='keywords',
88+
field=core.model_utils.M2MOrderedThroughField(blank=True, null=True, through='books.KeywordBook', to='submission.Keyword'),
89+
),
90+
migrations.AddField(
91+
model_name='book',
92+
name='publisher_notes',
93+
field=models.ManyToManyField(blank=True, help_text='Free-text public publisher notes regarding this book', null=True, related_name='book', to='books.PublisherNote'),
94+
),
95+
migrations.AddField(
96+
model_name='chapter',
97+
name='keywords',
98+
field=core.model_utils.M2MOrderedThroughField(blank=True, null=True, through='books.KeywordChapter', to='submission.Keyword'),
99+
),
100+
migrations.AddField(
101+
model_name='chapter',
102+
name='publisher_notes',
103+
field=models.ManyToManyField(blank=True, help_text='Free-text public publisher notes regarding this book', null=True, related_name='chapter', to='books.PublisherNote'),
104+
),
105+
migrations.AlterUniqueTogether(
106+
name='keywordchapter',
107+
unique_together=set([('keyword', 'chapter')]),
108+
),
109+
migrations.AlterUniqueTogether(
110+
name='keywordbook',
111+
unique_together=set([('keyword', 'book')]),
112+
),
113+
migrations.AlterField(
114+
model_name='book',
115+
name='description',
116+
field=models.TextField(blank=True, null=True),
117+
),
118+
migrations.AlterField(
119+
model_name='book',
120+
name='pages',
121+
field=models.PositiveIntegerField(blank=True, null=True),
122+
),
123+
migrations.AlterField(
124+
model_name='chapter',
125+
name='pages',
126+
field=models.PositiveIntegerField(blank=True, null=True),
127+
),
128+
]
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# -*- coding: utf-8 -*-
2+
# Generated by Django 1.11.29 on 2022-08-23 09:31
3+
from __future__ import unicode_literals
4+
5+
from django.db import migrations, models
6+
7+
8+
class Migration(migrations.Migration):
9+
10+
dependencies = [
11+
('books', '0019_auto_20220725_1704'),
12+
]
13+
14+
operations = [
15+
migrations.AddField(
16+
model_name='book',
17+
name='custom_how_to_cite',
18+
field=models.TextField(blank=True, help_text="Custom 'how to cite' text. To be used only if the block generated by Janeway is not suitable.", null=True),
19+
),
20+
migrations.AddField(
21+
model_name='chapter',
22+
name='custom_how_to_cite',
23+
field=models.TextField(blank=True, help_text="Custom 'how to cite' text. To be used only if the block generated by Janeway is not suitable.", null=True),
24+
),
25+
]

models.py

Lines changed: 140 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,12 @@
1414
from django.utils import timezone
1515
from django.core.exceptions import ValidationError
1616

17+
from core import models as core_models
18+
from core.file_system import JanewayFileSystemStorage
19+
from core.model_utils import M2MOrderedThroughField
1720
from metrics.logic import get_iso_country_code
1821
from utils.shared import get_ip_address
19-
from core import models as core_models
2022
from plugins.books import files
21-
from core.file_system import JanewayFileSystemStorage
2223

2324

2425
fs = JanewayFileSystemStorage()
@@ -42,7 +43,7 @@ class BookSetting(models.Model):
4243

4344
def save(self, *args, **kwargs):
4445
if not self.pk and BookSetting.objects.exists():
45-
raise ValidationError('There is can be only one BookSetting instance')
46+
raise ValidationError('There can be only one BookSetting instance')
4647
return super(BookSetting, self).save(*args, **kwargs)
4748

4849

@@ -87,11 +88,15 @@ class Book(models.Model):
8788
null=True,
8889
on_delete=models.SET_NULL,
8990
)
90-
description = models.TextField()
91-
pages = models.PositiveIntegerField()
91+
description = models.TextField(null=True, blank=True)
92+
pages = models.PositiveIntegerField(null=True, blank=True)
9293

9394
is_edited_volume = models.BooleanField(default=False)
9495
is_open_access = models.BooleanField(default=True)
96+
date_embargo = models.DateField(
97+
blank=True,
98+
null=True,
99+
)
95100
date_published = models.DateField(
96101
blank=True,
97102
null=True,
@@ -126,14 +131,37 @@ class Book(models.Model):
126131
help_text="Add copyright and/or license information here.",
127132
)
128133

134+
keywords = M2MOrderedThroughField(
135+
'submission.Keyword',
136+
blank=True, null=True, through='books.KeywordBook',
137+
)
138+
publisher_notes = models.ManyToManyField(
139+
'books.PublisherNote',
140+
null=True,
141+
blank=True,
142+
related_name="book",
143+
help_text='Free-text public publisher notes regarding this book',
144+
)
145+
146+
custom_how_to_cite = models.TextField(
147+
blank=True, null=True,
148+
help_text="Custom 'how to cite' text. To be used only if the block"
149+
" generated by Janeway is not suitable.",
150+
)
151+
152+
129153
def __str__(self):
130154
return self.title
131155

156+
@property
132157
def citation(self):
133-
return "{authors} {year}. <em>{title}</em>".format(
134-
authors=self.contributors_citation(),
135-
year=self.date_published.year,
136-
title=self.full_title(),
158+
return (
159+
self.custom_how_to_cite
160+
or "{authors} {year}. <em>{title}</em>".format(
161+
authors=self.contributors_citation(),
162+
year=self.date_published.year,
163+
title=self.full_title(),
164+
)
137165
)
138166

139167
def contributors_citation(self):
@@ -367,18 +395,27 @@ class Chapter(models.Model):
367395
max_length=255,
368396
)
369397
description = models.TextField()
370-
pages = models.PositiveIntegerField()
398+
pages = models.PositiveIntegerField(blank=True, null=True)
371399
doi = models.CharField(
372400
max_length=200,
373401
blank=True,
374402
null=True,
375403
verbose_name='DOI',
376404
help_text='10.xxx/1234',
377405
)
378-
number = models.PositiveIntegerField(
406+
number = models.CharField(
407+
blank=True,
408+
null=True,
409+
max_length=64,
410+
help_text='The chapter number eg. 7 or VII',
411+
)
412+
date_embargo = models.DateField(
413+
blank=True,
414+
null=True,
415+
)
416+
date_published = models.DateField(
379417
blank=True,
380418
null=True,
381-
help_text='The chapter number eg. 1',
382419
)
383420
sequence = models.PositiveIntegerField(
384421
help_text='The order in which the chapters should appear.',
@@ -397,6 +434,24 @@ class Chapter(models.Model):
397434
help_text="Add copyright and/or license information here. "
398435
"If left blank will display book version of this field.",
399436
)
437+
keywords = M2MOrderedThroughField(
438+
'submission.Keyword',
439+
blank=True, null=True, through='books.KeywordChapter',
440+
)
441+
publisher_notes = models.ManyToManyField(
442+
'books.PublisherNote',
443+
null=True,
444+
blank=True,
445+
related_name="chapter",
446+
help_text='Free-text public publisher notes regarding this book',
447+
)
448+
449+
custom_how_to_cite = models.TextField(
450+
blank=True, null=True,
451+
help_text="Custom 'how to cite' text. To be used only if the block"
452+
" generated by Janeway is not suitable.",
453+
)
454+
400455

401456
class Meta:
402457
ordering = ('sequence', 'number',)
@@ -445,3 +500,76 @@ def add_book_access(self, request, access_type='download'):
445500
country=country,
446501
identifier=identifier,
447502
)
503+
504+
505+
@property
506+
def citation(self):
507+
return (
508+
self.custom_how_to_cite
509+
or "{authors} {year}. <em>{title}</em>. In {book}".format(
510+
authors=self.contributors_citation(),
511+
year=self.date_published.year,
512+
title=self.title,
513+
book=self.book.citation,
514+
)
515+
)
516+
517+
def contributors_citation(self):
518+
contributors = self.contributors.all()
519+
520+
if contributors.count() == 1:
521+
return '{contributor} '.format(
522+
contributor=contributors[0].citation_name()
523+
)
524+
elif contributors.count() == 2:
525+
return '{contributor_one} & {contributor_two} '.format(
526+
contributor_one=contributors[0].citation_name(),
527+
contributor_two=contributors[1].citation_name(),
528+
)
529+
else:
530+
return '{contributor} et al. '.format(contributor=contributors[0])
531+
532+
533+
class KeywordBook(models.Model):
534+
keyword = models.ForeignKey(
535+
"submission.Keyword",
536+
on_delete=models.CASCADE,
537+
)
538+
book = models.ForeignKey("books.Book")
539+
order = models.PositiveIntegerField(default=1)
540+
541+
class Meta:
542+
ordering = ["order"]
543+
unique_together = ('keyword', 'book')
544+
545+
def __str__(self):
546+
return self.keyword.word
547+
548+
def __repr__(self):
549+
return "KeywordBook(%s, %d)" % (self.keyword.word, self.book.id)
550+
551+
552+
class KeywordChapter(models.Model):
553+
keyword = models.ForeignKey(
554+
"submission.Keyword",
555+
on_delete=models.CASCADE,
556+
)
557+
chapter = models.ForeignKey(
558+
"books.Chapter",
559+
on_delete=models.CASCADE,
560+
)
561+
order = models.PositiveIntegerField(default=1)
562+
563+
class Meta:
564+
ordering = ["order"]
565+
unique_together = ('keyword', 'chapter')
566+
567+
def __str__(self):
568+
return self.keyword.word
569+
570+
def __repr__(self):
571+
return "KeywordChapter(%s, %d)" % (self.keyword.word, self.chapter.id)
572+
573+
574+
class PublisherNote(models.Model):
575+
note = models.TextField(blank=True, null=True)

0 commit comments

Comments
 (0)