redo marc file upload

pull/1/head
eric 2014-10-27 16:57:35 -04:00
parent 3b4b836e6c
commit e1409ceac1
16 changed files with 295 additions and 118 deletions

View File

@ -35,6 +35,7 @@ regluit imports
""" """
from regluit import payment from regluit import payment
from regluit.core import models from regluit.core import models
from regluit.marc.models import MARCRecord
from regluit.core.lookups import ( from regluit.core.lookups import (
PublisherNameLookup, PublisherNameLookup,
WorkLookup, WorkLookup,
@ -207,12 +208,17 @@ class MARCRecordAdminForm(forms.ModelForm):
widget=AutoCompleteSelectWidget(EditionLookup), widget=AutoCompleteSelectWidget(EditionLookup),
required=True, required=True,
) )
user = AutoCompleteSelectField(
OwnerLookup,
widget=AutoCompleteSelectWidget(OwnerLookup),
required=True,
)
class Meta(object): class Meta(object):
model = models.MARCRecord model = MARCRecord
class MARCRecordAdmin(ModelAdmin): class MARCRecordAdmin(ModelAdmin):
list_display = ('edition',) list_display = ('edition', 'user')
date_hierarchy = 'created'
form = MARCRecordAdminForm form = MARCRecordAdminForm
admin_site = RegluitAdmin("Admin") admin_site = RegluitAdmin("Admin")
@ -238,7 +244,7 @@ admin_site.register(models.Wishlist, WishlistAdmin)
admin_site.register(models.UserProfile, UserProfileAdmin) admin_site.register(models.UserProfile, UserProfileAdmin)
admin_site.register(models.CeleryTask, CeleryTaskAdmin) admin_site.register(models.CeleryTask, CeleryTaskAdmin)
admin_site.register(models.Press, PressAdmin) admin_site.register(models.Press, PressAdmin)
admin_site.register(models.MARCRecord, MARCRecordAdmin) admin_site.register(MARCRecord, MARCRecordAdmin)
# payments # payments

View File

@ -770,15 +770,6 @@ class PressForm(forms.ModelForm):
class KindleEmailForm(forms.Form): class KindleEmailForm(forms.Form):
kindle_email = forms.EmailField() kindle_email = forms.EmailField()
class MARCUngluifyForm(forms.Form):
edition = AutoCompleteSelectField(
EditionLookup,
label='Edition',
widget=AutoCompleteSelectWidget(EditionLookup),
required=True,
error_messages={'required': 'Please specify an edition.'},
)
file = forms.FileField(label='Download a MARCXML file from Library of Congress; then upload it here.')
class MARCFormatForm(forms.ModelForm): class MARCFormatForm(forms.ModelForm):
class Meta: class Meta:

View File

@ -43,17 +43,8 @@
See <a href="https://encrypted.google.com/books?id={{ edition.googlebooks_id }}">this edition on Google Books</a><br /> See <a href="https://encrypted.google.com/books?id={{ edition.googlebooks_id }}">this edition on Google Books</a><br />
{% endif %} {% endif %}
{% endif %} {% endif %}
{% if edition.MARCrecords.all %} {% if user.libpref %}{% if edition.ebooks.all or edition.ebook_files.all %}
{% for record in edition.MARCrecords.all %} <a href="{% url upload_marc %}?edition={{ edition.id }}">Upload</a> a MARC record for this edition. <br />
Download {{record.link_target}} MARC record for this edition: (<a href="{% url marc_concatenate %}?record_{{ record.id }}=on&amp;format=xml">XML</a>) (<a href="{% url marc_concatenate %}?record_{{ record.id }}=on&amp;format=mrc">mrc</a>)<br />
{% endfor %}
{% else %}
{% if edition.ebooks.all %}
Download {{record.link_target}} MARC record for this edition: (<a href="{% url marc_concatenate %}?edition_{{ edition.id }}=on&amp;format=xml">XML</a>) (<a href="{% url marc_concatenate %}?edition_{{ edition.id }}=on&amp;format=mrc">mrc</a>)<br />
{% endif %}
{% endif %}
{% if user.is_staff %}{% if edition.ebooks.0 or edition.ebook_files.0 %}
<a href="{% url MARCUngluify %}?edition={{ edition.id }}">Upload</a> a MARC record for this edition. <br />
{% endif %} {% endif %} {% endif %} {% endif %}
</div> </div>

View File

@ -31,6 +31,8 @@ Weve added "Buy-to-Unglue" campaigns to so that libraries can lend ebooks on
<dl> <dl>
<dt><a href="{% url registration_register %}?next={{ request.get_full_path|urlencode }}">Sign up.</a> It's Free!</dt> <dt><a href="{% url registration_register %}?next={{ request.get_full_path|urlencode }}">Sign up.</a> It's Free!</dt>
<dd>Starting an account, for yourself or your library, is free. Use it to help us distribute unglued and ungluing ebooks. </dd> <dd>Starting an account, for yourself or your library, is free. Use it to help us distribute unglued and ungluing ebooks. </dd>
<dt>Add free ebooks to your collection with our <a href="{% url marc %}">MARC records</a>!</dt>
<dd>We're building a comprehensive database of freely licensed ebooks. We provide <a href="{% url marc %}">MARC records for these ebooks</a> wherever we can. They can live in the catalog in your ILS; they link to an epub file in the Internet Archive. Of course, because of unglued ebooks' Creative Commons licenses, you're free to shift that epub to other formats, host the file on your own servers, and edit the MARC record accordingly. And if you want, help us <a href="{% url marc %}">improve</a> our records.</dd>
<dt>Become an Unglue.it participating library</dt> <dt>Become an Unglue.it participating library</dt>
<dd><ol><li><a href="{% url library_create %}">Make your library page</a> on Unglue.it. It takes just a few minutes. It's the first step towards becoming an Unglue.it participating library.</li> <dd><ol><li><a href="{% url library_create %}">Make your library page</a> on Unglue.it. It takes just a few minutes. It's the first step towards becoming an Unglue.it participating library.</li>
<li>Review our <a href="https://www.docracy.com/0_uyw26qv9c/unglue-it-library-license-agreement">LIBRARY LICENSE AGREEMENT</a>. </li> <li>Review our <a href="https://www.docracy.com/0_uyw26qv9c/unglue-it-library-license-agreement">LIBRARY LICENSE AGREEMENT</a>. </li>
@ -42,10 +44,6 @@ The library license gives download access to one library member at a time for 14
</dd> </dd>
<dt>Stay in touch.</dt> <dt>Stay in touch.</dt>
<dd>You can follow us on Twitter (<a href="http://twitter.com/unglueit">@unglueit</a>), <a href="http://facebook/com/unglueit">Facebook</a>, and our <a href="http://blog.unglue.it">blog</a>, and <a href="http://eepurl.com/fKLfI">subscribe to our newsletter</a> (1-2 emails per month).</dd> <dd>You can follow us on Twitter (<a href="http://twitter.com/unglueit">@unglueit</a>), <a href="http://facebook/com/unglueit">Facebook</a>, and our <a href="http://blog.unglue.it">blog</a>, and <a href="http://eepurl.com/fKLfI">subscribe to our newsletter</a> (1-2 emails per month).</dd>
<dt>Add unglued ebooks to your collection.</dt>
<dd>We provide <a href="{% url marc %}">MARC records for unglued ebooks</a> wherever we can. We also strive to have MARC records available for all unglued ebooks. They can live in the catalog in your ILS; they link to an epub file in the Internet Archive. Of course, because of unglued ebooks' Creative Commons licenses, you're free to shift that epub to other formats, host the file on your own servers, and edit the MARC record accordingly.</dd>
<dt>Join our <a href="http://goo.gl/lCTLI">catalogers list</a>.</dt>
<dd>We're able to get MARC records into OCLC and SkyRiver because of the support of catalogers like you. Want to help? <a href="http://goo.gl/lCTLI">Add yourself to the list.</a> Usually all you'll need to do is modify an existing record for an earlier edition and upload the record. We'll supply you with the link and the unglued edition. We'll only contact you when there's an unglued book to be cataloged.</dd>
<dt>Spread the word.</dt> <dt>Spread the word.</dt>
<dd>There are social media sharing links on most pages on the site. There are some right here! <dd>There are social media sharing links on most pages on the site. There are some right here!
<div id="widgetcode">Copy/paste this into your site:<br /><textarea rows="7" cols="22">&lt;iframe src="https://{{request.META.HTTP_HOST}}/api/widget/{{work.first_isbn_13}}/" width="152" height="325" frameborder="0"&gt;&lt;/iframe&gt;</textarea></div> <div id="widgetcode">Copy/paste this into your site:<br /><textarea rows="7" cols="22">&lt;iframe src="https://{{request.META.HTTP_HOST}}/api/widget/{{work.first_isbn_13}}/" width="152" height="325" frameborder="0"&gt;&lt;/iframe&gt;</textarea></div>
@ -59,7 +57,7 @@ The library license gives download access to one library member at a time for 14
<dt>Educate yourself and your patrons about ebook issues and Creative Commons licenses.</dt> <dt>Educate yourself and your patrons about ebook issues and Creative Commons licenses.</dt>
<dd>Checkout limits, publishers who won't sell ebooks to libraries, DRM, companies tracking readers' behavior, library prices far in excess of consumer costs, incompatible technologies and formats, cataloging silos...you know why it's hard for you to deliver a seamless ereading experience to your patrons. Make sure they know, too. And make sure everyone knows how solutions, like <a href="http://creativecommons.org">Creative Commons</a> licenses, can help libraries and readers while respecting copyright and protecting creators' rights.</dd> <dd>Checkout limits, publishers who won't sell ebooks to libraries, DRM, companies tracking readers' behavior, library prices far in excess of consumer costs, incompatible technologies and formats, cataloging silos...you know why it's hard for you to deliver a seamless ereading experience to your patrons. Make sure they know, too. And make sure everyone knows how solutions, like <a href="http://creativecommons.org">Creative Commons</a> licenses, can help libraries and readers while respecting copyright and protecting creators' rights.</dd>
<dt>Support <a href="{% url campaign_list 'ending' %}">our active campaigns</a>.</dt> <dt>Support <a href="{% url campaign_list 'ending' %}">our active campaigns</a>.</dt>
<dd>Ultimately ebooks can't be unglued unless authors and publishers are paid for their work. Many of our staunchest supporters are librarians. There are also several libraries which have supported campaigns, including Leddy Library (University of Windsor, Ontario); the University of Alberta library ; and the Z. Smith Reynolds library (Wake Forest University.</dd> <dd>Ultimately ebooks can't be unglued unless authors and publishers are paid for their work. Many of our staunchest supporters are librarians. There are also several libraries which have supported campaigns, including Leddy Library (University of Windsor, Ontario); the University of Alberta library ; and the Z. Smith Reynolds library (Wake Forest University).</dd>
<dt>Give feedback and ask questions.</dt> <dt>Give feedback and ask questions.</dt>
<dd>Want to know more? Need help? Have ideas for how we could improve the site or make it more library-friendly? Contact us at: <a href="mailto:libraries@gluejar.com">libraries@gluejar.com</a>.</dd> <dd>Want to know more? Need help? Have ideas for how we could improve the site or make it more library-friendly? Contact us at: <a href="mailto:libraries@gluejar.com">libraries@gluejar.com</a>.</dd>
</dl> </dl>

View File

@ -44,8 +44,8 @@ ul.local li {
<p>Go ahead: add unglued ebooks to your library catalog!</p> <p>Go ahead: add unglued ebooks to your library catalog!</p>
{% if request.user.is_staff %} {% if request.user.libpref %}
<p>Hi, {{ request.user.username }}. Unglue.it staffers can also <a href="{% url MARCUngluify %}">add new records</a>.</p> <p>Hi, {{ request.user.username }}. Librarians can also <a href="{% url upload_marc %}">add new records</a>.</p>
{% endif %} {% endif %}
{% if messages %} {% if messages %}

View File

@ -0,0 +1,62 @@
{% extends "basedocumentation.html" %}
{% block title %}Add new MARC records{% endblock %}
{% block extra_extra_head %}
{{ block.super }}
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.13/themes/ui-lightness/jquery-ui.css" type="text/css" media="screen">
<link href="/static/selectable/css/dj.selectable.css" type="text/css" media="all" rel="stylesheet" />
<script type="text/javascript" src="{{ jquery_ui_home }}"></script>
<script type="text/javascript" src="/static/selectable/js/jquery.dj.selectable.js"></script>
{% endblock %}
{% block doccontent %}
{% if not request.user.libpref %}
<p><i>If you want to load MARC records, you probably want to <a href="{% url marc_config %}">enable Unglue.it's librarian tools</a> first!</i></p>
{% endif %}
<h2>Adding MARC records to Unglue.it</h2>
{% if messages %}
<ul class="messages">
{% for message in messages %}
<li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
{% if not form.initial.edition %}
<h3>Selecting an edition</h3>
<p>
MARC records are associated with unglue.it edition records. Look for links in the "more" tab of any unglue.it work page that has a "Download" button on it.
{% endif %}
<h3>Adapting records from LoC</h3>
<p>
For ebooks which have existing print editions cataloged in the Library of Congress, we can automatically convert those to Unglue.it ebook MARC records, which will then be automatically affixed to the ebook edition in our database and <a href="{% url marc %}">provided to ungluers</a>.
</p>
<p>
To get the XML record, search <a href="http://catalog.loc.gov/">http://catalog.loc.gov/</a>, select the print edition, and click on the permalink (will look something like <a href="http://lccn.loc.gov/63008219">http://lccn.loc.gov/63008219</a>). This page has a MARCXML link.
</p>
<p>
The record loader will automatically add links to all the unglued ebook files known to the Unglue.it database. <I>Make sure those links are in the database before adding the record.</i> </p>
<h3>Editing stub records from LoC</h3>
{% if form.initial.edition %}
The current records for this edition are here. They may be auto-generated stubs:
<div id="libtools">
<form method="POST" id="record_form" action="{% url marc_concatenate %}">
{% include 'marc_form.html' %}
<input type="hidden" name="edition_{{form.initial.edition}}" value="on">
<input type="submit" name="submit" value="Download MARC" id="submit">
</form>
</div>
{% endif %}
<p>
Edit the record, then upload it as a "record prepared for Unglue.it". The record loader strips 001, 003, 005, 006, 007, 856 and >900 fields, and adds them back in on download.
</p>
<h3>Load a record</h3>
<form action="" enctype="multipart/form-data" method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Add record" />
</form>
{% endblock %}

View File

@ -1,42 +0,0 @@
{% extends "basedocumentation.html" %}
{% block title %}Add new MARC records{% endblock %}
{% block extra_extra_head %}
{{ block.super }}
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.13/themes/ui-lightness/jquery-ui.css" type="text/css" media="screen">
<link href="/static/selectable/css/dj.selectable.css" type="text/css" media="all" rel="stylesheet" />
<script type="text/javascript" src="{{ jquery_ui_home }}"></script>
<script type="text/javascript" src="/static/selectable/js/jquery.dj.selectable.js"></script>
{% endblock %}
{% block doccontent %}
<h2>Make your unglued MARC records here</h2>
{% if messages %}
<ul class="messages">
{% for message in messages %}
<li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
<p>
For unglued ebooks which have existing print editions cataloged in the Library of Congress, we can automatically convert those to unglued ebook MARC records, which will then be automatically affixed to the ebook edition in our database and <a href="{% url marc %}">provided to ungluers</a>.
</p>
<p>
To get the XML record, search <a href="http://catalog.loc.gov/">http://catalog.loc.gov/</a>, select the print edition, and click on the permalink (will look something like <a href="http://lccn.loc.gov/63008219">http://lccn.loc.gov/63008219</a>). This page has a MARCXML link.
</p>
<p>
The robot cataloger will automatically add links to all the unglued ebook files known to the Unglue.it database. <I>Make sure you have added those links to the database before creating the record.</i> Likewise, it will autofill the ISBN, and you should have already provided that.
</p>
<p>
If you want to add a MARC record for a non-unglued but publicly available book, create a MARCRecord instance in the admin interface and populate its fields there. (This assumes that the MARC record is for the freely available ebook version and exists in a linkable form. If it does not, upload it to S3 first, by analogy with the <a href="http://django-storages.readthedocs.org/en/latest/backends/amazon-S3.html#tests">django-storages documentation</a>, and use that link.)
</p>
<form action="" enctype="multipart/form-data" method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Add record" />
</form>
{% endblock %}

View File

@ -36,7 +36,6 @@ from regluit.frontend.views import (
ByPubView, ByPubView,
kindle_config, kindle_config,
send_to_kindle, send_to_kindle,
MARCUngluifyView,
MARCConfigView, MARCConfigView,
DownloadView, DownloadView,
) )
@ -157,7 +156,6 @@ urlpatterns = patterns(
url(r"^accounts/edit/kindle_config/(?P<work_id>\d+)/$", "kindle_config", name="kindle_config_download"), url(r"^accounts/edit/kindle_config/(?P<work_id>\d+)/$", "kindle_config", name="kindle_config_download"),
url(r"^send_to_kindle/(?P<work_id>\d+)/(?P<javascript>\d)/$", "send_to_kindle", name="send_to_kindle"), url(r"^send_to_kindle/(?P<work_id>\d+)/(?P<javascript>\d)/$", "send_to_kindle", name="send_to_kindle"),
url(r"^marc/$", direct_to_template, {'template': 'marc.html'}, name="marc"), url(r"^marc/$", direct_to_template, {'template': 'marc.html'}, name="marc"),
url(r"^marc/ungluify/$", staff_member_required(MARCUngluifyView.as_view()), name="MARCUngluify"),
url(r"^accounts/edit/marc_config/$", login_required(MARCConfigView.as_view()), name="marc_config"), url(r"^accounts/edit/marc_config/$", login_required(MARCConfigView.as_view()), name="marc_config"),
) )

View File

@ -17,7 +17,6 @@ from notification import models as notification
from random import randint from random import randint
from re import sub from re import sub
from xml.etree import ElementTree as ET from xml.etree import ElementTree as ET
from xml.sax import SAXParseException
from tastypie.models import ApiKey from tastypie.models import ApiKey
''' '''
@ -116,7 +115,6 @@ from regluit.frontend.forms import (
MsgForm, MsgForm,
PressForm, PressForm,
KindleEmailForm, KindleEmailForm,
MARCUngluifyForm,
MARCFormatForm, MARCFormatForm,
DateCalculatorForm DateCalculatorForm
) )
@ -3110,39 +3108,6 @@ def work_marc(request, work_id):
work = safe_get_work(work_id) work = safe_get_work(work_id)
return qs_marc_records(request, qs=[ work ]) return qs_marc_records(request, qs=[ work ])
class MARCUngluifyView(FormView):
template_name = 'marcungluify.html'
form_class = MARCUngluifyForm
success_url = reverse_lazy('MARCUngluify')
# allow a get param to specify the edition
def get_initial(self):
if self.request.method == 'GET':
edition = self.request.GET.get('edition',None)
if models.Edition.objects.filter(id=edition).count():
edition = models.Edition.objects.filter(id=edition)[0]
if edition.ebooks.count() or edition.ebook_files.count():
return {'edition':edition.id}
return {}
def form_valid(self, form):
edition = form.cleaned_data['edition']
try:
marc.makemarc(
marcfile=self.request.FILES['file'],
edition=edition
)
messages.success(
self.request,
"You have successfully added a MARC record. Hooray! Add another?"
)
except SAXParseException:
messages.error(
self.request,
"Sorry, couldn't parse that file."
)
return super(MARCUngluifyView,self).form_valid(form)
class MARCConfigView(FormView): class MARCConfigView(FormView):
template_name = 'marc_config.html' template_name = 'marc_config.html'

22
marc/forms.py Normal file
View File

@ -0,0 +1,22 @@
from django import forms
from selectable.forms import (
AutoCompleteSelectWidget,
AutoCompleteSelectField
)
from regluit.core.lookups import EditionLookup
class MARCUploadForm(forms.Form):
edition = AutoCompleteSelectField(
EditionLookup,
label='Edition',
widget=AutoCompleteSelectWidget(EditionLookup),
required=True,
error_messages={'required': 'Please specify an edition.'},
)
file = forms.FileField(label='Select a MARCXML file.')
source = forms.ChoiceField(label='This file is ...', choices=[
( 'loc' , 'from Library of Congress (print)'),
( 'raw' , 'prepared for Unglue.it'),
])

View File

@ -117,6 +117,15 @@ def stub(edition):
return record return record
#load a with minimal change
def raw(marcfile, edition):
record = pymarc.parse_xml_to_array(marcfile)[0]
for field in record:
if field.tag in ('001', '003', '005', '006', '007', '856') or int( field.tag ) > 900:
record.remove_field(field)
add_stuff(record)
return record
#load a record from library of Congress #load a record from library of Congress
def from_lc(marcfile, edition): def from_lc(marcfile, edition):

View File

@ -5,12 +5,15 @@ from regluit.marc.models import MARCRecord
from regluit.core.models import MARCRecord as OldRecord from regluit.core.models import MARCRecord as OldRecord
class Command(BaseCommand): class Command(BaseCommand):
help = "migrate records from files" help = "migrate records (id<stoprecord) from files"
args = "" args = "<stoprecord>"
def handle(self, **options): def handle(self, stoprecord=None, **options):
editions=[] editions=[]
for old_record in OldRecord.objects.all().order_by('-id'): old_records=OldRecord.objects.all().order_by('-id')
if stoprecord:
old_records = old_records.filter(id__lt=int(stoprecord))
for old_record in old_records:
if old_record.edition.pk not in editions: if old_record.edition.pk not in editions:
new_record, created = MARCRecord.objects.get_or_create(id=old_record.pk) new_record, created = MARCRecord.objects.get_or_create(id=old_record.pk)
try: try:

View File

@ -0,0 +1,116 @@
# -*- coding: utf-8 -*-
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Adding field 'MARCRecord.user'
db.add_column('marc_marcrecord', 'user',
self.gf('django.db.models.fields.related.ForeignKey')(related_name='MARCRecords', null=True, to=orm['auth.User']),
keep_default=False)
# Adding field 'MARCRecord.created'
db.add_column('marc_marcrecord', 'created',
self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, default=datetime.datetime(2014, 10, 27, 0, 0), blank=True),
keep_default=False)
def backwards(self, orm):
# Deleting field 'MARCRecord.user'
db.delete_column('marc_marcrecord', 'user_id')
# Deleting field 'MARCRecord.created'
db.delete_column('marc_marcrecord', 'created')
models = {
'auth.group': {
'Meta': {'object_name': 'Group'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
'auth.permission': {
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
'core.edition': {
'Meta': {'object_name': 'Edition'},
'cover_image': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'publication_date': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '50', 'null': 'True', 'blank': 'True'}),
'publisher_name': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'editions'", 'null': 'True', 'to': "orm['core.PublisherName']"}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '1000'}),
'unglued': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'work': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'editions'", 'null': 'True', 'to': "orm['core.Work']"})
},
'core.publisher': {
'Meta': {'object_name': 'Publisher'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'description': ('django.db.models.fields.TextField', [], {'default': "''", 'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'logo_url': ('django.db.models.fields.URLField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'}),
'name': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'key_publisher'", 'to': "orm['core.PublisherName']"}),
'url': ('django.db.models.fields.URLField', [], {'max_length': '1024', 'null': 'True', 'blank': 'True'})
},
'core.publishername': {
'Meta': {'object_name': 'PublisherName'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'publisher': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'alternate_names'", 'null': 'True', 'to': "orm['core.Publisher']"})
},
'core.work': {
'Meta': {'ordering': "['title']", 'object_name': 'Work'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'db_index': 'True', 'blank': 'True'}),
'description': ('django.db.models.fields.TextField', [], {'default': "''", 'null': 'True', 'blank': 'True'}),
'earliest_publication': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True'}),
'featured': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'db_index': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'language': ('django.db.models.fields.CharField', [], {'default': "'en'", 'max_length': '5', 'db_index': 'True'}),
'num_wishes': ('django.db.models.fields.IntegerField', [], {'default': '0', 'db_index': 'True'}),
'openlibrary_lookup': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
'selected_edition': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'selected_works'", 'null': 'True', 'to': "orm['core.Edition']"}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '1000'})
},
'marc.marcrecord': {
'Meta': {'object_name': 'MARCRecord'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'edition': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'MARCRecords'", 'null': 'True', 'to': "orm['core.Edition']"}),
'guts': ('django.db.models.fields.TextField', [], {}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'MARCRecords'", 'null': 'True', 'to': "orm['auth.User']"})
}
}
complete_apps = ['marc']

View File

@ -4,6 +4,7 @@ from datetime import datetime
from StringIO import StringIO from StringIO import StringIO
from django.conf import settings from django.conf import settings
from django.contrib.auth.models import User
from django.db import models from django.db import models
from . import load from . import load
@ -54,6 +55,10 @@ class MARCRecord(models.Model):
# note capitalization of related_name # note capitalization of related_name
edition = models.ForeignKey(EDITION_MODEL, related_name="MARCRecords", null=True) edition = models.ForeignKey(EDITION_MODEL, related_name="MARCRecords", null=True)
user = models.ForeignKey(User, related_name="MARCRecords", null=True )
created = models.DateTimeField(auto_now_add=True)
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(MARCRecord, self).__init__( *args, **kwargs) super(MARCRecord, self).__init__( *args, **kwargs)
edition = kwargs.pop('edition', None) edition = kwargs.pop('edition', None)
@ -81,13 +86,20 @@ class MARCRecord(models.Model):
self._the_record.add_ordered_field(field001) self._the_record.add_ordered_field(field001)
super(MARCRecord, self).save(*args, **kwargs) super(MARCRecord, self).save(*args, **kwargs)
def load_from_lc(self): def load_from_file(self, source='raw'):
#parse guts #parse guts
if isinstance(self.guts, str) or isinstance(self.guts, unicode):
marcfile = StringIO(self.guts) marcfile = StringIO(self.guts)
else:
marcfile = self.guts
if source == 'loc':
self._the_record = load.from_lc(marcfile, self.edition) self._the_record = load.from_lc(marcfile, self.edition)
else:
self._the_record = load.raw(marcfile, self.edition)
self.guts = pymarc.record_to_xml(self._the_record) self.guts = pymarc.record_to_xml(self._the_record)
self.save() self.save()
# the record without 856 # the record without 856
def _record(self): def _record(self):
if self._the_record: if self._the_record:

View File

@ -1,7 +1,11 @@
from django.conf.urls.defaults import * from django.conf.urls.defaults import *
from django.contrib.auth.decorators import login_required
from . import views
urlpatterns = patterns( urlpatterns = patterns(
"regluit.marc.views", "regluit.marc.views",
url(r"^marc/concatenate/$", "marc_records", name="marc_concatenate"), url(r"^marc/concatenate/$", "marc_records", name="marc_concatenate"),
url(r"^marc/all/$", "all_marc_records", name="marc_all"), url(r"^marc/all/$", "all_marc_records", name="marc_all"),
url(r"^marc/upload/$", login_required(views.MARCUpload.as_view()), name="upload_marc"),
) )

View File

@ -1,9 +1,14 @@
from datetime import datetime from datetime import datetime
from django.core.urlresolvers import reverse from xml.sax import SAXParseException
from django.contrib import messages
from django.core.urlresolvers import reverse, reverse_lazy
from django.db.models import get_model from django.db.models import get_model
from django.http import HttpResponseRedirect, HttpResponse, HttpResponseNotFound from django.http import HttpResponseRedirect, HttpResponse, HttpResponseNotFound
from django.views.generic.edit import FormView
from . import models from . import models
from . import forms
PREAMBLE = ('<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' PREAMBLE = ('<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'
'<collection ' '<collection '
@ -88,3 +93,40 @@ def qs_marc_records(request, qs):
selected_records.extend(obj.marc_records()) selected_records.extend(obj.marc_records())
return marc_records(request, selected_records=selected_records) return marc_records(request, selected_records=selected_records)
class MARCUpload(FormView):
template_name = 'marc/upload.html'
form_class = forms.MARCUploadForm
success_url = reverse_lazy('upload_marc')
# allow a get param to specify the edition
def get_initial(self):
if self.request.method == 'GET':
edition = self.request.GET.get('edition',None)
if Edition.objects.filter(id=edition).count():
edition = Edition.objects.filter(id=edition)[0]
if edition.ebooks.count() or edition.ebook_files.count():
return {'edition':edition.id}
return {}
def form_valid(self, form):
edition = form.cleaned_data['edition']
source = form.cleaned_data['source']
try:
marcfile=self.request.FILES['file']
new_record = models.MARCRecord(
guts=marcfile,
edition=edition,
user= self.request.user
)
new_record.load_from_file(source)
messages.success(
self.request,
"You have successfully added a MARC record. Hooray! Add another?"
)
except SAXParseException:
messages.error(
self.request,
"Sorry, couldn't parse that file."
)
return super(MARCUpload,self).form_valid(form)