Commits

b7w committed b900aa9

First part of model refactor. Move ProxyUser to Gallery. Fix core module tests.

  • Participants
  • Parent commits 4dde944

Comments (0)

Files changed (27)

File bviewer/api/resources.py

 # -*- coding: utf-8 -*-
+from django.contrib.auth.models import User
 from django.db.models import Q
 
 from rest_framework.filters import OrderingFilter, DjangoFilterBackend
 from bviewer.api.filters import UserSelfFilter, ItemUserSelfFilter
 
 from bviewer.api.serializers import UserSerializer, AlbumSerializer, ImageSerializer, VideoSerializer
-from bviewer.core.models import Album, ProxyUser, Image, Video
+from bviewer.core.models import Gallery, Album, Image, Video
 
 
 ITEMS_PER_PAGE = 16
 
 
 class UserResource(ModelViewSet):
-    queryset = ProxyUser.objects.all().select_related()
+    queryset = User.objects.all().select_related()
     serializer_class = UserSerializer
     http_method_names = ('get',)
     permission_classes = (IsAuthenticated,)
     paginate_by = ITEMS_PER_PAGE
 
 
+class GalleryResource(ModelViewSet):
+    queryset = Gallery.objects.all().select_related()
+    serializer_class = UserSerializer
+    http_method_names = ('get',)
+    permission_classes = (IsAuthenticated,)
+
+    filter_backends = (OrderingFilter, DjangoFilterBackend,)
+    ordering = ('user',)
+
+    paginate_by = ITEMS_PER_PAGE
+
+
 class AlbumResource(ModelViewSet):
     queryset = Album.objects.all().select_related()
 
     permission_classes = (IsAuthenticatedOrReadOnly,)
 
     filter_backends = (UserSelfFilter, OrderingFilter, DjangoFilterBackend)
-    filter_fields = ('id', 'user', 'title')
+    filter_fields = ('id', 'gallery', 'title')
     ordering = ('title', 'time',)
 
     paginate_by = ITEMS_PER_PAGE

File bviewer/api/serializers.py

 # -*- coding: utf-8 -*-
+from django.contrib.auth.models import User
 from rest_framework.relations import HyperlinkedRelatedField, HyperlinkedIdentityField
 from rest_framework.serializers import ModelSerializer
 
-from bviewer.core.models import ProxyUser, Album, Image, Video
+from bviewer.core.models import Album, Image, Video
 
 
 class UserSerializer(ModelSerializer):
     detail = HyperlinkedIdentityField(view_name='proxyuser-detail')
 
     class Meta:
-        model = ProxyUser
+        model = User
         fields = ('detail', 'id', 'username', 'date_joined', 'last_login', 'about_title', 'about_text',)
 
 

File bviewer/archive/controllers.py

 class ZipArchiveController(object):
     STATUS_KEY_TIMOUT = 4 * 60
 
-    def __init__(self, image_paths, holder, name=None):
+    def __init__(self, image_paths, gallery, name=None):
         """
         :type image_paths: list of str
-        :type holder: bviewer.core.models.ProxyUser
+        :type gallery: bviewer.core.models.Gallery
         :type name: str
         """
-        self.holder = holder
-        self.storage = ImageStorage(holder, archive_cache=True)
+        self.gallery = gallery
+        self.storage = ImageStorage(gallery, archive_cache=True)
         self.image_paths = [self.storage.get_path(i) for i in image_paths]
         self.name = name or self.uid
 
     @property
     @cache_method
     def uid(self):
-        pack = [self.holder.home, ]
+        pack = [self.gallery.home, ]
         for path in self.image_paths:
             if path.exists:
                 pack.append(path.cache_name)

File bviewer/archive/views.py

 from django.utils.encoding import smart_text
 
 from bviewer.archive.controllers import ZipArchiveController
-from bviewer.core.controllers import get_album_user, AlbumController
+from bviewer.core.controllers import get_gallery, AlbumController
 from bviewer.core.files.response import download_response
 from bviewer.core.views import message_view
 
     Start to archive images, or if done redirect to download
     js - waite while done, after redirect to download
     """
-    holder = get_album_user(request)
-    if not holder:
+    gallery = get_gallery(request)
+    if not gallery:
         return message_view(request, message=NO_USER_DEFINED)
 
-    controller = AlbumController(holder, request.user, uid=gid)
+    controller = AlbumController(gallery, request.user, uid=gid)
     if not controller.exists():
         return message_view(request, message=NO_GALLERY_FOUND)
 
         return message_view(request, message=NOT_ALLOW_ARCHIVING)
 
     image_paths = [i.path for i in controller.get_images()]
-    z = ZipArchiveController(image_paths, holder)
+    z = ZipArchiveController(image_paths, gallery)
 
     # links for redirect to download, and check status
     redirect = reverse('archive.download', kwargs=dict(gid=gid, uid=z.uid))
 
     z.add_job()
     return render(request, 'archive/download.html', {
-        'holder': holder,
+        'gallery': gallery,
         'path': request.path,
         'link': link,
         'redirect': redirect,
     """
     Check if archive exists and ready for download
     """
-    holder = get_album_user(request)
-    if not holder:
+    gallery = get_gallery(request)
+    if not gallery:
         raise Http404(NO_USER_DEFINED)
 
-    controller = AlbumController(holder, request.user, gid)
+    controller = AlbumController(gallery, request.user, gid)
     if not controller.exists():
         return HttpResponse(json.dumps(dict(error=NO_GALLERY_FOUND)))
 
         return HttpResponse(json.dumps(dict(error=NOT_ALLOW_ARCHIVING)))
 
     image_paths = [i.path for i in controller.get_images()]
-    z = ZipArchiveController(image_paths, holder, name=uid)
+    z = ZipArchiveController(image_paths, gallery, name=uid)
     data = dict(status=z.status, album=gid, uid=uid, progress=z.progress)
 
     return HttpResponse(json.dumps(data))
     """
     Download archive
     """
-    holder = get_album_user(request)
-    if not holder:
+    gallery = get_gallery(request)
+    if not gallery:
         raise Http404(NO_USER_DEFINED)
 
-    controller = AlbumController(holder, request.user, uid=gid)
+    controller = AlbumController(gallery, request.user, uid=gid)
     if not controller.exists():
         raise Http404(NO_GALLERY_FOUND)
 
         return message_view(request, message=NOT_ALLOW_ARCHIVING)
 
     image_paths = [i.path for i in controller.get_images()]
-    z = ZipArchiveController(image_paths, holder, name=uid)
+    z = ZipArchiveController(image_paths, gallery, name=uid)
 
     if z == 'NONE':
         raise Http404('No file found')

File bviewer/core/admin.py

 from django.contrib.auth.forms import UserChangeForm
 
 from bviewer.core.utils import RaisingRange
-from bviewer.core.models import ProxyUser, Album, Image, Video
+from bviewer.core.models import Gallery, Album, Image, Video
 
 
 class AlbumAdmin(ModelAdmin):
 site.register(Video, VideoAdmin)
 
 
-class ProxyUserForm(UserChangeForm):
+class GalleryForm(UserChangeForm):
     """
-    Set for UserAdmin ProxyUser model except User.
+    Set for UserAdmin Gallery model except User.
     Add choice field for cache size filed.
     """
 
     def __init__(self, *args, **kwargs):
-        super(ProxyUserForm, self).__init__(*args, **kwargs)
+        super(GalleryForm, self).__init__(*args, **kwargs)
         self._set_choice('cache_size',
-            cache_max=ProxyUser.CACHE_SIZE_MAX,
-            cache_min=ProxyUser.CACHE_SIZE_MIN,
+            cache_max=Gallery.CACHE_SIZE_MAX,
+            cache_min=Gallery.CACHE_SIZE_MIN,
             base=16
         )
         self._set_choice('cache_archive_size',
-            cache_max=ProxyUser.CACHE_ARCHIVE_SIZE_MAX,
-            cache_min=ProxyUser.CACHE_ARCHIVE_SIZE_MIN,
+            cache_max=Gallery.CACHE_ARCHIVE_SIZE_MAX,
+            cache_min=Gallery.CACHE_ARCHIVE_SIZE_MIN,
             base=64
         )
 
         self.fields[field_name] = forms.ChoiceField(choices=choice)
 
     class Meta(object):
-        model = ProxyUser
+        model = Gallery
 
 
-class ProxyUserAdmin(UserAdmin, ModelAdmin):
+class GalleryAdmin(UserAdmin, ModelAdmin):
     list_select_related = True
 
     list_display = ('username', 'email', 'is_staff', 'home', 'top_album', )
     fieldsets = extra_fieldsets + UserAdmin.fieldsets[2:]
     readonly_fields = ('is_active', 'is_staff', 'last_login', 'date_joined', )
 
-    form = ProxyUserForm
+    form = GalleryForm
 
 
-site.register(ProxyUser, ProxyUserAdmin)
+site.register(Gallery, GalleryAdmin)

File bviewer/core/controllers.py

 from bviewer.core.files.response import download_response
 from bviewer.core.files.storage import ImageStorage
 from bviewer.core.images import CacheImage
-from bviewer.core.models import Album, Video, Image, ProxyUser
+from bviewer.core.models import Gallery, Album, Video, Image
 from bviewer.core.utils import cache_method, ImageOptions, as_job
 
 
 domain_match = re.compile(r'([w]{3})?\.?(?P<domain>[\w\.]+):?(\d{0,4})')
 
 
-def get_album_user(request):
+def get_gallery(request):
     """
-    Get domain from request and try to find user with user.url == domain.
-    If not try return authenticated user, else user from settings.VIEWER_USER_ID.
+    Get domain from request and try to find gallery with gallery.url == domain.
+    If not try return authenticated gallery, else gallery from settings.VIEWER_GALLERY_ID.
 
     :type request: django.http.HttpRequest
-    :rtype: bviewer.core.models.ProxyUser
+    :rtype: bviewer.core.models.Gallery
     """
-    key = 'core.utils.get_album_user({0})'.format(request.get_host())
+    key = 'core.controllers.get_gallery({0})'.format(request.get_host())
     data = cache.get(key)
     if data:
         return data
-    if settings.VIEWER_USER_ID:
-        user = ProxyUser.objects.get(id=settings.VIEWER_USER_ID)
-        cache.set(key, user)
-        return user
+    if settings.VIEWER_GALLERY_ID:
+        gallery = Gallery.objects.get(id=settings.VIEWER_GALLERY_ID)
+        cache.set(key, gallery)
+        return gallery
 
     match = domain_match.match(request.get_host())
     if match:
         url = match.group('domain')
-        user = ProxyUser.objects.safe_get(url=url)
-        if user:
-            cache.set(key, user)
-            return user
+        gallery = Gallery.objects.safe_get(url=url)
+        if gallery:
+            cache.set(key, gallery)
+            return gallery
 
     if request.user.is_authenticated():
-        return ProxyUser.objects.get(id=request.user.id)
+        return Gallery.objects.get(id=request.user.id)
 
     return None
 
 
 class BaseController(object):
-    def __init__(self, holder, user, uid=None, obj=None):
+    def __init__(self, gallery, user, uid=None, obj=None):
         """
-        :type holder: bviewer.core.models.ProxyUser
+        :type gallery: bviewer.core.models.Gallery
         :type user: django.contrib.auth.models.User
         :type uid: str
         """
-        self.holder = holder
+        self.gallery = gallery
         self.user = user
         if uid:
             self.uid = uid
 
     def is_owner(self):
         """
-        Return holder == user
+        Return gallery == user
 
         :rtype: bool
         """
-        return self.holder == self.user
+        return self.gallery.user == self.user
 
     def exists(self):
         return bool(self.get_object())
         if self.obj:
             return self.obj
         if self.is_owner():
-            return Album.objects.safe_get(pk=self.uid, user_id=self.holder.id)
-        return Album.objects.safe_get(Q(pk=self.uid), Q(user_id=self.holder.id), self.OPEN)
+            return Album.objects.safe_get(pk=self.uid, gallery_id=self.gallery.id)
+        return Album.objects.safe_get(Q(pk=self.uid), Q(gallery_id=self.gallery.id), self.OPEN)
 
     def _get_albums(self, parent_id):
         """
         sizes = [i for i in settings.VIEWER_IMAGE_SIZE.keys() if i != 'full']
         for size in sizes:
             for image in images:
-                storage = ImageStorage(self.holder)
+                storage = ImageStorage(self.gallery)
                 self._pre_cache_image(storage, image, size)
 
     def _pre_cache_image(self, storage, image, size):
         Get self.MODEL instance or None
         """
         if self.is_owner():
-            return self.MODEL.objects.safe_get(pk=self.uid, album__user__id=self.holder.id)
-        return self.MODEL.objects.safe_get(Q(pk=self.uid), Q(album__user__id=self.holder.id), self.OPEN)
+            return self.MODEL.objects.safe_get(pk=self.uid, album__gallery__id=self.gallery.id)
+        return self.MODEL.objects.safe_get(Q(pk=self.uid), Q(album__gallery__id=self.gallery.id), self.OPEN)
 
     def get_response(self, size):
         """
     def get_response(self, size):
         #: :type: bviewer.core.models.Image
         image = self.get_object()
-        storage = ImageStorage(self.holder)
+        storage = ImageStorage(self.gallery)
         options = ImageOptions.from_settings(size)
         image_path = storage.get_path(image.path, options)
         if not image_path.exists:
     def get_response(self, size):
         #: :type: bviewer.core.models.Video
         video = self.get_object()
-        storage = ImageStorage(self.holder)
+        storage = ImageStorage(self.gallery)
         options = ImageOptions.from_settings(size, name=str(video.id))
         image_url = storage.get_url(video.thumbnail_url, options)
 

File bviewer/core/files/path.py

 
     @property
     def url(self):
-        return '/'.join([self.storage.type, self.storage.holder.url, self.url_name])
+        return '/'.join([self.storage.type, self.storage.gallery.url, self.url_name])
 
     @property
     def url_name(self):

File bviewer/core/files/storage.py

     TYPES_ALLOWED = ('.jpeg', '.jpg', )
     PATH_CHECKERS = ('../', './', '/.', )
 
-    def __init__(self, holder, root_path=None, cache_path=None, archive_cache=False):
+    def __init__(self, gallery, root_path=None, cache_path=None, archive_cache=False):
         """
         :param root_path: place where image files stored, default settings.VIEWER_STORAGE_PATH
         :param cache_path: place where cache stored, default settings.VIEWER_CACHE_PATH
         :param archive_cache: set 'archives' sub cache folder instead of 'images'
-        :type holder: bviewer.core.models.ProxyUser
+        :type gallery: bviewer.core.models.Gallery
         """
-        self.holder = holder
+        self.gallery = gallery
         self.root = root_path or settings.VIEWER_STORAGE_PATH
         self.cache_path = cache_path or settings.VIEWER_CACHE_PATH
         self.type = 'archives' if archive_cache else 'images'
 
-        self._abs_root_path = os.path.join(self.root, holder.home)
+        self._abs_root_path = os.path.join(self.root, gallery.home)
         if archive_cache:
-            self._abs_cache_path = os.path.join(self.cache_path, self.type, holder.url)
-            self._max_cache_size = holder.cache_archive_size * 2 ** 20
+            self._abs_cache_path = os.path.join(self.cache_path, self.type, gallery.url)
+            self._max_cache_size = gallery.cache_archive_size * 2 ** 20
         else:
-            self._abs_cache_path = os.path.join(self.cache_path, self.type, holder.url)
-            self._max_cache_size = holder.cache_size * 2 ** 20
+            self._abs_cache_path = os.path.join(self.cache_path, self.type, gallery.url)
+            self._max_cache_size = gallery.cache_size * 2 ** 20
         self.create_cache()
 
     def _is_valid_path(self, path):
     @io_call
     def clear_cache(self, full=False):
         """
-        Clear old cache while size of directory bigger than holder.cache_size.
+        Clear old cache while size of directory bigger than gallery.cache_size.
         If `full` is True - delete user cache folder.
         """
         abs_cache = self._abs_cache_path
         return uuid.uuid1().hex
 
     def __repr__(self):
-        return 'ImageStorage({h})'.format(h=self.holder)
+        return 'ImageStorage({h})'.format(h=self.gallery)

File bviewer/core/management/commands/clearcache.py

 from django.core.management.base import BaseCommand
 
 from bviewer.core.files.storage import ImageStorage
-from bviewer.core.models import ProxyUser
+from bviewer.core.models import Gallery
 
 
 logger = logging.getLogger(__name__)
 
     def handle(self, *args, **options):
         full = 'full' in args
-        for user in ProxyUser.objects.all():
+        for user in Gallery.objects.all():
             ImageStorage(user).clear_cache(full=full)
             ImageStorage(user, archive_cache=True).clear_cache(full=full)
-        self.stdout.write('Clear cache for {c} users'.format(c=ProxyUser.objects.count()))
+        self.stdout.write('Clear cache for {c} users'.format(c=Gallery.objects.count()))

File bviewer/core/models.py

     from urllib.request import urlopen
     from urllib.error import URLError
 
-from django.contrib.auth.models import User, AbstractUser, Permission
+from django.contrib.auth.models import User, Permission
 from django.contrib.sites.models import Site
 from django.core.exceptions import ValidationError
 from django.core.validators import MaxValueValidator, MinValueValidator
             return None
 
 
-class ProxyUser(User):
+class Gallery(models.Model):
     CACHE_SIZE_MIN = 16
     CACHE_SIZE_MAX = 256
     CACHE_ARCHIVE_SIZE_MIN = 128
     CACHE_ARCHIVE_SIZE_MAX = 2048
 
+    user = models.ForeignKey(User)
+
     url = models.CharField(max_length=16, unique=True)
     home = models.CharField(max_length=256, blank=True, default='')
 
 
     def save(self, *args, **kwargs):
         if not self.url:
-            url = self.username.lower()
+            url = self.user.username.lower()
             domain = Site.objects.get_current().domain
             self.url = '{0}.{1}'.format(url, domain)
-        super(ProxyUser, self).save(*args, **kwargs)
-
-    def __eq__(self, other):
-        """
-        if isinstance of ProxyUser, AbstractUser:
-            return self.id == other.id
-        return False
-        """
-        if other and isinstance(other, (ProxyUser, AbstractUser)):
-            return self.id == other.id
-        return False
+        super(Gallery, self).save(*args, **kwargs)
 
     class Meta(object):
-        db_table = 'core_profile'
-        ordering = ['username']
-        verbose_name = 'Profile'
+        ordering = ['user']
         permissions = (
-            ('user_holder', 'User is albums holder'),
+            ('user_gallery', 'User is albums gallery'),
         )
 
 
 def add_top_album(sender, instance, created, **kwargs):
     if created:
-        gal = Album(user=instance, title='Welcome', description='Edit main album to change it')
+        gal = Album(gallery=instance, title='Welcome', description='Edit main album to change it')
         gal.save()
         instance.top_album = gal
         perms = Permission.objects.filter(
-            Q(codename='change_proxyuser') |
-            Q(codename='user_holder') |
+            Q(codename='change_gallery') |
+            Q(codename='user_gallery') |
             Q(codename='add_album') |
             Q(codename='change_album') |
             Q(codename='delete_album') |
             Q(codename='change_slideshow') |
             Q(codename='delete_slideshow')
         )
-        instance.user_permissions = list(perms)
+        instance.user.user_permissions = list(perms)
         instance.save()
 
 
-post_save.connect(add_top_album, sender=ProxyUser)
+post_save.connect(add_top_album, sender=Gallery)
 
 
 def date_now():
     id = models.CharField(max_length=32, default=uuid_pk(length=8), primary_key=True)
     parent = models.ForeignKey('self', null=True, blank=True, related_name='children', on_delete=models.SET_NULL)
     title = models.CharField(max_length=256)
-    user = models.ForeignKey(ProxyUser)
+    gallery = models.ForeignKey(Gallery)
     visibility = models.SmallIntegerField(max_length=1, choices=VISIBILITY_CHOICE, default=VISIBLE,
                                           help_text='HIDDEN - not shown on page for anonymous, '
-                                                    'PRIVATE - available only to the holder')
+                                                    'PRIVATE - available only to the gallery')
     album_sorting = models.SmallIntegerField(max_length=1, choices=SORT_CHOICE, default=ASK,
-                                               help_text='How to sort albums inside')
+                                             help_text='How to sort albums inside')
     allow_archiving = models.BooleanField(default=True)
     description = models.TextField(max_length=512, null=True, blank=True)
     thumbnail = models.ForeignKey('Image', null=True, blank=True, related_name='thumbnail', on_delete=models.SET_NULL)
         verbose_name = 'Album'
         verbose_name_plural = 'Albums'
         ordering = ['-time']
-        unique_together = (('title', 'user'),)
+        unique_together = (('title', 'gallery'),)
 
 
 class Image(models.Model):
     :type instance: Image
     """
     if created:
-        storage = ImageStorage(instance.album.user)
+        storage = ImageStorage(instance.album.gallery)
         set_time_from_exif(storage, instance, save=True)
 
 

File bviewer/core/templates/core/base.html

                     <li class="divider-vertical"></li>
                 {% endif %}
                 {% if request.user.is_authenticated %}
-                    {% if perms.core.user_holder %}
+                    {% if perms.core.user_gallery %}
                         <li class="view-full"><a href="{% url 'profile:index' %}">Profile</a></li>
                     {% endif %}
                     <li><a href="{% url 'core.logout' %}">Log out</a></li>
 <footer>
     <div class="container">
         <p>
-            Copyright &copy; {% now "Y" %} <a href="mailto:{{ holder.email }}">{{ holder.username }}</a>
+            Copyright &copy; {% now "Y" %} <a href="mailto:{{galleryr.email }}">{galleryer.username }}</a>
         </p>
 
         <p>

File bviewer/core/templates/core/gallery.html

 
 {% block navigation %}
     <li class="view-full">
-        {% if holder.top_album_id == main.id %}
+        {% if gallery.top_album_id == main.id %}
             <a href="{% url 'slideshow.index' %}">Slideshow</a>
         {% else %}
             <a href="{% url 'slideshow.album' main.id %}">Slideshow</a>
     </ul>
 
     <div class="album-years">
-        {% if holder.top_album_id == main.id %}
+        {% if gallery.top_album_id == main.id %}
             {% for item in years %}
                 <a href="{% url 'core.home' %}?year={{ item|date:"Y" }}"
                    class="{% if year_filter == item.year %}selected{% endif %}">{{ item|date:"Y" }}</a>

File bviewer/core/templates/core/login.html

             </ul>
             <fieldset>
                 <div>
-                    <input id="username" type="text" name="username" placeholder="Username" value="{{ form.username.value|default:"" }}">
+                    <input id="username" type="text" name="username" placegallery="Username" value="{{ form.username.value|default:"" }}">
                 </div>
                 <div>
-                    <input id="password" type="password" name="password" placeholder="Password">
+                    <input id="password" type="password" name="password" placegallery="Password">
                 </div>
                 <div>
                     <input type="hidden" name="next" value="{{ next|default:'/' }}"/>

File bviewer/core/tests/base.py

 
 class BaseViewTestCase(TestCase):
     """
-    Set up TestData, b7w user as holder.
+    Set up TestData, b7w user as gallery.
     """
 
     def setUp(self):
 
         self.data = TestData()
         self.data.load_all()
-        settings.VIEWER_USER_ID = self.data.user_b7w.id
+        settings.VIEWER_GALLERY_ID = self.data.user_b7w.id
 
     def reverse(self, name, *args):
         """
 
 class BaseImageStorageTestCase(TestCase):
     def setUp(self):
-        self.holder = Mock(home='holder_home', url='holder_url', cache_size=0)
-        self.storage = ImageStorage(self.holder)
+        self.gallery = Mock(home='gallery_home', url='gallery_url', cache_size=0)
+        self.storage = ImageStorage(self.gallery)
         self.remove_storage_folders()
         self.create_storage_folders()
 

File bviewer/core/tests/data.py

 from django.contrib.auth.models import User, Permission
 
 from bviewer.core.images import RandomImage
-from bviewer.core.models import ProxyUser, Album, Image, Video
+from bviewer.core.models import Gallery, Album, Image, Video
 
 
 class TestData(object):
 
     def load_all(self):
         self.load_users()
+        self.load_galleries()
         self.load_albums()
         self.load_images()
         self.load_videos()
 
     def load_users(self):
-        self.user_b7w = ProxyUser(username='B7W')
+        self.user_b7w = User(username='B7W')
         self.user_b7w.set_password(self.PASSWORD)
         self.user_b7w.save()
-        self.update_to_holder('B7W')
+        self.update_to_gallery('B7W')
 
-        self.user_keks = ProxyUser(username='Keks')
+        self.user_keks = User(username='Keks')
         self.user_keks.set_password(self.PASSWORD)
         self.user_keks.save()
-        self.update_to_holder('Keks')
+        self.update_to_gallery('Keks')
         return self
 
-    def update_to_holder(self, name):
+    def update_to_gallery(self, name):
         user = User.objects.get(username=name)
-        perm = Permission.objects.get(codename='user_holder')
+        perm = Permission.objects.get(codename='user_gallery')
         user.user_permissions.add(perm)
         user.save()
 
+    def load_galleries(self):
+        self.gallery_b7w = Gallery(user=self.user_b7w)
+        self.gallery_b7w.save()
+        self.gallery_keks = Gallery(user=self.user_keks)
+        self.gallery_keks.save()
+        return self
+
     def load_albums(self):
-        self.album_b7w = self.user_b7w.top_album
-        self.album_keks = self.user_keks.top_album
+        self.album_b7w = self.gallery_b7w.top_album
+        self.album_keks = self.gallery_keks.top_album
 
-        self.album1 = Album(parent=self.album_b7w, user=self.user_b7w, title='First')
+        self.album1 = Album(parent=self.album_b7w, gallery=self.gallery_b7w, title='First')
         self.album1.description = 'First description'
         self.album1.save()
 
-        self.album2 = Album(parent=self.album_b7w, user=self.user_b7w, title='Second')
+        self.album2 = Album(parent=self.album_b7w, gallery=self.gallery_b7w, title='Second')
         self.album2.visibility = Album.PRIVATE
         self.album2.description = 'Second description'
         self.album2.save()
 
-        self.album3 = Album(parent=self.album_b7w, user=self.user_b7w, title='Third')
+        self.album3 = Album(parent=self.album_b7w, gallery=self.gallery_b7w, title='Third')
         self.album3.description = 'Third description'
         self.album3.save()
 
-        self.album4 = Album(parent=self.album3, user=self.user_b7w, title='Under third')
+        self.album4 = Album(parent=self.album3, gallery=self.gallery_b7w, title='Under third')
         self.album4.description = 'Under description'
         self.album4.save()
 
-        self.album5 = Album(user=self.user_keks, title='Hidden')
+        self.album5 = Album(gallery=self.gallery_keks, title='Hidden')
         self.album5.description = 'Hidden description'
         self.album5.save()
         return self
     def load_images(self):
         self.image1 = Image.objects.create(album=self.album1, path='image1.jpg')
         self.image2 = Image.objects.create(album=self.album1, path='image2.jpg')
-        self.generate_image(self.album1.user.home, self.image1.path)
-        self.generate_image(self.album1.user.home, self.image2.path)
+        self.generate_image(self.album1.gallery.home, self.image1.path)
+        self.generate_image(self.album1.gallery.home, self.image2.path)
 
         self.image3 = Image.objects.create(album=self.album2, path='image3.jpg')
         self.image4 = Image.objects.create(album=self.album2, path='image4.jpg')
-        self.generate_image(self.album2.user.home, self.image3.path)
-        self.generate_image(self.album2.user.home, self.image4.path)
+        self.generate_image(self.album2.gallery.home, self.image3.path)
+        self.generate_image(self.album2.gallery.home, self.image4.path)
 
         self.image5 = Image.objects.create(album=self.album5, path='image5.jpg')
-        self.generate_image(self.album5.user.home, self.image5.path)
+        self.generate_image(self.album5.gallery.home, self.image5.path)
         return self
 
     def load_videos(self):

File bviewer/core/tests/test_controllers.py

         """
         data = TestData()
         data.load_users()
+        data.load_galleries()
 
-        user = data.user_b7w
-        top_album = user.top_album
-        g1 = Album.objects.create(parent=top_album, user=user, title='1')
-        g2 = Album.objects.create(parent=top_album, user=user, title='2')
+        gallery = data.gallery_b7w
+        top_album = gallery.top_album
+        g1 = Album.objects.create(parent=top_album, gallery=gallery, title='1')
+        g2 = Album.objects.create(parent=top_album, gallery=gallery, title='2')
 
-        g11 = Album.objects.create(parent=g1, user=user, title='1.1')
-        g12 = Album.objects.create(parent=g1, user=user, title='1.2')
-        g13 = Album.objects.create(parent=g1, user=user, title='1.3')
+        g11 = Album.objects.create(parent=g1, gallery=gallery, title='1.1')
+        g12 = Album.objects.create(parent=g1, gallery=gallery, title='1.2')
+        g13 = Album.objects.create(parent=g1, gallery=gallery, title='1.3')
 
-        g21 = Album.objects.create(parent=g2, user=user, title='2.1')
-        g22 = Album.objects.create(parent=g2, user=user, title='2.2')
+        g21 = Album.objects.create(parent=g2, gallery=gallery, title='2.1')
+        g22 = Album.objects.create(parent=g2, gallery=gallery, title='2.2')
 
-        g111 = Album.objects.create(parent=g11, user=user, title='1.1.1')
-        g112 = Album.objects.create(parent=g11, user=user, title='1.1.2')
+        g111 = Album.objects.create(parent=g11, gallery=gallery, title='1.1.1')
+        g112 = Album.objects.create(parent=g11, gallery=gallery, title='1.1.2')
 
-        g121 = Album.objects.create(parent=g12, user=user, title='1.2.1')
+        g121 = Album.objects.create(parent=g12, gallery=gallery, title='1.2.1')
 
-        controller = AlbumController(user, user, uid=top_album.id)
+        controller = AlbumController(gallery, gallery, uid=top_album.id)
         albums = controller.get_all_sub_albums()
         self.assertEqual(len(albums), 10)
 
-        controller = AlbumController(user, user, uid=top_album.id)
+        controller = AlbumController(gallery, gallery, uid=top_album.id)
         albums = controller.get_all_sub_albums(parents=False)
         self.assertEqual(len(albums), 6)
 
         """
         data = TestData()
         data.load_users()
+        data.load_galleries()
 
-        user = data.user_b7w
-        top_album = user.top_album
+        gallery = data.gallery_b7w
+        top_album = gallery.top_album
 
-        controller = AlbumController(user, user, uid=top_album.id)
+        controller = AlbumController(gallery, gallery, uid=top_album.id)
         self.assertEqual(controller.uid, top_album.id)
         self.assertIsNone(controller.obj)
         self.assertEqual(controller.get_object(), top_album)
 
-        controller = AlbumController(user, user, obj=top_album)
+        controller = AlbumController(gallery, gallery, obj=top_album)
         self.assertEqual(controller.uid, top_album.id)
         self.assertEqual(controller.obj, top_album)
         self.assertEqual(controller.get_object(), top_album)

File bviewer/core/tests/test_files.py

     def test_url(self):
         storage = Mock(
             hash_for=Mock(return_value='cache_name'),
-            holder=Mock(url='holder.url'),
+            gallery=Mock(url='gallery.url'),
             type='type'
         )
         self.assertEqual(storage.hash_for(), 'cache_name')
-        self.assertEqual(storage.holder.url, 'holder.url')
+        self.assertEqual(storage.gallery.url, 'gallery.url')
 
         path = ImagePath(storage, 'path/1.jpg')
-        self.assertEqual(path.url, 'type/holder.url/cache_name.jpg')
+        self.assertEqual(path.url, 'type/gallery.url/cache_name.jpg')
 
     def test_order(self):
         self.assertLess(self.f1, self.f2)
                 for_cache = os.path.normcase('cache/images/url/path/img.jpg')
                 self.assertEqual(func(image_path, for_cache=True), for_cache)
 
-        holder = Mock(home='home', url='url', cache_size=0)
-        storage = ImageStorage(holder, root_path='root', cache_path='cache')
+        gallery = Mock(home='home', url='url', cache_size=0)
+        storage = ImageStorage(gallery, root_path='root', cache_path='cache')
 
         assert_method_for_cache('os.path.getctime', storage.ctime, side_effect=str)
         assert_method_for_cache('os.path.exists', storage.exists, side_effect=str)

File bviewer/core/tests/test_images.py

         super(CacheImageTestCase, self).setUp()
         self.data = TestData()
         self.path = 'image1.jpg'
-        self.data.generate_image(self.holder.home, self.path)
+        self.data.generate_image(self.gallery.home, self.path)
 
     def assertCacheImage(self, options, download=False):
         image_path = self.storage.get_path(self.path, options)
         super(ExifTest, self).setUp()
         self.data = TestData()
         self.path = 'image1.jpg'
-        self.data.generate_image(self.holder.home, self.path)
+        self.data.generate_image(self.gallery.home, self.path)
 
     def test_ctime(self):
         exif = self.storage.exif(self.path)

File bviewer/core/tests/test_models.py

 from django.contrib.auth.models import User
 from django.test import TestCase
 
-from bviewer.core.models import ProxyUser, Album, Video
+from bviewer.core.models import Gallery, Album, Video
 from bviewer.core.tests.data import TestData
 
 
         """
         Tests domain match
         """
-        ProxyUser.objects.create(username='Test', password='secret')
+        user = User.objects.create_user('Test', 'test@test.com', 'test')
+
+        Gallery.objects.create(user=user)
         self.assertTrue(User.objects.filter(username='Test').exists())
-        self.assertTrue(ProxyUser.objects.filter(username='Test').exists())
-        self.assertIsNotNone(ProxyUser.objects.get(username='Test').top_album)
-        self.assertTrue(Album.objects.filter(user__username='Test').exists())
+        self.assertTrue(Gallery.objects.filter(user__username='Test').exists())
+        self.assertIsNotNone(Gallery.objects.get(user__username='Test').top_album)
+        self.assertTrue(Album.objects.filter(gallery__user__username='Test').exists())
 
-        user = ProxyUser.objects.get(username='Test')
+        user = User.objects.get(username='Test')
         need = [
-            'core.change_proxyuser',
-            'core.user_holder',
+            'core.change_gallery',
+            'core.user_gallery',
             'core.add_album',
             'core.change_album',
             'core.delete_album',
         Test Vimio 56433514 video and YouTube 7dGGPlZlPQw thumbnails http status.
         Videos can be deleted! Check it first. Anyway it is important test.
         """
-        data = TestData().load_users()
-        album = data.user_b7w.top_album
+        data = TestData().load_users().load_galleries()
+        album = data.gallery_b7w.top_album
 
         video1 = Video.objects.create(album=album, uid='56433514', type=Video.VIMIO)
         self.assertHttpOk(video1.thumbnail_url)

File bviewer/core/tests/test_utils.py

 # -*- coding: utf-8 -*-
+from django.contrib.auth.models import User
 from mock import Mock
 
 from django.conf import settings
 from django.test import TestCase
 
-from bviewer.core.controllers import domain_match, get_album_user
-from bviewer.core.models import ProxyUser
+from bviewer.core.controllers import domain_match, get_gallery
+from bviewer.core.models import Gallery
 
 
 def request_mock(host, user=None):
         """
         Tests get_album_user
         """
-        settings.VIEWER_USER_ID = None
-        user = ProxyUser.objects.create(username='User')
+        settings.VIEWER_GALLERY_ID = None
+        user = User.objects.create_user('User', 'user@user.com', 'test')
+        gallery = Gallery.objects.create(user=user)
 
         request = request_mock('user.example.com')
-        holder = get_album_user(request)
-        self.assertEqual(holder, user)
+        obj = get_gallery(request)
+        self.assertEqual(obj, gallery)
 
         request = request_mock('www.user.example.com:8000')
-        holder = get_album_user(request)
-        self.assertEqual(holder, user)
+        obj = get_gallery(request)
+        self.assertEqual(obj, gallery)
 
         request = request_mock('user.example.com')
-        holder = get_album_user(request)
-        self.assertEqual(holder, user)
+        obj = get_gallery(request)
+        self.assertEqual(obj, gallery)
 
         request = request_mock('example.com')
-        holder = get_album_user(request)
-        self.assertIsNone(holder)
+        obj = get_gallery(request)
+        self.assertIsNone(obj)
 
-        settings.VIEWER_USER_ID = user.id
+        settings.VIEWER_GALLERY_ID = gallery.id
         request = request_mock('example.com')
-        holder = get_album_user(request)
-        self.assertEqual(holder, user)
+        obj = get_gallery(request)
+        self.assertEqual(obj, gallery)

File bviewer/core/views.py

 from django.views.decorators.cache import cache_page
 from django.views.decorators.vary import vary_on_cookie
 
-from bviewer.core.controllers import AlbumController, ImageController, VideoController, get_album_user
+from bviewer.core.controllers import AlbumController, ImageController, VideoController, get_gallery
 from bviewer.core.exceptions import ResizeOptionsError, FileError
 from bviewer.core.utils import decor_on, get_year_parameter
 
     """
     Show home pages with albums
     """
-    holder = get_album_user(request)
-    if not holder:
+    gallery = get_gallery(request)
+    if not gallery:
         return message_view(request, message='No user defined')
 
-    controller = AlbumController(holder, request.user, uid=holder.top_album_id)
+    controller = AlbumController(gallery, request.user, uid=gallery.top_album_id)
     if not controller.exists():
         return message_view(request, message='No main album')
 
     years = controller.get_available_years()
 
     return render(request, 'core/gallery.html', {
-        'holder': holder,
+        'gallery': gallery,
         'main': main,
         'albums': albums,
         'year_filter': year_filter,
     """
     Show sub albums or images with videos
     """
-    holder = get_album_user(request)
-    if not holder:
+    gallery = get_gallery(request)
+    if not gallery:
         return message_view(request, message='No user defined')
 
-    controller = AlbumController(holder, request.user, uid=uid)
+    controller = AlbumController(gallery, request.user, uid=uid)
     if not controller.exists():
         return message_view(request, message='No such album')
 
         years = controller.get_available_years()
 
     return render(request, template, {
-        'holder': holder,
+        'gallery': gallery,
         'main': main,
         'albums': albums,
         'videos': videos,
         'images': images,
         'year_filter': year_filter,
         'years': years,
-        'back': dict(album_id=main.parent_id, home=holder.top_album_id == main.parent_id),
+        'back': dict(album_id=main.parent_id, home=gallery.top_album_id == main.parent_id),
     })
 
 
     """
     Show image with description
     """
-    holder = get_album_user(request)
-    if not holder:
+    gallery = get_gallery(request)
+    if not gallery:
         return message_view(request, message='No user defined')
 
-    controller = ImageController(holder, request.user, uid)
+    controller = ImageController(gallery, request.user, uid)
     image = controller.get_object()
     if image is None:
         return message_view(request, message='No such image')
 
     return render(request, 'core/image.html', {
-        'holder': holder,
+        'gallery': gallery,
         'album': image.album,
         'image': image,
         'back': dict(album_id=image.album_id),
     """
     Show video with description
     """
-    holder = get_album_user(request)
-    if not holder:
+    gallery = get_gallery(request)
+    if not gallery:
         return message_view(request, message='No user defined')
 
-    controller = VideoController(holder, request.user, uid)
+    controller = VideoController(gallery, request.user, uid)
     video = controller.get_object()
     if video is None:
         return message_view(request, message='No such video')
 
     return render(request, 'core/video.html', {
-        'holder': holder,
+        'gallery': gallery,
         'album': video.album,
         'video': video,
         'back': dict(album_id=video.album_id),
     """
     Get video thumbnail from video hosting and cache it
     """
-    holder = get_album_user(request)
-    if not holder:
+    gallery = get_gallery(request)
+    if not gallery:
         raise Http404('No user defined')
 
-    controller = VideoController(holder, request.user, uid)
+    controller = VideoController(gallery, request.user, uid)
     video = controller.get_object()
     if video is None:
         raise Http404('No such video')
     try:
         return controller.get_response('small')
     except ResizeOptionsError as e:
-        logger.error('id:%s, holder:%s \n %s', uid, holder, e)
+        logger.error('id:%s, gallery:%s \n %s', uid, gallery, e)
         return message_view(request, message=e)
     except FileError as e:
-        logger.error('id:%s, holder:%s \n %s', uid, holder, e)
+        logger.error('id:%s, gallery:%s \n %s', uid, gallery, e)
         raise Http404('Oops no video thumbnail found')
 
 
     """
     Get image with special size
     """
-    holder = get_album_user(request)
-    if not holder:
+    gallery = get_gallery(request)
+    if not gallery:
         raise Http404('No user defined')
 
-    controller = ImageController(holder, request.user, uid)
+    controller = ImageController(gallery, request.user, uid)
     image = controller.get_object()
     if image is None:
         raise Http404('No such image')
     try:
         return controller.get_response(size)
     except ResizeOptionsError as e:
-        logger.error('id:%s, holder:%s \n %s', uid, holder, e)
+        logger.error('id:%s, gallery:%s \n %s', uid, gallery, e)
         return message_view(request, message=e)
     except FileError as e:
-        logger.error('id:%s, holder:%s \n %s', uid, holder, e)
+        logger.error('id:%s, gallery:%s \n %s', uid, gallery, e)
         return redirect('/static/core/img/album.png')
 
 
     """
     Show about page
     """
-    holder = get_album_user(request)
-    if not holder:
+    gallery = get_gallery(request)
+    if not gallery:
         return message_view(request, message='No user defined')
 
     return render(request, 'core/about.html', {
-        'holder': holder,
-        'title': holder.about_title,
-        'text': holder.about_text,
+        'gallery': gallery,
+        'title': gallery.about_title,
+        'text': gallery.about_text,
     })
 
 
 def login_view(request):
     """
-    Proxy for `django.contrib.auth.views.login` + holder check
+    Proxy for `django.contrib.auth.views.login` + gallery check
     """
-    holder = get_album_user(request)
-    if not holder:
+    gallery = get_gallery(request)
+    if not gallery:
         return message_view(request, message='No user defined')
-    return login(request, template_name='core/login.html', extra_context=dict(holder=holder))
+    return login(request, template_name='core/login.html', extra_context=dict(gallery=gallery))
 
 
 def logout_view(request):
     """
-    Proxy for `django.contrib.auth.views.logout` + holder check
+    Proxy for `django.contrib.auth.views.logout` + gallery check
     """
-    holder = get_album_user(request)
-    if not holder:
+    gallery = get_gallery(request)
+    if not gallery:
         return message_view(request, message='No user defined')
     return logout(request, next_page='/')

File bviewer/profile/admin.py

 from django.template.loader import render_to_string
 from django.utils.encoding import smart_text
 
-from bviewer.core.admin import ProxyUserForm
+from bviewer.core.admin import GalleryForm
 from bviewer.core.controllers import AlbumController
 from bviewer.core.files.storage import ImageStorage
-from bviewer.core.models import Album, Image, ProxyUser, Video
+from bviewer.core.models import Album, Image, Gallery, Video
 from bviewer.profile.actions import bulk_time_update, update_time_from_exif
 from bviewer.profile.forms import AdminAlbumForm
 
 
     def has_permission(self, request):
         user = request.user
-        return user.is_active and request.user.has_perm('core.user_holder')
+        return user.is_active and request.user.has_perm('core.user_gallery')
 
 
 profile = ProfileSite()
         return super(ProfileAlbumAdmin, self).queryset(request).filter(user=request.user)
 
     def save_model(self, request, obj, form, change):
-        obj.user = ProxyUser.objects.get(pk=request.user.pk)
+        obj.user = Gallery.objects.get(pk=request.user.pk)
         if not obj.parent:
             obj.parent = obj.user.top_album
         thumbnail_id = form.data['thumbnail_id']
 
     def get_form(self, request, obj=None, **kwargs):
         # Add default parent Welcome album
-        user = ProxyUser.objects.get(pk=request.user.pk)
+        user = Gallery.objects.get(pk=request.user.pk)
         data = request.GET.copy()
         data['parent'] = user.top_album_id
         request.GET = data
     )
     readonly_fields = ('last_login', 'date_joined', 'cache_info', )
 
-    form = ProxyUserForm
+    form = GalleryForm
 
     def cache_info(self, user):
         storage = ImageStorage(user)
         return super(ProfileUserAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
 
 
-profile.register(ProxyUser, ProfileUserAdmin)
+profile.register(Gallery, ProfileUserAdmin)

File bviewer/profile/views.py

 from django.shortcuts import render
 from django.utils.encoding import smart_text
 
-from bviewer.core.controllers import get_album_user, AlbumController
+from bviewer.core.controllers import get_gallery, AlbumController
 from bviewer.core.exceptions import FileError
 from bviewer.core.files.response import download_response
 from bviewer.core.files.storage import ImageStorage
 
 
 @login_required
-@permission_required('core.user_holder')
+@permission_required('core.user_gallery')
 def images_view(request, uid):
-    holder = get_album_user(request)
-    if not holder:
+    gallery = get_gallery(request)
+    if not gallery:
         raise Http404()
 
-    controller = AlbumController(holder, request.user, uid=uid)
+    controller = AlbumController(gallery, request.user, uid=uid)
     if not controller.exists():
         return message_view(request, message='No such album')
 
     images = controller.get_images()
-    storage = ImageStorage(holder)
+    storage = ImageStorage(gallery)
     path = request.GET.get('p', '')
     try:
         image_paths = storage.list(path, saved_images=images)
 
 
 @login_required
-@permission_required('core.user_holder')
+@permission_required('core.user_gallery')
 def album_pre_cache(request, uid):
-    holder = get_album_user(request)
-    if not holder:
+    gallery = get_gallery(request)
+    if not gallery:
         raise Http404()
 
-    controller = AlbumController(holder, request.user, uid=uid)
+    controller = AlbumController(gallery, request.user, uid=uid)
     if not controller.exists():
         return message_view(request, message='No such album')
 
 
 
 @login_required
-@permission_required('core.user_holder')
+@permission_required('core.user_gallery')
 def download_image(request):
     if request.GET.get('p', None):
         path = request.GET['p']
-        user = get_album_user(request)
+        user = get_gallery(request)
         storage = ImageStorage(user)
         options = ImageOptions.from_settings('tiny')
         image_path = storage.get_path(path, options)

File bviewer/settings/project.py

 
 # If album is used for one person or for tests
 # set user id here
-VIEWER_USER_ID = None
+VIEWER_GALLERY_ID = None
 
 
 # Path where cache will be stored

File bviewer/slideshow/controllers.py

     def __init__(self, slideshow, redis=None):
         self.slideshow = slideshow
         self.redis = redis
-        self.holder = slideshow.album.user
+        self.gallery = slideshow.album.user
         self.user = slideshow.user
-        self.album_ctrl = AlbumController(self.holder, self.user, uid=slideshow.album_id)
+        self.album_ctrl = AlbumController(selfgalleryr, self.user, uid=slideshow.album_id)
 
     def get_key(self):
         return 'slideshow-id:' + self.slideshow.id
     @cache_method
     def get_album(self):
         obj = None
-        if self.user:  # if holder == user
+        if self.user:  # igalleryer == user
             obj = Album.objects.safe_get(id=self.album_id, user=self.user)
         if not obj:
             obj = Album.objects.safe_get(

File bviewer/slideshow/views.py

 from django.core.urlresolvers import reverse
 from django.shortcuts import render
 
-from bviewer.core.controllers import get_album_user, AlbumController
+from bviewer.core.controllers import get_gallery, AlbumController
 from bviewer.core.views import message_view
 
 
     """
     Slideshow, create new for each session
     """
-    holder = get_album_user(request)
-    if not holder:
+    gallery = get_gallery(request)
+    if not gallery:
         return message_view(request, message='No user defined')
 
-    controller = AlbumController(holder, request.user, uid=holder.top_album_id)
+    controller = AlbumController(gallery, request.user, uid=gallery.top_album_id)
     if not controller.exists():
         return message_view(request, message='No such album')
 
     main = controller.get_object()
-    link = reverse('actions-slideshow-get-or-create') + '?album={0}'.format(holder.top_album_id)
+    link = reverse('actions-slideshow-get-or-create') + '?album={0}'.format(gallery.top_album_id)
     return render(request, 'slideshow/index.html', {
-        'holder': holder,
+        'gallery': gallery,
         'main': main,
         'link': link,
-        'back': dict(album_id=main.id, home=holder.top_album_id == main.id),
+        'back': dict(album_id=main.id, home=gallery.top_album_id == main.id),
     })
 
 
     """
     Slideshow, create new for each session
     """
-    holder = get_album_user(request)
-    if not holder:
+    gallery = get_gallery(request)
+    if not gallery:
         return message_view(request, message='No user defined')
 
-    controller = AlbumController(holder, request.user, uid=album_id)
+    controller = AlbumController(gallery, request.user, uid=album_id)
     if not controller.exists():
         return message_view(request, message='No such album')
 
     main = controller.get_object()
     link = reverse('actions-slideshow-get-or-create') + '?album={0}'.format(album_id)
     return render(request, 'slideshow/index.html', {
-        'holder': holder,
+        'gallery': gallery,
         'main': main,
         'link': link,
-        'back': dict(album_id=main.id, home=holder.top_album_id == main.id),
+        'back': dict(album_id=main.id, home=gallery.top_album_id == main.id),
     })

File docs/ref/settings.rst

 Viewer configuration
 ====================
 
-VIEWER_USER_ID
+VIEWER_GALLERY_ID
 ---------------
 
-.. _CONF_VIEWER_USER_ID:
+.. _CONF_VIEWER_GALLERY_ID:
 
 Default: ``None``
 
-| If album is used for one person or for tests set user id here.
+| If gallery is used for one person or for tests set user id here.
 
 
 VIEWER_CACHE_PATH