Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • frank/uhepp.org
1 result
Show changes
Commits on Source (11)
Showing
with 191 additions and 29 deletions
...@@ -131,3 +131,17 @@ body { ...@@ -131,3 +131,17 @@ body {
background-size: contain; background-size: contain;
} }
} }
.alert {
border-bottom: none;
border-left: none;
border-right: none;
border-top-width: 0.25rem;
}
.alert-danger {
border-color: theme-color("danger");
}
.alert-success {
border-color: theme-color("success");
}
...@@ -2,7 +2,7 @@ import React, { useState } from "react"; ...@@ -2,7 +2,7 @@ import React, { useState } from "react";
import { AxisLeft, AxisBottom } from '@vx/axis'; import { AxisLeft, AxisBottom } from '@vx/axis';
import { AxisRight, AxisTop } from '@vx/axis'; import { AxisRight, AxisTop } from '@vx/axis';
import { AreaStack } from '@vx/shape'; import { AreaStack } from '@vx/shape';
import { scaleLinear, scaleOrdinal } from '@vx/scale'; import { scaleLinear, scaleLog } from '@vx/scale';
import { Group } from '@vx/group'; import { Group } from '@vx/group';
import { extent } from 'd3-array'; import { extent } from 'd3-array';
import { mathjax } from 'mathjax-full/js/mathjax'; import { mathjax } from 'mathjax-full/js/mathjax';
...@@ -666,20 +666,35 @@ const UheppHistPost = ({width, height, uhepp}) => { ...@@ -666,20 +666,35 @@ const UheppHistPost = ({width, height, uhepp}) => {
domain: extent(uhepp.bins.rebin || uhepp.bins.edges), domain: extent(uhepp.bins.rebin || uhepp.bins.edges),
}) })
const maxBinMain = getMaxBin(post_uhepp) const maxBinMain = getMaxBin(post_uhepp)
const yScale = scaleLinear({ const isScaleLin = !(uhepp.y_axis && uhepp.y_axis.log)
range: [yMax, 0], const yScaleMin = (uhepp.y_axis && uhepp.y_axis.min) ?? (isScaleLin ? 0 : 1);
domain: [0, maxBinMain * 1.5], const yScaleMax = (uhepp.y_axis && uhepp.y_axis.max) ?? (isScaleLin ? maxBinMain * 1.5 : maxBinMain * 10**1.5 );
})
const ratioScale = scaleLinear({
const yScale = isScaleLin ? (
scaleLinear({
range: [yMax, 0],
domain: [yScaleMin, yScaleMax],
})
) : (
scaleLog({
range: [yMax, 0],
domain: [yScaleMin, yScaleMax],
clamp: true,
})
)
const isRatioScaleLin = !(uhepp.ratio_axis && uhepp.ratio_axis.log)
const ratioScaleMaker = isRatioScaleLin ? scaleLinear : scaleLog
const ratioScale = ratioScaleMaker({
range: [ratioMax, 0], range: [ratioMax, 0],
domain: [ domain: [
(uhepp.ratio_axis && uhepp.ratio_axis.min) || 0.5, (uhepp.ratio_axis && uhepp.ratio_axis.min) ?? 0.5,
(uhepp.ratio_axis && uhepp.ratio_axis.max) || 1.5, (uhepp.ratio_axis && uhepp.ratio_axis.max) ?? 1.5,
], ],
clamp: !isRatioScaleLin,
}) })
const equidistent = computeEquidistent(uhepp.bins.rebin || uhepp.bins.edges, uhepp.bins.density_width) const equidistent = computeEquidistent(uhepp.bins.rebin || uhepp.bins.edges, uhepp.bins.density_width)
return ( return (
...@@ -877,7 +892,7 @@ const UheppHistPost = ({width, height, uhepp}) => { ...@@ -877,7 +892,7 @@ const UheppHistPost = ({width, height, uhepp}) => {
numTicks={5} numTicks={5}
tickTransform="translate(8, 0)" tickTransform="translate(8, 0)"
/> />
{ uhepp.ratio_axis.label && { uhepp.ratio_axis && uhepp.ratio_axis.label &&
<g transform={`matrix(0 -1 1 0 ${-margin.left + 20} ${ratioMax / 2})`}> <g transform={`matrix(0 -1 1 0 ${-margin.left + 20} ${ratioMax / 2})`}>
<MixedText y={0} x={0} align="center"> <MixedText y={0} x={0} align="center">
{ uhepp.ratio_axis.label } { uhepp.ratio_axis.label }
......
...@@ -6,8 +6,8 @@ import { SketchPicker } from 'react-color'; ...@@ -6,8 +6,8 @@ import { SketchPicker } from 'react-color';
const noVariationUsed = (uhepp) => { const noVariationUsed = (uhepp) => {
const main_names = uhepp.stacks.map(stack => stack.content.map(item => item.yields)).flat() const main_names = uhepp.stacks.map(stack => stack.content.map(item => item.yields)).flat()
const num_names = uhepp.ratio.map(item => item.numerator).flat() const num_names = uhepp.ratio ? uhepp.ratio.map(item => item.numerator).flat() : []
const den_names = uhepp.ratio.map(item => item.denominator).flat() const den_names = uhepp.ratio ? uhepp.ratio.map(item => item.denominator).flat() : []
const names = [main_names, den_names, num_names].flat() const names = [main_names, den_names, num_names].flat()
const varied_names = names.filter(name => (name && name.indexOf("/") != -1)) const varied_names = names.filter(name => (name && name.indexOf("/") != -1))
...@@ -675,13 +675,13 @@ const UheppHistUI = ({width, height, uhepp, uuid, size}) => { ...@@ -675,13 +675,13 @@ const UheppHistUI = ({width, height, uhepp, uuid, size}) => {
const [envId, setEnvId] = useState(0) const [envId, setEnvId] = useState(0)
const [envName, setEnvName] = useState("NOMINAL") const [envName, setEnvName] = useState("NOMINAL")
const [stacks, setStacks] = useState(uhepp.stacks) const [stacks, setStacks] = useState(uhepp.stacks)
const [ratio, setRatio] = useState(uhepp.ratio) const [ratio, setRatio] = useState(uhepp.ratio || [])
const reset = () => { const reset = () => {
setEnvId(0) setEnvId(0)
setEnvName("NOMINAL") setEnvName("NOMINAL")
setStacks(uhepp.stacks) setStacks(uhepp.stacks)
setRatio(uhepp.ratio) setRatio(uhepp.ratio || [])
} }
const handleEnvelop = (e) => { const handleEnvelop = (e) => {
let variationName = e.target.value let variationName = e.target.value
...@@ -849,8 +849,8 @@ const UheppHistUI = ({width, height, uhepp, uuid, size}) => { ...@@ -849,8 +849,8 @@ const UheppHistUI = ({width, height, uhepp, uuid, size}) => {
const isVariationReady = noVariationUsed(mod_uhepp) && (variations.length > 0) const isVariationReady = noVariationUsed(mod_uhepp) && (variations.length > 0)
const main_names = mod_uhepp.stacks.map(stack => stack.content.map(item => item.yield).flat()).flat() const main_names = mod_uhepp.stacks.map(stack => stack.content.map(item => item.yield).flat()).flat()
const num_names = mod_uhepp.ratio.map(item => item.numerator).flat() const num_names = mod_uhepp.ratio ? mod_uhepp.ratio.map(item => item.numerator).flat() : []
const den_names = mod_uhepp.ratio.map(item => item.denominator).flat() const den_names = mod_uhepp.ratio ? mod_uhepp.ratio.map(item => item.denominator).flat() : []
const all_names = [...main_names, ...num_names, ...den_names] const all_names = [...main_names, ...num_names, ...den_names]
const used_var_names = all_names.filter(n => n).map(n => n.split("/")).filter(t => t.length == 3).map(t => t[1]) const used_var_names = all_names.filter(n => n).map(n => n.split("/")).filter(t => t.length == 3).map(t => t[1])
......
[{"model": "uhepp_vault.collection", "pk": 1, "fields": {"title": "Frank at the zoo", "slug": "", "owner": 1, "description": null, "visibility": 30}}, {"model": "uhepp_vault.collection", "pk": 2, "fields": {"title": "Frank in the office", "slug": "", "owner": 1, "description": null, "visibility": 20}}, {"model": "uhepp_vault.collection", "pk": 3, "fields": {"title": "Frank at home", "slug": "", "owner": 1, "description": null, "visibility": 10}}, {"model": "uhepp_vault.collection", "pk": 4, "fields": {"title": "Karl at the zoo", "slug": "", "owner": 4, "description": null, "visibility": 30}}, {"model": "uhepp_vault.collection", "pk": 5, "fields": {"title": "Karl in the office", "slug": "", "owner": 4, "description": null, "visibility": 20}}, {"model": "uhepp_vault.collection", "pk": 6, "fields": {"title": "Karl at home", "slug": "", "owner": 4, "description": null, "visibility": 10}}, {"model": "uhepp_vault.collection", "pk": 7, "fields": {"title": "John at the zoo", "slug": "", "owner": 3, "description": null, "visibility": 30}}, {"model": "uhepp_vault.collection", "pk": 8, "fields": {"title": "John in the office", "slug": "", "owner": 3, "description": null, "visibility": 20}}, {"model": "uhepp_vault.collection", "pk": 9, "fields": {"title": "John at home", "slug": "", "owner": 3, "description": null, "visibility": 10}}] [{"model": "uhepp_vault.collection", "pk": 1, "fields": {"title": "Frank at the zoo", "slug": "", "owner": 1, "description": null, "visibility": 30, "activity": "2021-02-23T00:00:00+01:00", "created": "2021-02-23T00:00:00+01:00"}}, {"model": "uhepp_vault.collection", "pk": 2, "fields": {"title": "Frank in the office", "slug": "", "owner": 1, "description": null, "visibility": 20, "activity": "2021-02-23T00:00:00+01:00", "created": "2021-02-23T00:00:00+01:00"}}, {"model": "uhepp_vault.collection", "pk": 3, "fields": {"title": "Frank at home", "slug": "", "owner": 1, "description": null, "visibility": 10, "activity": "2021-02-23T00:00:00+01:00", "created": "2021-02-23T00:00:00+01:00"}}, {"model": "uhepp_vault.collection", "pk": 4, "fields": {"title": "Karl at the zoo", "slug": "", "owner": 4, "description": null, "visibility": 30, "activity": "2021-02-23T00:00:00+01:00", "created": "2021-02-23T00:00:00+01:00"}}, {"model": "uhepp_vault.collection", "pk": 5, "fields": {"title": "Karl in the office", "slug": "", "owner": 4, "description": null, "visibility": 20, "activity": "2021-02-23T00:00:00+01:00", "created": "2021-02-23T00:00:00+01:00"}}, {"model": "uhepp_vault.collection", "pk": 6, "fields": {"title": "Karl at home", "slug": "", "owner": 4, "description": null, "visibility": 10, "activity": "2021-02-23T00:00:00+01:00", "created": "2021-02-23T00:00:00+01:00"}}, {"model": "uhepp_vault.collection", "pk": 7, "fields": {"title": "John at the zoo", "slug": "", "owner": 3, "description": null, "visibility": 30, "activity": "2021-02-23T00:00:00+01:00", "created": "2021-02-23T00:00:00+01:00"}}, {"model": "uhepp_vault.collection", "pk": 8, "fields": {"title": "John in the office", "slug": "", "owner": 3, "description": null, "visibility": 20, "activity": "2021-02-23T00:00:00+01:00", "created": "2021-02-23T00:00:00+01:00"}}, {"model": "uhepp_vault.collection", "pk": 9, "fields": {"title": "John at home", "slug": "", "owner": 3, "description": null, "visibility": 10, "activity": "2021-02-23T00:00:00+01:00", "created": "2021-02-23T00:00:00+01:00"}}]
\ No newline at end of file
...@@ -112,6 +112,7 @@ INSTALLED_APPS = [ ...@@ -112,6 +112,7 @@ INSTALLED_APPS = [
'pygmentify', 'pygmentify',
'svg', 'svg',
'crispy_forms', 'crispy_forms',
'django.contrib.humanize',
] ]
CRISPY_TEMPLATE_PACK = 'bootstrap4' CRISPY_TEMPLATE_PACK = 'bootstrap4'
......
# Generated by Django 3.1.3 on 2021-02-23 16:20
from django.db import migrations, models
import django.utils.timezone
class Migration(migrations.Migration):
dependencies = [
('uhepp_vault', '0007_auto_20210201_1005'),
]
operations = [
migrations.AddField(
model_name='collection',
name='activity',
field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now),
preserve_default=False,
),
migrations.AddField(
model_name='collection',
name='created',
field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now),
preserve_default=False,
),
]
...@@ -6,6 +6,8 @@ from django.db import models ...@@ -6,6 +6,8 @@ from django.db import models
from django.db.models import F from django.db.models import F
from django.contrib.auth.models import User, Group from django.contrib.auth.models import User, Group
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from django.utils import timezone
from django.db.models.functions import Lower
from uhepp_api.models import Token from uhepp_api.models import Token
...@@ -36,6 +38,11 @@ class Collection(models.Model): ...@@ -36,6 +38,11 @@ class Collection(models.Model):
choices=VISIBILITY_LEVELS, choices=VISIBILITY_LEVELS,
default=PRIVATE_LEVEL, default=PRIVATE_LEVEL,
) )
created = models.DateTimeField(auto_now_add=True)
activity = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ['-activity', Lower('title')]
def __str__(self): def __str__(self):
return f"{self.owner}: {self.title}" return f"{self.owner}: {self.title}"
...@@ -47,7 +54,7 @@ class LazyPlotManger(models.Manager): ...@@ -47,7 +54,7 @@ class LazyPlotManger(models.Manager):
return super() \ return super() \
.get_queryset(*args, **kwargs) \ .get_queryset(*args, **kwargs) \
.defer("uhepp") \ .defer("uhepp") \
.order_by('title', 'uploaded') .order_by('-uploaded', 'title')
class Plot(models.Model): class Plot(models.Model):
"""Database record of a uhepp compliant plot""" """Database record of a uhepp compliant plot"""
...@@ -86,6 +93,10 @@ class Plot(models.Model): ...@@ -86,6 +93,10 @@ class Plot(models.Model):
if self.title is None: if self.title is None:
self.title = str(self) self.title = str(self)
if self.collection:
self.collection.activity = timezone.now()
self.collection.save()
return super().save(*args, **kwds) return super().save(*args, **kwds)
def __str__(self): def __str__(self):
......
{% extends 'uhepp_vault/base.html' %}
{% block teaser %}
<div class="jumbotron jumbo-fluid plot-background shadow">
<div class="container">
<div class="text-danger display-4">
<i class="fas fa-exclamation-triangle"></i> 404
</div>
<h2>Not found!</h2>
</div>
</div>
{% endblock %}
{% block content %}
<div class="alert alert-danger">
<h2 class="mt-2">Oops, something went wrong</h2>
<p>
We couldn't find the resource you were looking for.
Please make sure that</p>
<ul>
<li>the requested resource exists and</li>
<li>you have permission to view the resource.</li>
</ul>
The owner of the resource might have not made it visible to you.
</div>
{% endblock %}
{% extends 'uhepp_vault/base.html' %}
{% block teaser %}
<div class="jumbotron jumbo-fluid plot-background shadow">
<div class="container">
<div class="text-danger display-4">
<i class="fas fa-exclamation-triangle"></i> 500
</div>
<h2>Internal error!</h2>
</div>
</div>
{% endblock %}
{% block content %}
<div class="alert alert-danger">
<h2 class="mt-2">Oops, this is embarrassing</h2>
<p>
Something wend wrong at our end. This might be a temporary issue. Please try
again. If the issue persists, please contact an administrator.
</div>
{% endblock %}
...@@ -58,7 +58,7 @@ ...@@ -58,7 +58,7 @@
<a class="dropdown-item" href="{% url 'uhepp_vault:plot-list' %}">Plots</a> <a class="dropdown-item" href="{% url 'uhepp_vault:plot-list' %}">Plots</a>
</div> </div>
</li> </li>
{% if request.user.is_anonymous %} {% if not request.user or request.user.is_anonymous %}
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" href="/login">Sign in</a> <a class="nav-link" href="/login">Sign in</a>
</li> </li>
......
{% extends 'uhepp_vault/base.html' %} {% extends 'uhepp_vault/base.html' %}
{% load pygmentify_tags %} {% load pygmentify_tags %}
{% load humanize %}
{% block title %}{{ collection.title }} - uhepp hub{% endblock %} {% block title %}{{ collection.title }} - uhepp hub{% endblock %}
...@@ -100,6 +101,8 @@ uhepp push {{ collection.pk }} local_file.json ...@@ -100,6 +101,8 @@ uhepp push {{ collection.pk }} local_file.json
<li> <li>
<a href="{% url 'uhepp_vault:plot-detail' plot.uuid %}"> <a href="{% url 'uhepp_vault:plot-detail' plot.uuid %}">
{{ plot }} {{ plot }}
<small title="{{ plot.uploaded|date:"Y-m-d H:m" }}" class="text-muted">
({{ plot.uploaded|naturaltime }})</small>
</a> </a>
</li> </li>
{% endfor %}</ul> {% endfor %}</ul>
......
{% extends 'uhepp_vault/base.html' %} {% extends 'uhepp_vault/base.html' %}
{% load humanize %}
{% block title %}Collections - uhepp hub{% endblock %} {% block title %}Collections - uhepp hub{% endblock %}
...@@ -33,9 +34,14 @@ ...@@ -33,9 +34,14 @@
<span class="badge badge-primary badge-pill">{{ collection.plots.count }}</span> <span class="badge badge-primary badge-pill">{{ collection.plots.count }}</span>
{% endif %} {% endif %}
</div> </div>
<small class="text-body"> <div class="d-flex justify-content-between align-items-start">
{{ collection.description }} <small class="text-body">
</small> {{ collection.description }}
</small>
<small title="{{ collection.activity|date:"Y-m-d H:m" }}" class="text-muted">
{{ collection.activity|naturaltime }}
</small>
</div>
</a> </a>
{% endfor %} {% endfor %}
</div> </div>
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
<div class="jumbotron jumbo-fluid plot-background shadow"> <div class="jumbotron jumbo-fluid plot-background shadow">
<div class="container"> <div class="container">
<h1 class="display-4">uhepp hub</h1> <h1 class="display-4">uhepp hub</h1>
<h2>Home of {{ plot_count }} plots</h2> <h2>Home of over {{ plot_count }} plots</h2>
</div> </div>
</div> </div>
{% endblock %} {% endblock %}
......
{% extends 'uhepp_vault/base.html' %} {% extends 'uhepp_vault/base.html' %}
{% load pygmentify_tags %} {% load pygmentify_tags %}
{% load humanize %}
{% block title %}{{ plot.title }} - uhepp hub{% endblock %} {% block title %}{{ plot.title }} - uhepp hub{% endblock %}
...@@ -30,7 +31,11 @@ ...@@ -30,7 +31,11 @@
{% endif %}</h1> {% endif %}</h1>
<div class="d-none d-lg-inline text-muted"> <div class="d-none d-lg-inline text-muted">
<i class="fas fa-eye"></i> <i class="fas fa-eye"></i>
{{ plot.view_count }} view{{ plot.view_count|pluralize }} {{ plot.view_count }} view{{ plot.view_count|pluralize }},
<span title="{{ plot.uploaded|date:"Y-m-d H:m" }}">
<i class="fas fa-clock"></i>
{{ plot.uploaded|naturaltime }}
</span>
</div> </div>
<div class="d-flex"> <div class="d-flex">
......
{% extends 'uhepp_vault/base.html' %} {% extends 'uhepp_vault/base.html' %}
{% load humanize %}
{% block title %}Plots - uhepp hub{% endblock %} {% block title %}Plots - uhepp hub{% endblock %}
...@@ -17,6 +18,8 @@ ...@@ -17,6 +18,8 @@
<a href="{% url 'uhepp_vault:plot-detail' plot.uuid %}"> <a href="{% url 'uhepp_vault:plot-detail' plot.uuid %}">
{{ plot.collection.owner.username}} / {{ plot.collection.owner.username}} /
{{ plot.collection.title }} / {{ plot }} {{ plot.collection.title }} / {{ plot }}
<small title="{{ plot.uploaded|date:"Y-m-d H:m" }}" class="text-muted">
({{ plot.uploaded|naturaltime }})</small>
</a> </a>
</li> </li>
{% endfor %} {% endfor %}
......
{% extends 'uhepp_vault/base.html' %} {% extends 'uhepp_vault/base.html' %}
{% load humanize %}
{% block title %}{{ user.first_name }} {{ user.last_name }} - uhepp hub{% endblock %} {% block title %}{{ user.first_name }} {{ user.last_name }} - uhepp hub{% endblock %}
...@@ -55,9 +56,14 @@ ...@@ -55,9 +56,14 @@
<span class="badge badge-primary badge-pill">{{ collection.plots.count }}</span> <span class="badge badge-primary badge-pill">{{ collection.plots.count }}</span>
{% endif %} {% endif %}
</div> </div>
<small class="text-body"> <div class="d-flex justify-content-between align-items-start">
{{ collection.description }} <small class="text-body">
</small> {{ collection.description }}
</small>
<small title="{{ collection.activity|date:"Y-m-d H:m" }}" class="text-muted">
{{ collection.activity|naturaltime }}
</small>
</div>
</a> </a>
{% endfor %} {% endfor %}
</div> </div>
......
import unittest
from uhepp_vault.views import quantize
class QuantizeTest(unittest.TestCase):
def testQuantize(self):
self.assertEqual(quantize(123, 0), 0)
self.assertEqual(quantize(123, 1), 100)
self.assertEqual(quantize(123, 2), 120)
self.assertEqual(quantize(123, 3), 123)
self.assertEqual(quantize(123, 4), 123)
...@@ -2,6 +2,7 @@ from django.urls import path, include ...@@ -2,6 +2,7 @@ from django.urls import path, include
from django.contrib.auth import views as auth_views from django.contrib.auth import views as auth_views
from django.views.generic.base import RedirectView from django.views.generic.base import RedirectView
from django.conf import settings from django.conf import settings
from django.views.defaults import page_not_found, server_error
from . import views from . import views
...@@ -29,4 +30,6 @@ urlpatterns = [ ...@@ -29,4 +30,6 @@ urlpatterns = [
path('p/<str:uuid>', views.PlotDetail.as_view(), name='plot-detail'), path('p/<str:uuid>', views.PlotDetail.as_view(), name='plot-detail'),
path('p/<str:uuid>/delete', views.PlotDeleteView.as_view(), name='plot-delete'), path('p/<str:uuid>/delete', views.PlotDeleteView.as_view(), name='plot-delete'),
path('p/<str:uuid>/download', views.plot_download, name='plot-download'), path('p/<str:uuid>/download', views.plot_download, name='plot-download'),
path(r'404/', page_not_found, {'exception': Exception()}),
path(r'500/', server_error),
] ]
import math
from django.shortcuts import render from django.shortcuts import render
from django.views import generic from django.views import generic
from django.db.models import Q from django.db.models import Q
...@@ -20,8 +21,15 @@ from .models import PUBLIC_LEVEL, INTERNAL_LEVEL, PUBLIC_LEVEL, \ ...@@ -20,8 +21,15 @@ from .models import PUBLIC_LEVEL, INTERNAL_LEVEL, PUBLIC_LEVEL, \
from .forms import TokenForm from .forms import TokenForm
def quantize(value, sig_digits):
magnitude = math.floor(math.log10(value))
scale = magnitude - sig_digits + 1
return math.floor(value / 10**scale) * 10**scale
def home(request): def home(request):
plot_count = Plot.objects.count() plot_count = Plot.objects.count()
plot_count = quantize(plot_count, 2)
context = dict(plot_count=plot_count) context = dict(plot_count=plot_count)
return render(request, "uhepp_vault/home.html", context=context) return render(request, "uhepp_vault/home.html", context=context)
...@@ -165,7 +173,6 @@ class CollectionUpdateView(LoginRequiredMixin, generic.UpdateView): ...@@ -165,7 +173,6 @@ class CollectionUpdateView(LoginRequiredMixin, generic.UpdateView):
fields = ['title', 'description', 'visibility'] fields = ['title', 'description', 'visibility']
edit = True edit = True
def get_success_url(self): def get_success_url(self):
return reverse_lazy('uhepp_vault:collection-detail', return reverse_lazy('uhepp_vault:collection-detail',
args=[self.object.pk]) args=[self.object.pk])
......