Dependencies
============
+ * Python 2.7
* All packages listed in requirements.txt
* Sass>=3.2
3. Setup your local configuration based on settings.py. You need to generate a new SECRET_KEY, database stuff and domain related stuff.
4. Populate database:
- ./manage.py syncdb
./manage.py migrate
5. Run the server
return force_unicode(obj)
return obj
-# shortcut for JSON reponses
-class JSONResponse(HttpResponse):
- def __init__(self, data={}, callback=None, **kwargs):
- # get rid of mimetype
- kwargs.pop('mimetype', None)
- data = json.dumps(data)
- if callback:
- data = callback + "(" + data + ");"
- super(JSONResponse, self).__init__(data, content_type="application/json", **kwargs)
-
def method_decorator(function_decorator):
"""Converts a function decorator to a method decorator.
from catalogue.models import Book
from picture.models import Picture
-from search import Index
+from search.index import Index
class Command(BaseCommand):
('cover', catalogue.fields.EbookField(b'cover', upload_to=catalogue.models.book._cover_upload_to, storage=fnpdjango.storage.BofhFileSystemStorage(), max_length=255, blank=True, null=True, verbose_name='cover')),
('cover_thumb', catalogue.fields.EbookField(b'cover_thumb', max_length=255, upload_to=catalogue.models.book._cover_thumb_upload_to, null=True, verbose_name='cover thumbnail', blank=True)),
('_related_info', jsonfield.fields.JSONField(null=True, editable=False, blank=True)),
- ('txt_file', catalogue.fields.EbookField(b'txt', default=b'', storage=fnpdjango.storage.BofhFileSystemStorage(), upload_to=None, max_length=255, blank=True, verbose_name='TXT file')),
- ('fb2_file', catalogue.fields.EbookField(b'fb2', default=b'', storage=fnpdjango.storage.BofhFileSystemStorage(), upload_to=None, max_length=255, blank=True, verbose_name='FB2 file')),
- ('pdf_file', catalogue.fields.EbookField(b'pdf', default=b'', storage=fnpdjango.storage.BofhFileSystemStorage(), upload_to=None, max_length=255, blank=True, verbose_name='PDF file')),
- ('epub_file', catalogue.fields.EbookField(b'epub', default=b'', storage=fnpdjango.storage.BofhFileSystemStorage(), upload_to=None, max_length=255, blank=True, verbose_name='EPUB file')),
- ('mobi_file', catalogue.fields.EbookField(b'mobi', default=b'', storage=fnpdjango.storage.BofhFileSystemStorage(), upload_to=None, max_length=255, blank=True, verbose_name='MOBI file')),
- ('html_file', catalogue.fields.EbookField(b'html', default=b'', storage=fnpdjango.storage.BofhFileSystemStorage(), upload_to=None, max_length=255, blank=True, verbose_name='HTML file')),
- ('xml_file', catalogue.fields.EbookField(b'xml', default=b'', storage=fnpdjango.storage.BofhFileSystemStorage(), upload_to=None, max_length=255, blank=True, verbose_name='XML file')),
+ ('txt_file', catalogue.fields.EbookField(b'txt', default=b'', storage=fnpdjango.storage.BofhFileSystemStorage(), upload_to=catalogue.models.book._txt_upload_to, max_length=255, blank=True, verbose_name='TXT file')),
+ ('fb2_file', catalogue.fields.EbookField(b'fb2', default=b'', storage=fnpdjango.storage.BofhFileSystemStorage(), upload_to=catalogue.models.book._fb2_upload_to, max_length=255, blank=True, verbose_name='FB2 file')),
+ ('pdf_file', catalogue.fields.EbookField(b'pdf', default=b'', storage=fnpdjango.storage.BofhFileSystemStorage(), upload_to=catalogue.models.book._pdf_upload_to, max_length=255, blank=True, verbose_name='PDF file')),
+ ('epub_file', catalogue.fields.EbookField(b'epub', default=b'', storage=fnpdjango.storage.BofhFileSystemStorage(), upload_to=catalogue.models.book._epub_upload_to, max_length=255, blank=True, verbose_name='EPUB file')),
+ ('mobi_file', catalogue.fields.EbookField(b'mobi', default=b'', storage=fnpdjango.storage.BofhFileSystemStorage(), upload_to=catalogue.models.book._mobi_upload_to, max_length=255, blank=True, verbose_name='MOBI file')),
+ ('html_file', catalogue.fields.EbookField(b'html', default=b'', storage=fnpdjango.storage.BofhFileSystemStorage(), upload_to=catalogue.models.book._html_upload_to, max_length=255, blank=True, verbose_name='HTML file')),
+ ('xml_file', catalogue.fields.EbookField(b'xml', default=b'', storage=fnpdjango.storage.BofhFileSystemStorage(), upload_to=catalogue.models.book._xml_upload_to, max_length=255, blank=True, verbose_name='XML file')),
('parent', models.ForeignKey(related_name=b'children', blank=True, to='catalogue.Book', null=True)),
],
options={
# This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later.
# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
#
+from collections import OrderedDict
import re
from django.conf import settings
-from django.core.cache import get_cache
+from django.core.cache import caches
from django.db import models
from django.db.models import permalink
import django.dispatch
+from django.contrib.contenttypes.fields import GenericRelation
from django.core.urlresolvers import reverse
-from django.utils.datastructures import SortedDict
from django.utils.translation import ugettext_lazy as _
import jsonfield
from fnpdjango.storage import BofhFileSystemStorage
bofh_storage = BofhFileSystemStorage()
-permanent_cache = get_cache('permanent')
+permanent_cache = caches['permanent']
def _cover_upload_to(i, n):
return 'book/cover/%s.jpg' % i.slug
+
def _cover_thumb_upload_to(i, n):
return 'book/cover_thumb/%s.jpg' % i.slug,
+
def _ebook_upload_to(upload_path):
def _upload_to(i, n):
return upload_path % i.slug
objects = models.Manager()
tagged = managers.ModelTaggedItemManager(Tag)
tags = managers.TagDescriptor(Tag)
+ tag_relations = GenericRelation(Tag.intermediary_table_model)
html_built = django.dispatch.Signal()
published = django.dispatch.Signal()
return create_zip(paths, "%s_%s" % (self.slug, format_))
def search_index(self, book_info=None, index=None, index_tags=True, commit=True):
- import search
if index is None:
- index = search.Index()
+ from search.index import Index
+ index = Index()
try:
index.index_book(self, book_info)
if index_tags:
books_by_parent.setdefault(book.parent_id, []).append(book)
orphans = []
- books_by_author = SortedDict()
+ books_by_author = OrderedDict()
for tag in Tag.objects.filter(category='author').iterator():
books_by_author[tag] = []
else:
return None
-
# add the file fields
for format_ in Book.formats:
field_name = "%s_file" % format_
- upload_to = _ebook_upload_to('book/%s/%%s.%s' % (format_, format_))
+ # This weird globals() assignment makes Django migrations comfortable.
+ _upload_to = _ebook_upload_to('book/%s/%%s.%s' % (format_, format_))
+ _upload_to.__name__ = '_%s_upload_to' % format_
+ globals()[_upload_to.__name__] = _upload_to
+
EbookField(format_, _("%s file" % format_.upper()),
- upload_to=upload_to,
+ upload_to=_upload_to,
storage=bofh_storage,
max_length=255,
blank=True,
# This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later.
# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
#
+from collections import OrderedDict
import json
from collections import namedtuple
from django.db import models
from django.utils.translation import ugettext_lazy as _
-from django.utils.datastructures import SortedDict
import jsonfield
from fnpdjango.utils.text.slughifi import slughifi
from catalogue.fields import OverwritingFileField
class BookMedia(models.Model):
"""Represents media attached to a book."""
FileFormat = namedtuple("FileFormat", "name ext")
- formats = SortedDict([
+ formats = OrderedDict([
('mp3', FileFormat(name='MP3', ext='mp3')),
('ogg', FileFormat(name='Ogg Vorbis', ext='ogg')),
('daisy', FileFormat(name='DAISY', ext='daisy.zip')),
# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
#
from django.conf import settings
-from django.core.cache import get_cache
+from django.contrib.contenttypes.fields import GenericRelation
+from django.core.cache import caches
from django.core.urlresolvers import reverse
from django.db import models
from django.template.loader import render_to_string
from catalogue.models import Tag
-permanent_cache = get_cache('permanent')
+permanent_cache = caches['permanent']
class Fragment(models.Model):
objects = models.Manager()
tagged = managers.ModelTaggedItemManager(Tag)
tags = managers.TagDescriptor(Tag)
+ tag_relations = GenericRelation(Tag.intermediary_table_model)
class Meta:
ordering = ('book', 'anchor',)
# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
#
from django.conf import settings
-from django.core.cache import get_cache
+from django.core.cache import caches
from django.db.models.signals import post_save, pre_delete, post_delete
import django.dispatch
from catalogue.models import Tag, BookMedia, Book, Fragment, Collection
from newtagging.models import tags_updated
-permanent_cache = get_cache('permanent')
+permanent_cache = caches['permanent']
def _tags_updated_handler(sender, affected_tags, **kwargs):
@django.dispatch.receiver(post_delete, sender=Book)
def _remove_book_from_index_handler(sender, instance, **kwargs):
""" remove the book from search index, when it is deleted."""
- import search
- idx = search.Index()
+ from search.index import Index
+ idx = Index()
idx.remove_book(instance)
idx.index_tags()
else:
meta_tags.append(tag)
return meta_tags
+
+
+# Pickle complains about not having this.
+TagRelation = Tag.intermediary_table_model
\ No newline at end of file
{% for book in books %}
{% book_mini book %}
{% endfor %}
+{% for book in random_related %}
+ {% book_mini book %}
+{% endfor %}
{% endspaceless %}
\ No newline at end of file
related = cache.get(cache_key)
if related is None:
related = Book.tagged.related_to(book,
- Book.objects.exclude(common_slug=book.common_slug),
- ignore_by_tag=book.book_tag())[:limit-random]
+ Book.objects.exclude(common_slug=book.common_slug)
+ ).exclude(tag_relations__tag=book.book_tag())[:limit-random]
cache.set(cache_key, related, 1800)
if random:
random_books = Book.objects.exclude(
if random == 1:
count = random_books.count()
if count:
- related.append(random_books[randint(0, count - 1)])
+ random_related = [random_books[randint(0, count - 1)]]
else:
- related += list(random_books.order_by('?')[:random])
+ random_related = list(random_books.order_by('?')[:random])
+ else:
+ random_related = []
return {
'books': related,
+ 'random_related': random_related,
}
# This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later.
# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
#
+from collections import OrderedDict
import re
import itertools
from django.template import RequestContext
from django.template.loader import render_to_string
from django.shortcuts import render_to_response, get_object_or_404
-from django.http import HttpResponse, HttpResponseRedirect, Http404, HttpResponsePermanentRedirect
+from django.http import HttpResponse, HttpResponseRedirect, Http404, HttpResponsePermanentRedirect, JsonResponse
from django.core.urlresolvers import reverse
from django.db.models import Q
from django.contrib.auth.decorators import login_required, user_passes_test
-from django.utils.datastructures import SortedDict
from django.utils.http import urlquote_plus
from django.utils import translation
from django.utils.translation import get_language, ugettext as _, ugettext_lazy
from django.views.decorators.vary import vary_on_headers
-from ajaxable.utils import JSONResponse, AjaxableFormView
+from ajaxable.utils import AjaxableFormView
from catalogue import models
from catalogue import forms
from catalogue.utils import split_tags, MultiQuerySet, SortedMultiQuerySet
'catalogue/collection_list.html', collection_list(collections))
permanent_cache.set(cache_key, output)
if request.is_ajax():
- return JSONResponse(output)
+ return JsonResponse(output)
else:
return render_to_response('catalogue/catalogue.html', locals(),
context_instance=RequestContext(request))
if get_filter:
filter = get_filter()
books_by_author, orphans, books_by_parent = models.Book.book_list(filter)
- books_nav = SortedDict()
+ books_nav = OrderedDict()
for tag in books_by_author:
if books_by_author[tag]:
books_nav.setdefault(tag.sort_key[0], []).append(tag)
fragment_keys = [fragment.pk for fragment in fragments.iterator()]
if fragment_keys:
related_tags = models.Fragment.tags.usage(counts=True,
- filters={'pk__in': fragment_keys},
- extra={'where': ["catalogue_tag.category != 'book'"]})
+ filters={'pk__in': fragment_keys}).exclude(
+ category='book')
related_tags = (tag for tag in related_tags if tag not in fragment_tags)
categories = split_tags(related_tags, categories)
result = [prefix, tags_list]
else:
result = {"matches": tags_list}
- return JSONResponse(result, callback)
+ return JsonResponse(result, callback)
# =========
from django.core.urlresolvers import reverse
from django.contrib.auth.models import User
from django.contrib.contenttypes.models import ContentType
-from django.contrib.contenttypes import generic
+from django.contrib.contenttypes.fields import GenericForeignKey
from django.conf import settings
from jsonfield import JSONField
pickle = models.FileField(_('Continuations file'), upload_to='lesmianator')
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
- content_object = generic.GenericForeignKey('content_type', 'object_id')
+ content_object = GenericForeignKey('content_type', 'object_id')
class Meta:
unique_together = (('content_type', 'object_id'), )
super(ModelTagManager, self).__init__()
self.tag_model = tag_model
- def get_query_set(self):
+ def get_queryset(self):
content_type = ContentType.objects.get_for_model(self.model)
return self.tag_model.objects.filter(
items__content_type__pk=content_type.pk).distinct()
super(ModelTaggedItemManager, self).__init__()
self.intermediary_table_model = tag_model.objects.intermediary_table_model
- def related_to(self, obj, queryset=None, num=None, ignore_by_tag=None):
+ def related_to(self, obj, queryset=None):
if queryset is None:
return self.intermediary_table_model.objects.get_related(
- obj, self.model, num=num, ignore_by_tag=ignore_by_tag)
+ obj, self.model)
else:
return self.intermediary_table_model.objects.get_related(
- obj, queryset, num=num, ignore_by_tag=ignore_by_tag)
+ obj, queryset)
def with_all(self, tags, queryset=None):
if queryset is None:
Models and managers for generic tagging.
"""
-from django.contrib.contenttypes import generic
+from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
from django.db import connection, models
from django.utils.translation import ugettext_lazy as _
from django.db.models.base import ModelBase
-from django.db.models.loading import get_model # D1.7: apps?
from django.core.exceptions import ObjectDoesNotExist
from django.dispatch import Signal
tag_count = len(tags)
if not tag_count:
# No existing tags were given
- return queryset
+ return queryset.none()
elif tag_count == 1:
# Optimisation for single tag - fall through to the simpler
# query below.
queryset, model = get_queryset_and_model(queryset_or_model)
tags = self.tag_model.get_tag_list(tags)
if not tags:
- return queryset
+ return queryset.none()
# TODO: presumes reverse generic relation
return queryset.filter(tag_relations__tag__in=tags)
# TODO: presumes reverse generic relation.
# Do we know it's 'tags'?
return queryset.filter(tag_relations__tag__in=obj.tags).annotate(
- count=models.Count('pk')).order_by('-count').exclude(obj=obj.pk)
+ count=models.Count('pk')).order_by('-count').exclude(pk=obj.pk)
##########
'tag': models.ForeignKey(model, verbose_name=_('tag'), related_name='items'),
'content_type': models.ForeignKey(ContentType, verbose_name=_('content type')),
'object_id': models.PositiveIntegerField(_('object id'), db_index=True),
- 'content_object': generic.GenericForeignKey('content_type', 'object_id'),
+ 'content_object': GenericForeignKey('content_type', 'object_id'),
'__unicode__': obj_unicode,
}
WLTestCase, get_fixture)
from catalogue.models import Book
from librarian import WLURI, XMLNamespace
-from search import Index, Search
+from search.index import Index, Search
AtomNS = XMLNamespace("http://www.w3.org/2005/Atom")
if not settings.NO_SEARCH_INDEX:
def update_index(sender, instance, **kwargs):
- import search
- idx = search.Index()
+ from search.index import Index
+ idx = Index()
idx.index_tags(instance, remove_only=not 'created' in kwargs)
post_delete.connect(update_index, Author)
from django.db.models import permalink
from sorl.thumbnail import ImageField
from django.conf import settings
+from django.contrib.contenttypes.fields import GenericRelation
from django.core.files.storage import FileSystemStorage
from django.utils.datastructures import SortedDict
from django.template.loader import render_to_string
from django.utils.safestring import mark_safe
-from django.core.cache import get_cache
+from django.core.cache import caches
from catalogue.utils import split_tags
from fnpdjango.utils.text.slughifi import slughifi
from picture import tasks
from os import path
-permanent_cache = get_cache('permanent')
+permanent_cache = caches['permanent']
picture_storage = FileSystemStorage(location=path.join(
settings.MEDIA_ROOT, 'pictures'),
objects = models.Manager()
tagged = managers.ModelTaggedItemManager(catalogue.models.Tag)
tags = managers.TagDescriptor(catalogue.models.Tag)
+ tag_relations = GenericRelation(catalogue.models.Tag.intermediary_table_model)
@classmethod
def rectangle(cls, picture, kind, coords):
objects = models.Manager()
tagged = managers.ModelTaggedItemManager(catalogue.models.Tag)
tags = managers.TagDescriptor(catalogue.models.Tag)
+ tag_relations = GenericRelation(catalogue.models.Tag.intermediary_table_model)
class AlreadyExists(Exception):
pass
# This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later.
# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
#
+from collections import OrderedDict
from django.contrib.auth.decorators import permission_required
-from django.utils.datastructures import SortedDict
from django.shortcuts import render_to_response, get_object_or_404
from django.template import RequestContext
from picture.models import Picture
if get_filter:
filt = get_filter()
pictures_by_author, orphans = Picture.picture_list(filt)
- books_nav = SortedDict()
+ books_nav = OrderedDict()
for tag in pictures_by_author:
if pictures_by_author[tag]:
books_nav.setdefault(tag.sort_key[0], []).append(tag)
# This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later.
# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
#
-from index import Index, Search, SearchResult
)
def handle(self, *args, **opts):
from catalogue.models import Book
- import search
- idx = search.Index()
+ from search.index import Index
+ idx = Index()
if not opts['just_tags']:
if args:
def handle(self, *args, **opts):
from catalogue.models import Book
- import search
+ from search.index import Search
if opts['check']:
sfn = glob(settings.SEARCH_INDEX+'snippets/*')
except UnicodeDecodeError, ude:
print "error in snippets %d" % bkid
if opts['check2']:
- s = search.Search()
+ s = Search()
reader = s.searcher.getIndexReader()
numdocs = reader.numDocs()
for did in range(numdocs):
from os import path
import tempfile
from catalogue.models import Book, Tag
-from search import Index, Search, SearchResult
+from search.index import Index, Search, SearchResult
import catalogue
import opds
from django.shortcuts import render_to_response, get_object_or_404
from django.template import RequestContext
from django.views.decorators import cache
-from django.http import HttpResponse, HttpResponseRedirect, Http404, HttpResponsePermanentRedirect
+from django.http import HttpResponse, HttpResponseRedirect, Http404, HttpResponsePermanentRedirect, JsonResponse
from django.utils.translation import ugettext as _
from catalogue.utils import split_tags
from catalogue.models import Book, Tag, Fragment
from pdcounter.models import Author as PDCounterAuthor, BookStub as PDCounterBook
-from catalogue.views import JSONResponse
-from search import Search, SearchResult
+from search.index import Search, SearchResult
from suggest.forms import PublishingSuggestForm
import re
#import enchant
def hint(request):
prefix = request.GET.get('term', '')
if len(prefix) < 2:
- return JSONResponse([])
+ return JsonResponse([])
prefix = remove_query_syntax_chars(prefix)
return HttpResponse("%s(%s);" % (callback, json.dumps(data)),
content_type="application/json; charset=utf-8")
else:
- return JSONResponse(data)
+ return JsonResponse(data)
def main(request):
# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
#
from django.shortcuts import render, get_object_or_404, redirect
-from django.http import HttpResponseForbidden
+from django.http import HttpResponseForbidden, JsonResponse
from django.contrib.auth.decorators import login_required
from django.views.decorators.http import require_POST
-from ajaxable.utils import JSONResponse, AjaxableFormView
+from ajaxable.utils import AjaxableFormView
from catalogue.models import Book
from social import forms
set_sets(request.user, book, [tag])
if request.is_ajax():
- return JSONResponse({"success": True, "msg": "ok", "like": True})
+ return JsonResponse({"success": True, "msg": "ok", "like": True})
else:
return redirect(book)
set_sets(request.user, book, [])
if request.is_ajax():
- return JSONResponse({"success": True, "msg": "ok", "like": False})
+ return JsonResponse({"success": True, "msg": "ok", "like": False})
else:
return redirect(book)
# documentation root, use os.path.abspath to make it absolute, like shown here.
#sys.path.insert(0, os.path.abspath('.'))
sys.path += [
- os.path.abspath('../wolnelektury'),
+ os.path.abspath('..'),
os.path.abspath('../apps'),
os.path.abspath('../lib'),
os.path.abspath('../lib/librarian'),
]
-from django.core.management import setup_environ
-import settings
-setup_environ(settings)
+os.environ.setdefault("DJANGO_SETTINGS_MODULE", "wolnelektury.settings")
# General information about the project.
project = u'Wolne Lektury'
-copyright = u'2007-2012, Fundacja Nowoczesna Polska'
+copyright = u'2007-2014, Fundacja Nowoczesna Polska'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
Requirements
------------
-* `Python 2.6+ <http://python.org>`_
+* `Python 2.7 <http://python.org>`_
* Python requiremets: ``pip install -r requirements.txt``
* a library for your database of choice
(see `DBs supported by Django <http://docs.djangoproject.com/en/dev/topics/install/#get-your-database-running>`_)
Some tasks (like generating e-books) run in a seperate
Celery process by default, so you'll also need to run::
- ./manage.py celeryd --loglevel=INFO
+ celery -A wolnelektury worker --loglevel=INFO
Or, if you don't want to run a separate Celery daemon, set this
in your ``localsettings.py``::
BabelDjango
Fabric
sphinx
+pyinotify
django-pipeline>=1.3,<1.4
django-pagination>=1.0
django-maintenancemode>=0.10
-django-piston>=0.2.2.1,<0.2.3
+django-piston==0.2.2.1.2
jsonfield>=0.9.20
django-picklefield
django-modeltranslation==0.8b2
# MySQL-python>=1.2,<2.0
# celery tasks
-django-celery>=3.1,<3.2
+celery>=3.1.12,<3.2
+-e git+git://github.com/rczajka/kombu.git@4ed3622d1e801811410eda503e3eb8a6efd7f86f#egg=kombu
# spell checking
pyenchant
# -*- 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 model 'Payment'
- db.create_table(u'getpaid_payment', (
- (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
- ('amount', self.gf('django.db.models.fields.DecimalField')(max_digits=20, decimal_places=4)),
- ('currency', self.gf('django.db.models.fields.CharField')(max_length=3)),
- ('status', self.gf('django.db.models.fields.CharField')(default='new', max_length=20, db_index=True)),
- ('backend', self.gf('django.db.models.fields.CharField')(max_length=50)),
- ('created_on', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, db_index=True, blank=True)),
- ('paid_on', self.gf('django.db.models.fields.DateTimeField')(default=None, null=True, db_index=True, blank=True)),
- ('amount_paid', self.gf('django.db.models.fields.DecimalField')(default=0, max_digits=20, decimal_places=4)),
- ('order', self.gf('django.db.models.fields.related.ForeignKey')(related_name='payment', to=orm['funding.Funding'])),
- ))
- db.send_create_signal(u'getpaid', ['Payment'])
-
-
- def backwards(self, orm):
- # Deleting model 'Payment'
- db.delete_table(u'getpaid_payment')
-
-
- models = {
- 'catalogue.book': {
- 'Meta': {'ordering': "('sort_key',)", 'object_name': 'Book'},
- '_related_info': ('jsonfield.fields.JSONField', [], {'null': 'True', 'blank': 'True'}),
- 'changed_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'db_index': 'True', 'blank': 'True'}),
- 'common_slug': ('django.db.models.fields.SlugField', [], {'max_length': '120'}),
- 'cover': ('catalogue.fields.EbookField', [], {'max_length': '100', 'null': 'True', 'format_name': "'cover'", 'blank': 'True'}),
- 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'db_index': 'True', 'blank': 'True'}),
- 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'epub_file': ('catalogue.fields.EbookField', [], {'default': "''", 'max_length': '100', 'format_name': "'epub'", 'blank': 'True'}),
- 'extra_info': ('jsonfield.fields.JSONField', [], {'default': "'{}'"}),
- 'fb2_file': ('catalogue.fields.EbookField', [], {'default': "''", 'max_length': '100', 'format_name': "'fb2'", 'blank': 'True'}),
- 'gazeta_link': ('django.db.models.fields.CharField', [], {'max_length': '240', 'blank': 'True'}),
- 'html_file': ('catalogue.fields.EbookField', [], {'default': "''", 'max_length': '100', 'format_name': "'html'", 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'language': ('django.db.models.fields.CharField', [], {'default': "'pol'", 'max_length': '3', 'db_index': 'True'}),
- 'mobi_file': ('catalogue.fields.EbookField', [], {'default': "''", 'max_length': '100', 'format_name': "'mobi'", 'blank': 'True'}),
- 'parent': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'children'", 'null': 'True', 'to': "orm['catalogue.Book']"}),
- 'parent_number': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'pdf_file': ('catalogue.fields.EbookField', [], {'default': "''", 'max_length': '100', 'format_name': "'pdf'", 'blank': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '120'}),
- 'sort_key': ('django.db.models.fields.CharField', [], {'max_length': '120', 'db_index': 'True'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '120'}),
- 'txt_file': ('catalogue.fields.EbookField', [], {'default': "''", 'max_length': '100', 'format_name': "'txt'", 'blank': 'True'}),
- 'wiki_link': ('django.db.models.fields.CharField', [], {'max_length': '240', 'blank': 'True'}),
- 'xml_file': ('catalogue.fields.EbookField', [], {'default': "''", 'max_length': '100', 'format_name': "'xml'", 'blank': 'True'})
- },
- u'funding.funding': {
- 'Meta': {'ordering': "['-payed_at']", 'object_name': 'Funding'},
- 'amount': ('django.db.models.fields.DecimalField', [], {'max_digits': '10', 'decimal_places': '2'}),
- 'anonymous': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
- 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '127', 'blank': 'True'}),
- 'offer': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['funding.Offer']"}),
- 'payed_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
- 'perks': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['funding.Perk']", 'symmetrical': 'False', 'blank': 'True'})
- },
- u'funding.offer': {
- 'Meta': {'ordering': "['-end']", 'object_name': 'Offer'},
- 'author': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
- 'book': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['catalogue.Book']", 'null': 'True', 'blank': 'True'}),
- 'due': ('django.db.models.fields.DateField', [], {}),
- 'end': ('django.db.models.fields.DateField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'redakcja_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}),
- 'start': ('django.db.models.fields.DateField', [], {}),
- 'target': ('django.db.models.fields.DecimalField', [], {'max_digits': '10', 'decimal_places': '2'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '255'})
- },
- u'funding.perk': {
- 'Meta': {'ordering': "['-price']", 'object_name': 'Perk'},
- 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
- 'offer': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['funding.Offer']", 'null': 'True', 'blank': 'True'}),
- 'price': ('django.db.models.fields.DecimalField', [], {'max_digits': '10', 'decimal_places': '2'})
- },
- u'getpaid.payment': {
- 'Meta': {'ordering': "('-created_on',)", 'object_name': 'Payment'},
- 'amount': ('django.db.models.fields.DecimalField', [], {'max_digits': '20', 'decimal_places': '4'}),
- 'amount_paid': ('django.db.models.fields.DecimalField', [], {'default': '0', 'max_digits': '20', 'decimal_places': '4'}),
- 'backend': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'created_on': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'db_index': 'True', 'blank': 'True'}),
- 'currency': ('django.db.models.fields.CharField', [], {'max_length': '3'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'order': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'payment'", 'to': u"orm['funding.Funding']"}),
- 'paid_on': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True', 'db_index': 'True', 'blank': 'True'}),
- 'status': ('django.db.models.fields.CharField', [], {'default': "'new'", 'max_length': '20', 'db_index': 'True'})
- }
- }
-
- complete_apps = ['getpaid']
\ No newline at end of file
+from __future__ import unicode_literals
+
+from django.db import models, migrations
+import getpaid.abstract_mixin
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('funding', '0001_initial'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='Payment',
+ fields=[
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ ('amount', models.DecimalField(verbose_name='amount', max_digits=20, decimal_places=4)),
+ ('currency', models.CharField(max_length=3, verbose_name='currency')),
+ ('status', models.CharField(default=b'new', max_length=20, verbose_name='status', db_index=True, choices=[(b'new', 'new'), (b'in_progress', 'in progress'), (b'partially_paid', 'partially paid'), (b'paid', 'paid'), (b'failed', 'failed')])),
+ ('backend', models.CharField(max_length=50, verbose_name='backend')),
+ ('created_on', models.DateTimeField(auto_now_add=True, verbose_name='created on', db_index=True)),
+ ('paid_on', models.DateTimeField(default=None, null=True, verbose_name='paid on', db_index=True, blank=True)),
+ ('amount_paid', models.DecimalField(default=0, verbose_name='amount paid', max_digits=20, decimal_places=4)),
+ ('external_id', models.CharField(max_length=64, null=True, verbose_name='external id', blank=True)),
+ ('description', models.CharField(max_length=128, null=True, verbose_name='Description', blank=True)),
+ ('order', models.ForeignKey(related_name=b'payment', to='funding.Funding')),
+ ],
+ options={
+ 'ordering': ('-created_on',),
+ 'verbose_name': 'Payment',
+ 'verbose_name_plural': 'Payments',
+ },
+ bases=(models.Model, getpaid.abstract_mixin.AbstractMixin),
+ ),
+ ]
+++ /dev/null
-# -*- 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 'Payment.external_id'
- db.add_column(u'getpaid_payment', 'external_id',
- self.gf('django.db.models.fields.CharField')(max_length=64, null=True, blank=True),
- keep_default=False)
-
- # Adding field 'Payment.description'
- db.add_column(u'getpaid_payment', 'description',
- self.gf('django.db.models.fields.CharField')(max_length=128, null=True, blank=True),
- keep_default=False)
-
-
- def backwards(self, orm):
- # Deleting field 'Payment.external_id'
- db.delete_column(u'getpaid_payment', 'external_id')
-
- # Deleting field 'Payment.description'
- db.delete_column(u'getpaid_payment', 'description')
-
-
- models = {
- 'catalogue.book': {
- 'Meta': {'ordering': "('sort_key',)", 'object_name': 'Book'},
- '_related_info': ('jsonfield.fields.JSONField', [], {'null': 'True', 'blank': 'True'}),
- 'changed_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'db_index': 'True', 'blank': 'True'}),
- 'common_slug': ('django.db.models.fields.SlugField', [], {'max_length': '120'}),
- 'cover': ('catalogue.fields.EbookField', [], {'max_length': '100', 'null': 'True', 'format_name': "'cover'", 'blank': 'True'}),
- 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'db_index': 'True', 'blank': 'True'}),
- 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'epub_file': ('catalogue.fields.EbookField', [], {'default': "''", 'max_length': '100', 'format_name': "'epub'", 'blank': 'True'}),
- 'extra_info': ('jsonfield.fields.JSONField', [], {'default': "'{}'"}),
- 'fb2_file': ('catalogue.fields.EbookField', [], {'default': "''", 'max_length': '100', 'format_name': "'fb2'", 'blank': 'True'}),
- 'gazeta_link': ('django.db.models.fields.CharField', [], {'max_length': '240', 'blank': 'True'}),
- 'html_file': ('catalogue.fields.EbookField', [], {'default': "''", 'max_length': '100', 'format_name': "'html'", 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'language': ('django.db.models.fields.CharField', [], {'default': "'pol'", 'max_length': '3', 'db_index': 'True'}),
- 'mobi_file': ('catalogue.fields.EbookField', [], {'default': "''", 'max_length': '100', 'format_name': "'mobi'", 'blank': 'True'}),
- 'parent': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'children'", 'null': 'True', 'to': "orm['catalogue.Book']"}),
- 'parent_number': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
- 'pdf_file': ('catalogue.fields.EbookField', [], {'default': "''", 'max_length': '100', 'format_name': "'pdf'", 'blank': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '120'}),
- 'sort_key': ('django.db.models.fields.CharField', [], {'max_length': '120', 'db_index': 'True'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '120'}),
- 'txt_file': ('catalogue.fields.EbookField', [], {'default': "''", 'max_length': '100', 'format_name': "'txt'", 'blank': 'True'}),
- 'wiki_link': ('django.db.models.fields.CharField', [], {'max_length': '240', 'blank': 'True'}),
- 'xml_file': ('catalogue.fields.EbookField', [], {'default': "''", 'max_length': '100', 'format_name': "'xml'", 'blank': 'True'})
- },
- u'funding.funding': {
- 'Meta': {'ordering': "['-payed_at']", 'object_name': 'Funding'},
- 'amount': ('django.db.models.fields.DecimalField', [], {'max_digits': '10', 'decimal_places': '2'}),
- 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '127', 'blank': 'True'}),
- 'offer': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['funding.Offer']"}),
- 'payed_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
- 'perks': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['funding.Perk']", 'symmetrical': 'False', 'blank': 'True'})
- },
- u'funding.offer': {
- 'Meta': {'ordering': "['-end']", 'object_name': 'Offer'},
- 'author': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
- 'book': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['catalogue.Book']", 'null': 'True', 'blank': 'True'}),
- 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'due': ('django.db.models.fields.DateField', [], {}),
- 'end': ('django.db.models.fields.DateField', [], {}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'redakcja_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
- 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}),
- 'start': ('django.db.models.fields.DateField', [], {}),
- 'target': ('django.db.models.fields.DecimalField', [], {'max_digits': '10', 'decimal_places': '2'}),
- 'title': ('django.db.models.fields.CharField', [], {'max_length': '255'})
- },
- u'funding.perk': {
- 'Meta': {'ordering': "['-price']", 'object_name': 'Perk'},
- 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
- 'end_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
- 'offer': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['funding.Offer']", 'null': 'True', 'blank': 'True'}),
- 'price': ('django.db.models.fields.DecimalField', [], {'max_digits': '10', 'decimal_places': '2'})
- },
- u'getpaid.payment': {
- 'Meta': {'ordering': "('-created_on',)", 'object_name': 'Payment'},
- 'amount': ('django.db.models.fields.DecimalField', [], {'max_digits': '20', 'decimal_places': '4'}),
- 'amount_paid': ('django.db.models.fields.DecimalField', [], {'default': '0', 'max_digits': '20', 'decimal_places': '4'}),
- 'backend': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
- 'created_on': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'db_index': 'True', 'blank': 'True'}),
- 'currency': ('django.db.models.fields.CharField', [], {'max_length': '3'}),
- 'description': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True', 'blank': 'True'}),
- 'external_id': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True', 'blank': 'True'}),
- u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
- 'order': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'payment'", 'to': u"orm['funding.Funding']"}),
- 'paid_on': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True', 'db_index': 'True', 'blank': 'True'}),
- 'status': ('django.db.models.fields.CharField', [], {'default': "'new'", 'max_length': '20', 'db_index': 'True'})
- }
- }
-
- complete_apps = ['getpaid']
\ No newline at end of file
+++ /dev/null
-# -*- 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):
- pass
-
- def backwards(self, orm):
- pass
-
- models = {
-
- }
-
- complete_apps = ['payu']
\ No newline at end of file
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
- 'django.middleware.doc.XViewMiddleware',
+ 'django.contrib.admindocs.middleware.XViewMiddleware',
'pagination.middleware.PaginationMiddleware',
'django.middleware.locale.LocaleMiddleware',
'maintenancemode.middleware.MaintenanceModeMiddleware',
#'rosetta',
#'south',
'sorl.thumbnail',
- 'djcelery',
'kombu.transport.django',
'honeypot',
#'django_nose',
},
'permanent': {
'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
- 'TIMEOUT': 2419200,
+ 'TIMEOUT': None,
'LOCATION': [
'127.0.0.1:11211',
]
BROKER_URL = 'django://'
-CELERY_RESULT_BACKEND='djcelery.backends.database:DatabaseBackend'
CELERY_EAGER_PROPAGATES_EXCEPTIONS = True
CELERY_SEND_TASK_ERROR_EMAILS = True
MODELTRANSLATION_DEFAULT_LANGUAGE = 'pl'
MODELTRANSLATION_PREPOPULATE_LANGUAGE = 'pl'
-SOUTH_MIGRATION_MODULES = {
+MIGRATION_MODULES = {
'getpaid' : 'wolnelektury.migrations.getpaid',
- 'payu': 'wolnelektury.migrations.getpaid_payu',
}
GETPAID_ORDER_DESCRIPTION = "{% load funding_tags %}{{ order|sanitize_payment_title }}"
# Add apps and lib directories to PYTHONPATH
sys.path = [
ROOT,
- os.path.join(ROOT, 'wolnelektury'),
os.path.join(ROOT, 'apps'),
os.path.join(ROOT, 'lib'),
os.path.join(ROOT, 'lib/librarian'),
] + sys.path
-os.environ.setdefault("DJANGO_SETTINGS_MODULE", "settings")
+os.environ.setdefault("DJANGO_SETTINGS_MODULE", "wolnelektury.settings")
# This application object is used by the development server
# as well as any WSGI server configured to use this file.