def edit(): """ POST /comic/edit/:id Updates comic details. """ comic = get_or_404(db.comic, request.args(0)) # Ensure the user owns this comic if not comic_helpers.user_can_edit(db, comic.id, auth.user.id): flash_and_redirect_back('danger', 'You cannot edit a comic you did not create.') form = ComicForm(comic) if form.process().accepted: flash('info', 'Comic updated successfully.', comic.url) elif form.form.errors: flash('danger', 'Form has errors.') return { 'form': form.form, 'comic': comic, 'owner': auth.user, }
def delete(): """ POST /box/delete/:id Deletes a box and ensures any comics that were in only this box are moved to 'Unfiled'. """ box = get_or_404(db.box, request.args(0), owner=auth.user.id) if box.is_unfiled: flash('danger', 'You cannot delete the Unfiled box.', box.url) comics = [x.comic for x in box.comicbox.select()] # Find the comics who only reside in the box we're deleting count = db.comicbox.id.count() comic_just_in_box = db(db.comicbox.comic.belongs(comics)).select(db.comicbox.id, count, groupby=db.comicbox.comic) comic_just_in_box = filter(lambda row: row[count] == 1, comic_just_in_box) # Move all comics that only reside in the box we're deleting to 'Unfiled' for record in comic_just_in_box: record.comicbox.update_record(box=_unfiled_box().id) # Remove all comics from this box db(db.comicbox.box == box.id).delete() # Delete the old box box.delete_record() flash('info', '%s box deleted.' % box.name, URL('collection', 'view', args=[auth.user.id]))
def search(): """ GET /comic/search?search=:query Searches all public comics across a number of criteria. """ original_search = request.get_vars.get('search', '') user_id = auth.user.id if auth.is_logged_in() else 0 # generate a base query which finds all comics that the logged in user has permission to see base_query = db(db.comic.id == db.comicbox.comic)(db.comicbox.box == db.box.id)( (db.box.private == False) | (db.box.owner == user_id)) # basic partial matching fuzzy_like = lambda f, q: f.like('%{0}%'.format(q)) # generate the queries for each criteria queries = { 'title': lambda q: base_query(fuzzy_like(db.comic.title, q)), 'publisher': lambda q: base_query(db.publisher.id == db.comic.publisher)(fuzzy_like(db.publisher.name, q)), 'writer': lambda q: base_query(db.comicwriter.comic == db.comic.id)(db.writer.id == db.comicwriter.writer)( fuzzy_like(db.writer.name, q)), 'artist': lambda q: base_query(db.comicartist.comic == db.comic.id)(db.artist.id == db.comicartist.artist)( fuzzy_like(db.artist.name, q)), } only_field, search = None, original_search search_parts = original_search.split(':', 1) # determine which (if any) criteria to search against if len(search_parts) > 1: if search_parts[0] in queries: only_field, search = search_parts else: flash('danger', 'Invalid criteria "%s", expected one of: %s' % (search_parts[0], ', '.join(queries.keys()))) if only_field: # filter using a single criteria comics = queries[only_field](search).select(db.comic.ALL, distinct=True) else: # combine all queries to a single set of comics query_results = map(lambda q: q(search).select(db.comic.ALL, distinct=True), queries.values()) comics = reduce(lambda c, q: c | q, query_results) return { 'original_search': original_search, 'search': search, 'comics': comics, 'only_field': only_field }
def create(): """ POST /box/create Creates a new box for this user. """ form = SQLFORM(db.box, fields=['name', 'private']) add_element_required_attr(db.box, form) form.vars.owner = auth.user if form.process(onvalidation=_validate_box_form).accepted: flash('success', 'Created box.', URL('box', 'view', args=[form.vars.id])) elif form.errors: flash('danger', 'Form has errors.') return { 'form': form }
def view(): """ GET /box/view/:id Views a box, ensures that the logged in user has permission to view it. """ user_id = auth.user.id if auth.is_logged_in() else 0 box = get_or_404(db.box, ((db.box.id == request.args(0)) & ((db.box.owner == user_id) | (db.box.private == False)))) # find all comics in this box comics = db(db.comicbox.comic == db.comic.id)(db.comicbox.box == box.id).select(db.comic.ALL) comic_ids = map(lambda c: c.id, comics) # find all the comics owned by this user that aren't already in the box other_comics = db(db.comic.id == db.comicbox.comic)(db.box.id == db.comicbox.box)( db.box.owner == user_id).select(db.comic.ALL, groupby=db.comic.id) other_comics = filter(lambda c: c.id not in comic_ids, other_comics) user_owned = user_id == box.owner.id can_edit = user_owned and not box.is_unfiled if can_edit: rename_form = SQLFORM(db.box, box, fields=['name'], showid=False) add_element_required_attr(db.box, rename_form) if rename_form.process(onvalidation=_validate_box_form).accepted: flash('info', 'Box renamed successfully.', request.env['PATH_INFO']) elif rename_form.errors: flash('danger', 'Form has errors.') else: rename_form = None return { 'box': box, 'comics': comics, 'other_comics': other_comics, 'can_edit': can_edit, 'user_owned': user_owned, 'rename_form': rename_form }
def create(): """ POST /comic/create?box=:box_id Creates a new comic. """ form = ComicForm() # Pre-select the box that the user wants to add to if not form.form.vars.box and request.get_vars['box']: form.form.vars.box = get_or_404(db.box, request.get_vars['box'], owner=auth.user.id).id if form.process().accepted: flash('success', 'Created comic.', URL('comic', 'view', args=[form.id])) elif form.form.errors: flash('danger', 'Form has errors.') return { 'form': form.form, 'owner': auth.user, }
def add_comic(): """ POST /box/add_comic Adds a comic to a box, also may create or update an existing box if 'new box' was specified. The 'comic' POST var can occur multiple times to add many comics to a single box in one operation. """ # Create a new box if request.post_vars['box'] == 'new': target_box = db.box(db.box.name.like(request.post_vars['name']) & (db.box.owner == auth.user.id)) private = bool(request.post_vars['private']) if target_box: target_box.update(private=private) else: target_box_id = db.box.insert(name=request.post_vars['name'], owner=auth.user.id, private=private) target_box = db.box[target_box_id] else: target_box = get_or_404(db.box, request.post_vars['box'], owner=auth.user.id) raw_comic = request.post_vars['comic'] if raw_comic is None: flash_and_redirect_back('warning', 'No comics selected.') comics = raw_comic if isinstance(raw_comic, list) else [raw_comic] for source_comic_id in comics: source_comic = get_or_404(db.comic, source_comic_id) # Is the comic already in the box we want to add it to? if db.comicbox((db.comicbox.box == target_box.id) & (db.comicbox.comic == source_comic.id)): flash_and_redirect_back('warning', 'This comic already exists in %s.' % target_box.name) # If this user doesn't own the comic, duplicate it if db(db.box.owner == auth.user.id)(db.comicbox.box == db.box.id)(db.comicbox.comic == source_comic.id).isempty(): target_comic_id = db.comic.insert( publisher=source_comic.publisher, title=source_comic.title, issue=source_comic.issue, description=source_comic.description, cover_image=source_comic.cover_image ) for comicwriter in source_comic.comicwriter.select(): db.comicwriter.insert(writer=comicwriter.writer, comic=target_comic_id) for comicartist in source_comic.comicartist.select(): db.comicartist.insert(artist=comicartist.artist, comic=target_comic_id) elif target_box.is_unfiled: return flash_and_redirect_back('danger', 'This comic cannot be added to "Unfiled" as it is already belongs to a box.') else: target_comic_id = source_comic.id # Add comic to box db.comicbox.insert(comic=target_comic_id, box=target_box.id) # Find the Unfiled box for this user if not target_box.is_unfiled: db((db.comicbox.comic == target_comic_id) & (db.comicbox.box == _unfiled_box().id)).delete() flash_text = 'Added comic%s to %s.' % ('s' if len(comics) > 1 else '', target_box.name) # if we just duplicated this comic, redirect to the new comic if source_comic.owner.id != auth.user.id: flash('success', flash_text, URL('comic', 'view', args=[target_comic_id])) # otherwise, redirect back else: flash_and_redirect_back('success', flash_text)