-i https://py.mdrn.pl/simple/
# django
-Django==2.2.8
+Django==2.2.9
fnpdjango==0.4
docutils
books = Book.tagged.with_all(tags)
else:
books = Book.objects.all()
+ books = books.filter(findable=True)
books = order_books(books, new_api)
if not Membership.is_active_for(self.request.user):
after = self.request.query_params.get('after')
count = int(self.request.query_params.get('count', 50))
books = order_books(Book.objects.distinct(), new_api)
+ books = books.filter(findable=True)
if is_lektura is not None:
books = books.filter(has_audience=is_lektura)
if is_audiobook is not None:
)
except ValueError:
raise Http404
- return Fragment.tagged.with_all(tags).select_related('book')
+ return Fragment.tagged.with_all(tags).filter(book__findable=True).select_related('book')
@vary_on_auth # Because of 'liked'.
def items(self, args):
objects = models.BookMedia.objects.order_by('-uploaded_at')
+ objects = objects.filter(book__findable=True)
if type == 'all':
objects = objects.filter(type__in=('mp3', 'ogg', 'daisy'))
else:
count_for_book(child, count_by_combination, combs_for_child)
count_by_combination = defaultdict(lambda: 0)
- for b in Book.objects.filter(parent=None):
+ for b in Book.objects.filter(findable=True, parent=None):
count_for_book(b, count_by_combination)
next_combinations = defaultdict(set)
def get_audiobook_tags():
audiobook_tag_ids = cache.get('audiobook_tags')
if audiobook_tag_ids is None:
- books_with_audiobook = Book.objects.filter(media__type__in=('mp3', 'ogg'))\
+ books_with_audiobook = Book.objects.filter(findable=True, media__type__in=('mp3', 'ogg'))\
.distinct().values_list('pk', flat=True)
audiobook_tag_ids = Tag.objects.filter(
items__content_type=ContentType.objects.get_for_model(Book),
'-S', '--no-search-index', action='store_false',
dest='search_index', default=True,
help='Skip indexing imported works for search')
+ parser.add_argument(
+ '-F', '--not-findable', action='store_false',
+ dest='findable', default=True,
+ help='Set book as not findable.')
parser.add_argument(
'-p', '--picture', action='store_true', dest='import_picture',
default=False, help='Import pictures')
file_base, ext = os.path.splitext(file_path)
book = Book.from_xml_file(file_path, overwrite=options.get('force'),
dont_build=dont_build,
- search_index_tags=False)
+ search_index_tags=False,
+ findable=options.get('findable'),
+ )
for ebook_format in Book.ebook_formats:
if os.path.isfile(file_base + '.' + ebook_format):
getattr(book, '%s_file' % ebook_format).save(
--- /dev/null
+# Generated by Django 2.2.9 on 2019-12-30 21:57
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('catalogue', '0026_book_preview_key'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='book',
+ name='findable',
+ field=models.BooleanField(db_index=True, default=True, verbose_name='findable'),
+ ),
+ ]
preview = models.BooleanField(_('preview'), default=False)
preview_until = models.DateField(_('preview until'), blank=True, null=True)
preview_key = models.CharField(max_length=32, blank=True, null=True)
+ findable = models.BooleanField(_('findable'), default=True, db_index=True)
# files generated during publication
cover = EbookField(
format_)
field_name = "%s_file" % format_
- books = Book.objects.filter(parent=None).exclude(**{field_name: ""}).exclude(preview=True)
+ books = Book.objects.filter(parent=None).exclude(**{field_name: ""}).exclude(preview=True).exclude(findable=False)
paths = [(pretty_file_name(b), getattr(b, field_name).path) for b in books.iterator()]
return create_zip(paths, app_settings.FORMAT_ZIPS[format_])
return create_zip(paths, "%s_%s" % (self.slug, format_))
def search_index(self, book_info=None, index=None, index_tags=True, commit=True):
+ if not self.findable:
+ return
if index is None:
from search.index import Index
index = Index()
@classmethod
def from_text_and_meta(cls, raw_file, book_info, overwrite=False, dont_build=None, search_index=True,
- search_index_tags=True, remote_gallery_url=None, days=0):
+ search_index_tags=True, remote_gallery_url=None, days=0, findable=True):
if dont_build is None:
dont_build = set()
dont_build = set.union(set(dont_build), set(app_settings.DONT_BUILD))
if book.preview:
book.xml_file.set_readable(False)
+ book.findable = findable
book.language = book_info.language
book.title = book_info.title
if book_info.variant_of:
if format_ not in dont_build:
getattr(book, '%s_file' % format_).build_delay()
- if not settings.NO_SEARCH_INDEX and search_index:
+ if not settings.NO_SEARCH_INDEX and search_index and findable:
tasks.index_book.delay(book.id, book_info=book_info, index_tags=search_index_tags)
for child in notify_cover_changed:
def other_versions(self):
"""Find other versions (i.e. in other languages) of the book."""
- return type(self).objects.filter(common_slug=self.common_slug).exclude(pk=self.pk)
+ return type(self).objects.filter(common_slug=self.common_slug, findable=True).exclude(pk=self.pk)
def parents(self):
books = []
"""
objects = cls.tagged.with_all(tags)
- return objects.exclude(ancestor__in=objects)
+ return objects.filter(findable=True).exclude(ancestor__in=objects)
@classmethod
def book_list(cls, book_filter=None):
"""
books_by_parent = {}
- books = cls.objects.order_by('parent_number', 'sort_key').only('title', 'parent', 'slug', 'extra_info')
+ books = cls.objects.filter(findable=True).order_by('parent_number', 'sort_key').only('title', 'parent', 'slug', 'extra_info')
if book_filter:
books = books.filter(book_filter).distinct()
# Reserve one spot for an image.
max_books -= 1
- books_qs = Book.objects.all()
+ books_qs = Book.objects.filter(findable=True)
if not is_picture:
books_qs = books_qs.exclude(common_slug=instance.common_slug).exclude(ancestor=instance)
books = Book.tagged.related_to(instance, books_qs)[:max_books]
from .. import app_settings
if random() < app_settings.RELATED_RANDOM_PICTURE_CHANCE:
return None
- queryset = Book.objects.exclude(pk__in=exclude_ids)
+ queryset = Book.objects.filter(findable=True).exclude(pk__in=exclude_ids)
count = queryset.count()
if count:
return queryset[randint(0, count - 1)]
else:
if tag_ids is not None:
tags = Tag.objects.filter(pk__in=tag_ids)
- fragments = Fragment.tagged.with_all(tags).order_by().only('id')
+ fragments = Fragment.tagged.with_all(tags).filter(book__findable=True).order_by().only('id')
else:
- fragments = Fragment.objects.all().order_by().only('id')
+ fragments = Fragment.objects.filter(book__findable=True).order_by().only('id')
fragment_count = fragments.count()
fragment = fragments[randint(0, fragment_count - 1)] if fragment_count else None
return fragment
def catalogue(request):
return render(request, 'catalogue/catalogue.html', {
- 'books': Book.objects.filter(parent=None),
+ 'books': Book.objects.filter(findable=True, parent=None),
'pictures': Picture.objects.all(),
'collections': Collection.objects.all(),
'active_menu_item': 'all_works',
def literature(request):
- books = Book.objects.filter(parent=None)
+ books = Book.objects.filter(parent=None, findable=True)
return object_list(request, books, related_tags=get_top_level_related_tags([]))
def audiobooks(request):
- audiobooks = Book.objects.filter(media__type__in=('mp3', 'ogg')).distinct()
+ audiobooks = Book.objects.filter(findable=True, media__type__in=('mp3', 'ogg')).distinct()
return object_list(request, audiobooks, list_type='audiobooks', extra={
- 'daisy': Book.objects.filter(media__type='daisy').distinct(),
+ 'daisy': Book.objects.filter(findable=True, media__type='daisy').distinct(),
})
# TODO: Pictures on shelves not supported yet.
books = Book.tagged.with_all(shelf_tags).order_by()
fragments = fragments.filter(Q(book__in=books) | Q(book__ancestor__in=books))
+ else:
+ fragments = fragments.filter(book__findable=True)
if not fragments and len(tags) == 1 and list_type == 'books':
if PictureArea.tagged.with_any(tags).exists() or Picture.tagged.with_any(tags).exists():
if any(tag.category == 'set' for tag in tags):
params = {'objects': books}
else:
+ books = books.filter(findable=True)
params = {
- 'objects': Book.tagged_top_level(tags),
+ 'objects': Book.tagged_top_level(tags).filter(findable=True),
'fragments': Fragment.objects.filter(book__in=books),
'related_tags': get_top_level_related_tags(tags),
}
elif list_type == 'gallery':
params = {'objects': Picture.tagged.with_all(tags)}
elif list_type == 'audiobooks':
- audiobooks = Book.objects.filter(media__type__in=('mp3', 'ogg')).distinct()
+ audiobooks = Book.objects.filter(findable=True, media__type__in=('mp3', 'ogg')).distinct()
params = {
'objects': Book.tagged.with_all(tags, audiobooks),
'extra': {
@task(ignore_result=True)
def build_notes(book):
+ if not book.findable:
+ return
task_logger.info(book.slug)
with transaction.atomic():
book.notesource_set.all().delete()
def notes_from_book(sender, instance, **kwargs):
- build_notes.delay(instance)
+ if instance.findable:
+ build_notes.delay(instance)
Book.html_built.connect(notes_from_book)
year_zero = timezone.make_aware(datetime(1990, 1, 1, 0, 0, 0), timezone.utc)
try:
- earliest_change = Book.objects.filter(preview=False).order_by('changed_at')[0].changed_at
+ earliest_change = Book.objects.filter(findable=True, preview=False).order_by('changed_at')[0].changed_at
except IndexError:
earliest_change = year_zero
raise error.NoSetHierarchyError("Wolne Lektury does not support sets.")
# books = Book.tagged.with_all([tag])
else:
- books = Book.objects.filter(preview=False)
+ books = Book.objects.filter(findable=True, preview=False)
deleted = Deleted.objects.exclude(slug__exact='')
books = books.order_by('changed_at')
results = q.execute()
book_scores = dict([(r['book_id'], r['score']) for r in results])
- books = Book.objects.filter(id__in=set([r['book_id'] for r in results]))
+ books = Book.objects.filter(findable=True, id__in=set([r['book_id'] for r in results]))
books = list(books)
books.sort(reverse=True, key=lambda book: book_scores[book.id])
return books
def _find_some_books(query_terms=None, max_results=20):
from .index import SearchResult
- qs = Book.objects.order_by('?')
+ qs = Book.objects.filter(findable=True).order_by('?')
results = []
for book in qs[:randint(1, max_results)]:
doc = {
'id': b.id,
'url': b.get_absolute_url()
}
- for b in Book.objects.filter(title__iregex='\m' + prefix)[:limit-len(data)]
+ for b in Book.objects.filter(findable=True, title__iregex='\m' + prefix)[:limit-len(data)]
]
callback = request.GET.get('callback', None)
if callback:
@never_cache
def main_page(request):
ctx = {
- 'last_published': Book.objects.exclude(cover_thumb='').filter(parent=None).order_by('-created_at')[:6],
+ 'last_published': Book.objects.exclude(cover_thumb='').filter(findable=True, parent=None).order_by('-created_at')[:6],
'theme_books': [],
}
if Fragment.objects.exists():
while True:
ctx['theme'] = Tag.objects.filter(category='theme').order_by('?')[:1][0]
- tf = Fragment.tagged.with_any([ctx['theme']]).select_related('book').order_by('?')[:100]
+ tf = Fragment.tagged.with_any([ctx['theme']]).select_related('book').filter(book__findable=True).order_by('?')[:100]
if not tf:
continue
ctx['theme_fragment'] = tf[0]
except IndexError:
pass
- ctx['best'] = Book.objects.order_by('?')[:5]
+ ctx['best'] = Book.objects.filter(findable=True).order_by('?')[:5]
return render(request, "main_page.html", ctx)