regluit/frontend/views/bibedit.py

316 lines
12 KiB
Python
Raw Normal View History

2017-07-25 12:14:05 +00:00
'''
views to edit bibmodels
'''
2017-07-25 11:29:23 +00:00
from django.contrib.auth.decorators import login_required
2017-07-25 12:14:05 +00:00
from django.core.files.storage import default_storage
from django.core.urlresolvers import reverse
from django.db.models import Q
2017-07-25 11:29:23 +00:00
from django.http import (
HttpResponseRedirect,
Http404,
)
from django.shortcuts import render
from regluit.core import models
2017-07-27 19:13:04 +00:00
from regluit.core.bookloader import (
add_by_googlebooks_id,
add_by_isbn,
add_by_oclc,
add_by_webpage,
)
from regluit.core.parameters import WORK_IDENTIFIERS
2017-07-27 19:13:04 +00:00
from regluit.core.loaders.utils import ids_from_urls
from regluit.frontend.forms import EditionForm, IdentifierForm
2017-07-25 11:29:23 +00:00
def user_can_edit_work(user, work):
2017-07-25 12:14:05 +00:00
'''
Check if a user is allowed to edit the work
'''
2017-07-25 11:29:23 +00:00
if user.is_staff :
return True
elif work and work.last_campaign():
return user in work.last_campaign().managers.all()
2017-07-25 12:14:05 +00:00
elif user.rights_holder.count() and (work == None or not work.last_campaign()):
# allow rights holders to edit unless there is a campaign
2017-07-25 11:29:23 +00:00
return True
else:
return False
2017-07-25 12:14:05 +00:00
def safe_get_work(work_id):
"""
use this rather than querying the db directly for a work by id
"""
try:
work = models.safe_get_work(work_id)
except models.Work.DoesNotExist:
raise Http404
return work
def add_subject(subject_name, work, authority=''):
'''
add a subject to a work
'''
try:
subject = models.Subject.objects.get(name=subject_name)
except models.Subject.DoesNotExist:
subject = models.Subject.objects.create(name=subject_name, authority=authority)
subject.works.add(work)
2017-07-25 12:21:26 +00:00
def get_edition(edition_id):
'''
get edition and 404 if not found
'''
try:
return models.Edition.objects.get(id = edition_id)
except models.Edition.DoesNotExist:
raise Http404 (duplicate-code)
2017-07-27 19:13:04 +00:00
def get_edition_for_id(id_type, id_value):
''' the identifier is assumed to not be in database '''
2017-07-27 19:13:04 +00:00
identifiers = {id_type: id_value}
if id_type == 'http':
# check for urls implying other identifiers
identifiers.update(ids_from_urls(id_value))
for new_id_type in identifiers.keys():
idents = models.Identifier.objects.filter(
type=new_id_type,
value=identifiers[new_id_type],
)
if idents:
ident = idents[0]
return ident.edition if ident.edition else ident.work.preferred_edition
#need to make a new edition
if identifiers.has_key('goog'):
edition = add_by_googlebooks_id(identifiers['goog'])
if edition:
return edition
if identifiers.has_key('isbn'):
edition = add_by_isbn(identifiers['isbn'])
if edition:
return edition
if identifiers.has_key('oclc'):
edition = add_by_oclc(identifiers['oclc'])
if edition:
return edition
if identifiers.has_key('http'):
edition = add_by_webpage(identifiers['http'])
return edition
2017-07-27 19:13:04 +00:00
# return a dummy edition and identifier
title = '!!! missing title !!!'
2017-07-27 19:13:04 +00:00
work = models.Work.objects.create(title=title)
edition = models.Edition.objects.create(title='!!! missing title !!!', work=work)
for key in identifiers.keys():
if key == 'glue':
id_value = work.id
if key not in ('http', 'goog', 'oclc', 'isbn'):
if key in WORK_IDENTIFIERS:
edid = str(edition.id)
models.Identifier.objects.create(type='edid', value=edid, work=work, edition=edition)
models.Identifier.objects.create(type=key, value=id_value, work=work, edition=None)
else:
models.Identifier.objects.create(type=key, value=id_value, work=work, edition=edition)
2017-07-27 19:13:04 +00:00
return edition
2017-07-25 11:29:23 +00:00
@login_required
def new_edition(request, by=None):
2017-07-25 12:14:05 +00:00
'''
view for creating editions
2017-07-25 12:14:05 +00:00
'''
alert = ''
if request.method == 'POST':
form = IdentifierForm(data=request.POST)
2017-07-27 19:13:04 +00:00
if form.is_valid():
if form.cleaned_data.get('make_new', False):
edition = get_edition_for_id('glue', 'new')
2017-07-27 19:13:04 +00:00
else:
id_type = form.cleaned_data['id_type']
id_value = form.cleaned_data['id_value']
identifiers = models.Identifier.objects.filter(type=id_type, value=id_value)
if identifiers:
# pre-existing identifier
ident = identifiers[0]
work = ident.work
edition = ident.edition if ident.edition else work.preferred_edition
else:
edition = get_edition_for_id(id_type, id_value)
2017-07-27 19:13:04 +00:00
return HttpResponseRedirect(
2017-07-27 19:13:04 +00:00
reverse('new_edition', kwargs={
'work_id': edition.work.id,
'edition_id': edition.id
})
)
else:
form = IdentifierForm()
return render(request, 'new_edition.html', {'form': form, 'alert':alert})
@login_required
def edit_edition(request, work_id, edition_id, by=None):
'''
view for editing editions
'''
if not work_id and not edition_id:
return new_edition(request, by=by)
2017-07-25 11:29:23 +00:00
# if the work and edition are set, we save the edition and set the work
language = 'en'
age_level = ''
description = ''
title = ''
if work_id:
work = safe_get_work(work_id)
language = work.language
age_level = work.age_level
description = work.description
title = work.title
else:
work = None
alert = ''
admin = user_can_edit_work(request.user, work)
if edition_id:
2017-07-25 12:21:26 +00:00
edition = get_edition(edition_id)
2017-07-25 11:29:23 +00:00
if work:
edition.work = work
language = edition.work.language
age_level = edition.work.age_level
description = edition.work.description
else:
edition = models.Edition()
if work:
edition.work = work
edition.publication_date = work.earliest_publication_date
edition.new_authors = []
for relator in work.relators():
edition.new_authors.append((relator.author.name, relator.relation.code))
initial = {
'language': language,
'age_level': age_level,
'publisher_name': edition.publisher_name,
'description': description,
'title': title,
}
2017-07-25 11:29:23 +00:00
if request.method == 'POST':
form = None
2017-07-25 12:14:05 +00:00
edition.new_authors = zip(
request.POST.getlist('new_author'),
request.POST.getlist('new_author_relation')
)
2017-07-25 11:29:23 +00:00
edition.new_subjects = request.POST.getlist('new_subject')
if edition.id and admin:
for author in edition.authors.all():
if request.POST.has_key('delete_author_%s' % author.id):
edition.remove_author(author)
form = EditionForm(instance=edition, data=request.POST, files=request.FILES)
break
work_rels = models.WorkRelation.objects.filter(Q(to_work=work) | Q(from_work=work))
for work_rel in work_rels:
if request.POST.has_key('delete_work_rel_%s' % work_rel.id):
work_rel.delete()
form = EditionForm(instance=edition, data=request.POST, files=request.FILES)
break
2017-07-25 12:14:05 +00:00
2017-07-25 11:29:23 +00:00
if request.POST.has_key('add_author_submit') and admin:
new_author_name = request.POST['add_author'].strip()
new_author_relation = request.POST['add_author_relation']
try:
author = models.Author.objects.get(name=new_author_name)
except models.Author.DoesNotExist:
author = models.Author.objects.create(name=new_author_name)
edition.new_authors.append((new_author_name, new_author_relation))
form = EditionForm(instance=edition, data=request.POST, files=request.FILES)
elif not form and admin:
form = EditionForm(instance=edition, data=request.POST, files=request.FILES)
if form.is_valid():
form.save()
if not work:
work = models.Work(
title=form.cleaned_data['title'],
language=form.cleaned_data['language'],
age_level=form.cleaned_data['age_level'],
description=form.cleaned_data['description'],
)
work.save()
edition.work = work
edition.save()
else:
work.description = form.cleaned_data['description']
work.title = form.cleaned_data['title']
work.publication_range = None # will reset on next access
work.language = form.cleaned_data['language']
work.age_level = form.cleaned_data['age_level']
work.save()
id_type = form.cleaned_data['id_type']
id_val = form.cleaned_data['id_value']
if id_val == 'delete':
if edition.identifiers.exclude(type=id_type):
2017-07-25 11:29:23 +00:00
edition.identifiers.filter(type=id_type).delete()
else:
alert = ('Can\'t delete identifier - must have at least one left.')
elif id_val:
models.Identifier.set(
type=id_type,
value=id_val,
edition=edition,
work=work
)
2017-07-25 11:29:23 +00:00
for relator in edition.relators.all():
if request.POST.has_key('change_relator_%s' % relator.id):
new_relation = request.POST['change_relator_%s' % relator.id]
relator.set(new_relation)
related_work = form.cleaned_data['add_related_work']
if related_work:
models.WorkRelation.objects.get_or_create(
to_work=work,
from_work=related_work,
relation=form.cleaned_data['add_work_relation'],
2017-07-25 12:14:05 +00:00
)
2017-07-25 11:29:23 +00:00
for (author_name, author_relation) in edition.new_authors:
edition.add_author(author_name, author_relation)
if form.cleaned_data.has_key('bisac'):
bisacsh = form.cleaned_data['bisac']
while bisacsh:
add_subject(bisacsh.full_label, work, authority="bisacsh")
bisacsh = bisacsh.parent
for subject_name in edition.new_subjects:
add_subject(subject_name, work)
work_url = reverse('work', kwargs={'work_id': edition.work.id})
cover_file = form.cleaned_data.get("coverfile", None)
if cover_file:
# save it
2017-07-25 12:14:05 +00:00
cover_file_name = '/Users/%s/covers/%s/%s' % (
request.user.username,
edition.pk,
cover_file.name
)
new_file = default_storage.open(cover_file_name, 'w')
new_file.write(cover_file.read())
new_file.close()
2017-07-25 11:29:23 +00:00
#and put its url into cover_image
edition.cover_image = default_storage.url(cover_file_name)
edition.save()
if not alert:
return HttpResponseRedirect(work_url)
2017-07-25 11:29:23 +00:00
else:
form = EditionForm(instance=edition, initial=initial)
return render(request, 'edit_edition.html', {
'form': form,
'identform': IdentifierForm(),
'edition': edition,
'admin': admin,
'alert': alert,
2017-07-25 11:29:23 +00:00
})