def remove_tag(request, type, id): tag = request.GET.get('tag') if request.method == 'POST': ownedwrapper = OwnedWrapper.objects.get_for_object(user=request.user, type=type, object_id=id) Tag.objects.update_tags( ownedwrapper, ' '.join([ '"%s"' % s for s in Tag.objects.get_for_object(ownedwrapper).exclude( name=tag).values_list('name') ])) if request.is_ajax(): return HttpResponse(simplejson.dumps(dict(result='ok')), content_type='application/javascript') else: messages.add_message(request, messages.INFO, message="Tag removed successfully.") return HttpResponseRedirect( validate_next_link(request.GET.get('next'), '/')) return render(request, 'ui_tag_remove.html', { 'tag': tag, 'next': validate_next_link(request.GET.get('next')), })
def delete_selected_records(request): selected = list(request.session['selected_records']) deletable_items = [] for record in Record.filter_by_access(request.user, *selected): if record.editable_by(request.user): deletable_items.append(record) if request.method == 'POST': for record in deletable_items: if record.id in selected: selected.remove(record.id) record.delete() request.session['selected_records'] = selected from rooibos.middleware import HistoryMiddleware return HttpResponseRedirect( validate_next_link( request.GET.get('next'), HistoryMiddleware.go_back( request, to_before=reverse('ui-delete-selected'), default=reverse('solr-selected')))) return render(request, 'ui_delete_selected.html', { 'items': deletable_items, })
def media_delete(request, mediaid, medianame): media = get_object_or_404(Media, id=mediaid) if not media.editable_by(request.user): raise Http404() if request.method == 'POST': media.delete() return HttpResponseRedirect( validate_next_link(request.GET.get('next'), '.')) else: return HttpResponseNotAllowed(['POST'])
def media_upload(request, recordid, record): record = Record.get_or_404(recordid, request.user) if not record.editable_by(request.user): raise Http404() if request.method == 'POST': upload_file_form = media_upload_form(request) if not upload_file_form: raise Http404() form = upload_file_form(request.POST, request.FILES) if form.is_valid(): storage = Storage.objects.get( id=form.cleaned_data['storage'].split(',')[0]) file = request.FILES['file'] mimetype = mimetypes.guess_type(file.name)[0] or file.content_type limit = storage.get_upload_limit(request.user) if limit > 0 and file.size > limit * 1024: messages.add_message(request, messages.INFO, message="The uploaded file is too large.") return HttpResponseRedirect( validate_next_link(request.GET.get('next'), reverse('main'))) media = Media.objects.create(record=record, name=os.path.splitext(file.name)[0], storage=storage, mimetype=mimetype) media.save_file(file.name, file) return HttpResponseRedirect( validate_next_link(request.GET.get('next'), reverse('main'))) else: # Invalid form submission raise Http404() else: return HttpResponseNotAllowed(['POST'])
def save_collection_visibility_preferences(request): form = get_collection_visibility_prefs_form(request.user)(request.POST) if form.is_valid(): if set_collection_visibility_preferences( request.user, form.cleaned_data['show_or_hide'], form.cleaned_data['collections']): messages.add_message( request, messages.INFO, message="Collection visibility preferences saved.") next = validate_next_link(request.GET.get('next'), reverse('main')) return HttpResponseRedirect(next)
def add_tags(request, type, id): if request.method != 'POST': return HttpResponseNotAllowed(['POST']) tags = request.POST.get('tags') if '"' in tags: new_tags = parse_tag_input(tags) else: new_tags = [_f for _f in [s.strip() for s in tags.split(',')] if _f] ownedwrapper = OwnedWrapper.objects.get_for_object(user=request.user, type=type, object_id=id) for tag in new_tags: Tag.objects.add_tag(ownedwrapper, '"%s"' % tag) return HttpResponseRedirect( validate_next_link(request.GET.get('next'), '/'))
def password(request, id, name): presentation = get_object_or_404( filter_by_access(request.user, Presentation) .filter(Presentation.published_q(request.user), id=id) ) class PasswordForm(forms.Form): password = forms.CharField(widget=forms.PasswordInput) def clean_password(self): p = self.cleaned_data.get('password') if p != presentation.password: raise forms.ValidationError("Password is not correct.") return p if request.method == 'POST': form = PasswordForm(request.POST) if form.is_valid(): request.session.setdefault( 'passwords', dict() )[presentation.id] = form.cleaned_data.get('password') request.session.modified = True return HttpResponseRedirect(validate_next_link( request.GET.get('next'), reverse('presentation-browse'))) else: form = PasswordForm() return render( request, 'presentation_password.html', { 'form': form, 'presentation': presentation, 'next': request.GET.get('next', reverse('presentation-browse')), } )
def clear_selected_records(request): request.session['selected_records'] = () return HttpResponseRedirect( validate_next_link(request.GET.get('next'), reverse('solr-search')))
def create(request): existing_tags = Tag.objects.usage_for_model( OwnedWrapper, filters=dict( user=request.user, content_type=OwnedWrapper.t(Presentation) ) ) selected = request.session.get('selected_records', ()) next = validate_next_link( request.GET.get('next'), reverse('presentation-manage')) custom_permissions = getattr(settings, 'PRESENTATION_PERMISSIONS', None) class CreatePresentationForm(forms.Form): title = forms.CharField( label='Title', max_length=Presentation._meta.get_field('title').max_length ) add_selected = forms.BooleanField( label='Add selected records immediately', required=False, initial=True ) auth_access = forms.BooleanField( label='Set default permissions', required=False, initial=True ) if request.method == "POST": form = CreatePresentationForm(request.POST) if form.is_valid(): hidden = getattr(settings, 'PRESENTATION_HIDE_ON_CREATE', False) presentation = Presentation.objects.create( title=form.cleaned_data['title'], owner=request.user, hidden=hidden, ) if form.cleaned_data['add_selected']: add_selected_items(request, presentation) if form.cleaned_data['auth_access']: if not custom_permissions: g = ExtendedGroup.objects.filter(type=AUTHENTICATED_GROUP) g = g[0] if g else ExtendedGroup.objects.create( type=AUTHENTICATED_GROUP, name='Authenticated Users') AccessControl.objects.create( content_object=presentation, usergroup=g, read=True) else: for name in custom_permissions: g = ExtendedGroup.objects.filter(name=name) if len(g) == 0: g = Group.objects.filter(name=name) if len(g) == 0: continue AccessControl.objects.create( content_object=presentation, usergroup=g[0], read=True ) update_actionbar_tags(request, presentation) return HttpResponseRedirect( reverse( 'presentation-edit', kwargs={ 'id': presentation.id, 'name': presentation.name } ) ) else: form = CreatePresentationForm() return render( request, 'presentation_create.html', { 'form': form, 'next': next, 'selected': selected, 'existing_tags': existing_tags, 'can_publish': request.user.has_perm( 'presentation.publish_presentations'), 'custom_permissions': custom_permissions, } )
def record(request, id, name, contexttype=None, contextid=None, contextname=None, edit=False, customize=False, personal=False, copy=False, copyid=None, copyname=None): collections = apply_collection_visibility_preferences( request.user, Collection.objects.all()) writable_collections = list( filter_by_access(request.user, collections, write=True).values_list('id', flat=True)) readable_collections = list( filter_by_access(request.user, collections).values_list('id', flat=True)) personal_collections = None can_edit = request.user.is_authenticated() can_manage = False if id and name: record = Record.get_or_404(id, request.user) can_edit = can_edit and record.editable_by(request.user) can_manage = record.manageable_by(request.user) else: if request.user.is_authenticated(): if personal: personal_collections = \ get_allowed_collections_for_personal_records( request.user, readable_collections) if writable_collections or (personal and personal_collections): record = Record() if personal: record.owner = request.user else: raise Http404() else: raise Http404() if record.owner: if personal_collections is None: personal_collections = \ get_allowed_collections_for_personal_records( request.user, readable_collections) valid_collections = (set(personal_collections) | set(writable_collections)) else: valid_collections = writable_collections context = None if contexttype and contextid: app_label, model = contexttype.split('.') model_class = get_object_or_404(ContentType, app_label=app_label, model=model).model_class() context = get_object_or_404(filter_by_access(request.user, model_class), id=contextid) media = Media.objects.select_related().filter(record=record, storage__in=filter_by_access( request.user, Storage)) # Can any media be downloaded? download_image = False # Only list media that is downloadable or editable for m in media: # Calculate permissions and store with object for later use in template m.downloadable_in_template = m.is_downloadable_by(request.user) m.editable_in_template = m.editable_by(request.user) download_image = download_image or \ m.is_downloadable_by(request.user, original=False) media = [ m for m in media if m.downloadable_in_template or m.editable_in_template ] edit = edit and request.user.is_authenticated() copyrecord = Record.get_or_404(copyid, request.user) if copyid else None class FieldSetForm(forms.Form): fieldset = FieldSetChoiceField( user=request.user, default_label='Default' if not edit else None) fieldsetform = FieldSetForm(request.GET) if fieldsetform.is_valid(): if fieldsetform.cleaned_data['fieldset']: fieldset = FieldSet.for_user( request.user).get(id=fieldsetform.cleaned_data['fieldset']) else: fieldset = None elif edit: default_fieldset_name = getattr(settings, 'RECORD_DEFAULT_FIELDSET', 'dc') # Creating new record, use DC fieldset by default fieldset = FieldSet.objects.get(name=default_fieldset_name) else: fieldset = None collection_items = collectionformset = None if edit: if not can_edit and not customize and not context: return HttpResponseRedirect( reverse('data-record', kwargs=dict(id=id, name=name))) def _field_choices(): fsf = list( FieldSetField.objects.select_related('fieldset', 'field').all().order_by( 'fieldset__name', 'order', 'field__label')) grouped = {} for f in fsf: grouped.setdefault((f.fieldset.title, f.fieldset.id), []).append(f.field) others = list( Field.objects.exclude( id__in=[f.field.id for f in fsf]).order_by('label').values_list( 'id', 'label')) choices = [('', '-' * 10) ] + [(set[0], [(f.id, f.label) for f in fields]) for set, fields in sorted(iter(grouped.items()), key=lambda s: s[0][0])] if others: choices.append(('Others', others)) return choices class FieldValueForm(forms.ModelForm): def __init__(self, *args, **kwargs): super(FieldValueForm, self).__init__(*args, **kwargs) def clean_field(self): return Field.objects.get(id=self.cleaned_data['field']) def clean_context_type(self): context = self.cleaned_data.get('context_type') if context: context = ContentType.objects.get(id=context) return context def clean(self): cleaned_data = self.cleaned_data return cleaned_data field = forms.ChoiceField(choices=_field_choices()) value = forms.CharField(widget=forms.Textarea, required=False) context_type = forms.IntegerField(widget=forms.HiddenInput, required=False) context_id = forms.IntegerField(widget=forms.HiddenInput, required=False) index_value = forms.CharField(widget=forms.HiddenInput, required=False) browse_value = forms.CharField(widget=forms.HiddenInput, required=False) class Meta: model = FieldValue fields = "__all__" class CollectionForm(forms.Form): id = forms.IntegerField(widget=forms.HiddenInput) title = forms.CharField(widget=DisplayOnlyTextWidget) member = forms.BooleanField(required=False) shared = forms.BooleanField(required=False) fieldvalues_readonly = [] if customize or context: fieldvalues = record.get_fieldvalues( owner=request.user, context=context, hidden=True).filter(owner=request.user) else: fieldvalues = record.get_fieldvalues(hidden=True) field_value_formset = modelformset_factory( FieldValue, form=FieldValueForm, fields=FieldValueForm.Meta.fields, can_delete=True, extra=3) collection_formset = formset_factory(CollectionForm, extra=0) if request.method == 'POST': formset = field_value_formset(request.POST, request.FILES, queryset=fieldvalues, prefix='fv') if not (customize or context): collectionformset = collection_formset(request.POST, request.FILES, prefix='c') else: collectionformset = None if formset.is_valid() and (customize or context or collectionformset.is_valid()): record.save() if not (customize or context): collections = dict((c['id'], c) for c in collectionformset.cleaned_data if c['id'] in valid_collections) for item in record.collectionitem_set.filter( collection__in=valid_collections): if item.collection_id in collections: if not collections[item.collection_id]['member']: item.delete() elif collections[item.collection_id]['shared'] == \ item.hidden: item.hidden = not item.hidden item.save() del collections[item.collection_id] for coll in list(collections.values()): if coll['member']: CollectionItem.objects.create( record=record, collection_id=coll['id'], hidden=not coll['shared']) instances = formset.save(commit=False) # Explicitly remove deleted objects for instance in formset.deleted_objects: instance.delete() o1 = fieldvalues and max(v.order or 0 for v in fieldvalues) or 0 o2 = instances and max(v.order or 0 for v in instances) or 0 order = max(o1, o2, 0) for instance in instances: if not instance.value: if instance.id: instance.delete() continue instance.record = record if instance.order == 0: order += 1 instance.order = order if customize or context: instance.owner = request.user if context: instance.context = context instance.save() messages.add_message(request, messages.INFO, message="Record saved successfully.") url = reverse('data-record-edit-customize' if customize else 'data-record-edit', kwargs=dict(id=record.id, name=record.name)) next = validate_next_link( request.GET.get('next'), reverse('data-record', kwargs=dict(id=record.id, name=record.name))) return HttpResponseRedirect(url if 'save_and_continue' in request.POST else next) else: if copyrecord: initial = [] for fv in copyrecord.get_fieldvalues(hidden=True): initial.append( dict( label=fv.label, field=fv.field_id, refinement=fv.refinement, value=fv.value, date_start=fv.date_start, date_end=fv.date_end, numeric_value=fv.numeric_value, language=fv.language, order=fv.order, group=fv.group, hidden=fv.hidden, )) field_value_formset.extra = len(initial) + 3 elif fieldset: needed = fieldset.fields.filter(~Q( id__in=[fv.field_id for fv in fieldvalues])).order_by( 'fieldsetfield__order').values_list('id', flat=True) initial = [{'field': id2} for id2 in needed] field_value_formset.extra = len(needed) + 3 else: initial = [] formset = field_value_formset(queryset=fieldvalues, prefix='fv', initial=initial) if not (customize or context): collections = dict(((coll.id, dict(id=coll.id, title=coll.title)) for coll in Collection.objects.filter( id__in=valid_collections))) for item in (copyrecord or record).collectionitem_set.all(): collections.get(item.collection_id, {}).update( dict( member=True, shared=not item.hidden, )) collections = list(collections.values()) collectionformset = collection_formset(prefix='c', initial=collections) part_of_works = None related_works = None else: fieldvalues_readonly = record.get_fieldvalues(owner=request.user, fieldset=fieldset) formset = None if record.owner == request.user or request.user.is_superuser: q = Q() else: q = Q(hidden=False) collection_items = record.collectionitem_set.filter( q, collection__in=readable_collections) part_of_works = [] related_works = [] works = FieldValue.objects.filter( record=record, field__name='relation', field__standard__prefix='dc', owner=None, ).values_list('value', 'refinement') for work, refinement in works: if refinement and refinement.lower() == 'ispartof': part_of_works.append(work) elif not refinement: related_works.append(work) if can_edit: from rooibos.storage.views import media_upload_form upload_file_form = media_upload_form(request) upload_form = upload_file_form() if upload_file_form else None else: upload_form = None record_usage = record.presentationitem_set.values('presentation') \ .distinct().count() if can_edit else 0 back_url = HistoryMiddleware.go_back( request, to_before=reverse('data-record-back-helper-url'), ) if record.id: upload_url = ( "%s?sidebar&next=%s" % (reverse('storage-media-upload', args=(record.id, record.name)), request.get_full_path() + '?refreshthumb=1')) else: upload_url = None # In edit mode, optionally hide fieldset dropdown if formset and getattr(settings, 'HIDE_RECORD_FIELDSETS', False): fieldsetform = None return render( request, 'data_record.html', { 'record': record, 'media': media, 'fieldsetform': fieldsetform, 'fieldset': fieldset, 'fieldvalues': fieldvalues_readonly, 'context': context, 'customize': customize, 'fv_formset': formset, 'c_formset': collectionformset, 'can_edit': can_edit, 'can_manage': can_manage, 'next': validate_next_link(request.GET.get('next')), 'collection_items': collection_items, 'upload_form': upload_form, 'upload_url': upload_url, 'record_usage': record_usage, 'back_url': back_url, 'download_image': download_image, 'part_of_works': part_of_works, 'related_works': related_works, })
def import_files(request): available_storage = get_list_or_404( filter_by_access(request.user, Storage, write=True).order_by('title')) available_collections = get_list_or_404( filter_by_access(request.user, Collection)) writable_collection_ids = list( filter_by_access(request.user, Collection, write=True).values_list('id', flat=True)) storage_choices = [ make_storage_select_choice(s, request.user) for s in available_storage ] class UploadFileForm(forms.Form): collection = forms.ChoiceField(choices=( (c.id, '%s%s' % ('*' if c.id in writable_collection_ids else '', c.title)) for c in available_collections)) storage = forms.ChoiceField(choices=storage_choices) file = forms.FileField() create_records = forms.BooleanField(required=False) replace_files = forms.BooleanField(required=False, label='Replace files of same type') multiple_files = forms.BooleanField( required=False, label='Allow multiple files of same type') personal_records = forms.BooleanField(required=False) response_type = forms.CharField(required=False, widget=forms.HiddenInput) def clean(self): cleaned_data = self.cleaned_data if any(self.errors): return cleaned_data personal = cleaned_data['personal_records'] if not personal: if int(cleaned_data['collection']) not in \ writable_collection_ids: self._errors['collection'] = \ ErrorList([ "Can only add personal records " "to selected collection" ]) del cleaned_data['collection'] return cleaned_data if request.method == 'POST': form = UploadFileForm(request.POST, request.FILES) if form.is_valid(): create_records = form.cleaned_data['create_records'] replace_files = form.cleaned_data['replace_files'] multiple_files = form.cleaned_data['multiple_files'] personal_records = form.cleaned_data['personal_records'] collection = get_object_or_404( filter_by_access(request.user, Collection.objects.filter( id=form.cleaned_data['collection']), write=True if not personal_records else None)) storage = get_object_or_404( filter_by_access( request.user, Storage.objects.filter( id=form.cleaned_data['storage'].split(',')[0]), write=True)) file = request.FILES['file'] record = None limit = storage.get_upload_limit(request.user) if limit > 0 and file.size > limit * 1024: result = "The uploaded file is too large (%d>%d)." % ( file.size, limit * 1024) else: mimetype = mimetypes.guess_type(file.name)[0] or \ file.content_type owner = request.user if personal_records else None id = os.path.splitext(file.name)[0] # find record by identifier titlefield = standardfield('title') idfield = standardfield('identifier') # Match identifiers that are either full file name # (with extension) or just base name match records = find_record_by_identifier( ( id, file.name, ), collection, owner=owner, ignore_suffix=multiple_files) result = "File skipped." if len(records) == 1: # Matching record found record = records[0] media = record.media_set.filter(storage=storage, mimetype=mimetype) media_same_id = media.filter(name=id) if len(media) == 0 or \ (len(media_same_id) == 0 and multiple_files): # No media yet media = Media.objects.create(record=record, name=id, storage=storage, mimetype=mimetype) media.save_file(file.name, file) result = "File added (Identifier '%s')." % id elif len(media_same_id) > 0 and multiple_files: # Replace existing media with same name and mimetype media = media_same_id[0] media.delete_file() media.save_file(file.name, file) result = "File replaced (Identifier '%s')." % id elif replace_files: # Replace existing media with same mimetype media = media[0] media.delete_file() media.save_file(file.name, file) result = "File replaced (Identifier '%s')." % id else: result = "File skipped, media files already attached." elif len(records) == 0: # No matching record found if create_records: # Create a record record = Record.objects.create(name=id, owner=owner) CollectionItem.objects.create(collection=collection, record=record) FieldValue.objects.create(record=record, field=idfield, value=id, order=0) FieldValue.objects.create(record=record, field=titlefield, value=id, order=1) media = Media.objects.create(record=record, name=id, storage=storage, mimetype=mimetype) media.save_file(file.name, file) result = \ "File added to new record (Identifier '%s')." % id else: result = \ "File skipped, no matching record found " \ "(Identifier '%s')." % id else: result = \ "File skipped, multiple matching records found " \ "(Identifier '%s')." % id # Multiple matching records found pass if form.cleaned_data['response_type'] == 'json': return HttpResponse(content=simplejson.dumps( dict(status='ok', message=result)), content_type='application/json') messages.add_message(request, messages.INFO, message=result) next = validate_next_link(request.GET.get('next'), request.get_full_path()) return HttpResponseRedirect(next) else: pass else: form = UploadFileForm() return render(request, 'storage_import_files.html', { 'upload_form': form, })