Compare commits

...

7 Commits

Author SHA1 Message Date
reverend 4c5a5fee8d #3 Displaying Models on Admin page 2022-12-18 09:24:15 +01:00
reverend 17647bf4b7 #3 Setting up Views for Uploading and listing images 2022-12-18 09:23:36 +01:00
reverend 4deeb3d773 #3 Upload form for Images 2022-12-18 09:23:06 +01:00
reverend 5342e62bcb #3 Setting up Media and Static root 2022-12-18 09:22:44 +01:00
reverend 02512c1677 #3 Dependencies for Images 2022-12-18 09:21:57 +01:00
reverend ba6a40fbe5 Migration for Base Model 2022-12-18 09:20:30 +01:00
reverend bce03d0500 Squashed commit of the following:
commit e08aecabb4db848b495f86c6095fd0ee1edc05be
Author: reverend <reverend@reverend2048.de>
Date:   Sun Dec 18 09:15:25 2022 +0100
2022-12-18 09:18:50 +01:00
13 changed files with 330 additions and 5 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
django_web_galleries/media/*

View File

@ -5,6 +5,8 @@ name = "pypi"
[packages]
django = "*"
django-responsive-images = "*"
pillow = "*"
[dev-packages]

View File

@ -37,6 +37,8 @@ INSTALLED_APPS = [
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'responsive_images',
'web_galleries',
]
MIDDLEWARE = [
@ -115,9 +117,13 @@ USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/4.1/howto/static-files/
STATIC_ROOT = BASE_DIR / 'static'
STATIC_URL = 'static/'
# Default primary key field type
# https://docs.djangoproject.com/en/4.1/ref/settings/#default-auto-field
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
MEDIA_ROOT = BASE_DIR / 'media'
MEDIA_URL = 'media/'

View File

@ -14,8 +14,9 @@ Including another URLconf
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('web_galleries.urls'))
]

View File

@ -1,3 +1,11 @@
from django.contrib import admin
# Register your models here.
from .models import (
Image,
Visitor,
Gallery
)
admin.site.register(Image)
admin.site.register(Visitor)
admin.site.register(Gallery)

View File

@ -0,0 +1,9 @@
from django import forms
from django.utils.translation import gettext as _
from .models import Image
class ImageUploadForm(forms.ModelForm):
class Meta:
model = Image
fields = ['description', 'image_file', 'private']

View File

@ -0,0 +1,55 @@
# Generated by Django 4.1.4 on 2022-12-18 08:19
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='Gallery',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('title', models.CharField(max_length=100, null=True, verbose_name='Optional title for this gallery')),
('private', models.BooleanField(blank=True, default=False, verbose_name='Wether the gallery is vsibile publicly or to certain users only')),
('access_code', models.CharField(max_length=32, null=True, verbose_name='Code to access private galleries')),
],
),
migrations.CreateModel(
name='Visitor',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('session_id', models.CharField(max_length=50, verbose_name='A cookie set by this application to identify a visitor by session')),
('name', models.CharField(default=None, max_length=50, null=True, unique=True, verbose_name='Human readable, self assigned name of the visitor')),
],
),
migrations.CreateModel(
name='Image',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('description', models.TextField(null=True, verbose_name='An optional description of the Image')),
('image_file', models.ImageField(upload_to='web_galleries/uploads/', verbose_name='File of the image')),
('private', models.BooleanField(blank=True, default=False, verbose_name='Wether this image is visible publicly or to certain users only')),
('access_code', models.CharField(max_length=32, null=True, verbose_name='Code to access private images')),
('uploaded_when', models.DateTimeField(auto_now_add=True, verbose_name='When this picture was uploaded')),
('galleries', models.ManyToManyField(related_name='images', to='web_galleries.gallery', verbose_name='What galleries this image is in')),
('uploaded_by', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='uploaded_images', to='web_galleries.visitor', verbose_name='Which visitor uploaded this picture')),
],
),
migrations.AddField(
model_name='gallery',
name='created_by',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='created_galleries', to='web_galleries.visitor', verbose_name='Visitor who created the gallery'),
),
migrations.AddField(
model_name='gallery',
name='visitors',
field=models.ManyToManyField(related_name='linked_galleries', to='web_galleries.visitor', verbose_name='Visitors that a part of this gallery'),
),
]

View File

@ -1,3 +1,107 @@
from django.db import models
from django.core.exceptions import ValidationError
from django.utils.translation import gettext as _
class Visitor(models.Model):
"""
Stores information about a visitor of this application.
No personal information is gathered, the name is optional and can be anything.
The name has to be unique, tho.
"""
session_id = models.CharField(
_('A cookie set by this application to identify a visitor by session'),
max_length=50
)
name = models.CharField(
_('Human readable, self assigned name of the visitor'),
null=True,
default=None,
max_length=50,
unique=True
)
class Gallery(models.Model):
"""
A gallery is a collection of multiple images.
It must be
"""
title = models.CharField(
_('Optional title for this gallery'),
null=True,
max_length=100
)
private = models.BooleanField(
_('Wether the gallery is vsibile publicly or to certain users only'),
default=False,
blank=True
)
access_code = models.CharField(
_('Code to access private galleries'),
null=True,
max_length=32
)
created_by = models.ForeignKey(
Visitor,
verbose_name=_('Visitor who created the gallery'),
related_name='created_galleries',
on_delete=models.CASCADE
)
visitors = models.ManyToManyField(
Visitor,
verbose_name=_('Visitors that a part of this gallery'),
related_name='linked_galleries'
)
def clean(self):
if self.private and access_code is None:
raise ValidationErrorr('Private gallery needs an access code')
if len(self.visitors.all()) > 10:
raise ValidationError('Gallery can not have more than 10 visitors assigned')
class Image(models.Model):
"""
An image contains the path to the image file and several information
like description, uploader and affiliation to galleries.
"""
description = models.TextField(
_('An optional description of the Image'),
null=True
)
image_file = models.ImageField(
_('File of the image'),
upload_to='web_galleries/uploads/'
)
private = models.BooleanField(
_('Wether this image is visible publicly or to certain users only'),
default=False,
blank=True
)
access_code = models.CharField(
_('Code to access private images'),
null=True,
max_length=32
)
uploaded_by = models.ForeignKey(
Visitor,
verbose_name=_('Which visitor uploaded this picture'),
null=True,
related_name='uploaded_images',
on_delete=models.SET_NULL
)
uploaded_when = models.DateTimeField(
_('When this picture was uploaded'),
auto_now_add=True
)
galleries = models.ManyToManyField(
Gallery,
verbose_name=_('What galleries this image is in'),
related_name='images'
)
# Create your models here.

View File

@ -0,0 +1,46 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Web Gallery</title>
</head>
<body>
<div class="RV-Page">
<head class="RV-Head">
<nav class="RV-Navigation">
<ul class="RV-Navigation__list">
<li class="RV-Navigation__item">
<a href="{% url 'home' %}" class="RV-Navigation__link">
Home
</a>
</li>
<li class="RV-Navigation__item">
<a href="{% url 'upload_image' %}" class="RV-Navigation__link">
Upload image
</a>
</li>
<li class="RV-Navigation__item">
<a href="#" class="RV-Navigation__link">
My galleries
</a>
</li>
<li class="RV-Navigation__item">
<a href="#" class="RV-Navigation__link">
Create gallery
</a>
</li>
</ul>
</nav>
</head>
<main class="RV-Content">
{% block content %}
{% endblock content %}
</main>
<footer class="RV-Footer">
</footer>
</div>
</body>
</html>

View File

@ -0,0 +1,13 @@
{% extends '../global.html' %}
{% load responsive_images %}
{% block content %}
<sectoin class="RV-Images">
<li class="RV-Images__list">
{% for image in images %}
<img src="{% src image.image_file 200x200 %}">
{% endfor %}
</li>
</sectoin>
{% endblock content %}

View File

@ -0,0 +1,9 @@
{% extends '../global.html' %}
{% block content %}
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
{{ form }}
<button type="submit">Upload</button>
</form>
{% endblock content %}

View File

@ -0,0 +1,19 @@
from django.urls import path
from django.conf import settings
from django.conf.urls.static import static
from .views import (
ImageUploadView,
PublicImageListView
)
urlpatterns = [
path('', PublicImageListView.as_view(), name='home'),
path('upload/', ImageUploadView.as_view(), name='upload_image')
]
if settings.DEBUG:
urlpatterns += static(
settings.MEDIA_URL,
document_root=settings.MEDIA_ROOT
)

View File

@ -1,3 +1,55 @@
from django.shortcuts import render
import secrets
# Create your views here.
from django.views import View
from django.views.generic.list import ListView
from django.shortcuts import render, redirect
from django.urls import reverse
from .forms import ImageUploadForm
from .models import Image
class ImageUploadView(View):
def get(self, request):
form = ImageUploadForm()
return render(
request,
'upload_image/upload.html',
{
'form': form
}
)
def post(self, request):
form = ImageUploadForm(
request.POST,
request.FILES
)
if form.is_valid():
image = form.save(commit=False)
if image.private:
image.access_code = secrets.token_hex(32)
image.save()
return redirect(
reverse('home')
)
else:
form = ImageUploadForm()
return render(
request,
'upload_image/upload.html',
{
'form': form
}
)
class PublicImageListView(ListView):
model = Image
paginate_by = 20
context_object_name = 'images'
template_name = 'list_images/image_list.html'
def get_queryset(self):
return Image.objects.all().filter(private=False)