Initial commit from ZIP

This commit is contained in:
kusz committed 2024-11-27 13:18:16 +01:00
commit 378d4692a9
454 files changed
+40367

No files matched your search

+11
View File
@@ -0,0 +1,11 @@
from django.utils.translation import gettext_lazy as _
from django.apps import AppConfig
class FinalPhotobriefingAppConfig(AppConfig):
name = "outbo.apps.final_photobriefing"
label = "final_photobriefing"
verbose_name = _("Final photo briefing")
default_app_config = "outbo.apps.final_photobriefing.FinalPhotobriefingAppConfig"
+3
View File
@@ -0,0 +1,3 @@
from django.contrib import admin
# Register your models here.
+9
View File
@@ -0,0 +1,9 @@
from enum import Enum
class PhotoType(Enum):
INVALID = "<invalid>"
ARRANGEMENT_PHOTOS = "arrangement"
CLIPPING = "clipping"
PACKSHOT = "packshot"
EXTRA_PHOTO = "extraPhoto"
@@ -0,0 +1,49 @@
# Generated by Django 2.2.8 on 2019-12-18 13:54
import rules.contrib.models
from django.db import migrations, models
import outbo.apps.core.fields
class Migration(migrations.Migration):
initial = True
dependencies = []
operations = [
migrations.CreateModel(
name="FinalBrief",
fields=[
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"created_at",
outbo.apps.core.fields.CreationDateTimeField(
auto_now_add=True, verbose_name="Created at"
),
),
(
"updated_at",
outbo.apps.core.fields.ModificationDateTimeField(
auto_now=True, verbose_name="Updated at"
),
),
(
"deleted_at",
outbo.apps.core.fields.RemovalDateTimeField(
blank=True, editable=False, null=True, verbose_name="Deleted at"
),
),
],
options={"abstract": False,},
bases=(rules.contrib.models.RulesModelMixin, models.Model),
),
]
@@ -0,0 +1,14 @@
# Generated by Django 2.2.8 on 2019-12-18 14:03
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("final_photobriefing", "0001_initial"),
]
operations = [
migrations.RemoveField(model_name="finalbrief", name="id",),
]
@@ -0,0 +1,27 @@
# Generated by Django 2.2.8 on 2019-12-18 14:03
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
("photobriefing", "0001_initial"),
("final_photobriefing", "0002_remove_finalbrief_id"),
]
operations = [
migrations.AddField(
model_name="finalbrief",
name="brief",
field=models.ForeignKey(
default=0,
on_delete=django.db.models.deletion.PROTECT,
primary_key=True,
serialize=False,
to="photobriefing.Brief",
),
preserve_default=False,
),
]
@@ -0,0 +1,24 @@
# Generated by Django 2.2.8 on 2019-12-18 14:05
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
("final_photobriefing", "0003_finalbrief_brief"),
]
operations = [
migrations.AlterField(
model_name="finalbrief",
name="brief",
field=models.OneToOneField(
on_delete=django.db.models.deletion.PROTECT,
primary_key=True,
serialize=False,
to="photobriefing.Brief",
),
),
]
@@ -0,0 +1,26 @@
# Generated by Django 2.2.8 on 2019-12-18 14:06
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
("final_photobriefing", "0004_auto_20191218_1505"),
]
operations = [
migrations.AlterField(
model_name="finalbrief",
name="brief",
field=models.OneToOneField(
on_delete=django.db.models.deletion.PROTECT,
primary_key=True,
related_name="final",
related_query_name="final",
serialize=False,
to="photobriefing.Brief",
),
),
]
@@ -0,0 +1,102 @@
# Generated by Django 2.2.8 on 2019-12-19 08:48
from django.db import migrations, models
import django.db.models.deletion
import outbo.apps.core.fields
import outbo.apps.final_photobriefing.enums
import outbo.apps.final_photobriefing.models
import rules.contrib.models
class Migration(migrations.Migration):
dependencies = [
("final_photobriefing", "0005_auto_20191218_1506"),
]
operations = [
migrations.CreateModel(
name="FinalBriefPhoto",
fields=[
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"created_at",
outbo.apps.core.fields.CreationDateTimeField(
auto_now_add=True, verbose_name="Created at"
),
),
(
"updated_at",
outbo.apps.core.fields.ModificationDateTimeField(
auto_now=True, verbose_name="Updated at"
),
),
(
"deleted_at",
outbo.apps.core.fields.RemovalDateTimeField(
blank=True, editable=False, null=True, verbose_name="Deleted at"
),
),
(
"file",
models.FileField(
upload_to=outbo.apps.final_photobriefing.models.FormatFinalPhotoBriefPhotoFilename()
),
),
(
"category",
models.CharField(
choices=[
(
outbo.apps.final_photobriefing.enums.PhotoType(
"<invalid>"
),
"<invalid>",
),
(
outbo.apps.final_photobriefing.enums.PhotoType(
"arrangement"
),
"arrangement",
),
(
outbo.apps.final_photobriefing.enums.PhotoType(
"clipping"
),
"clipping",
),
(
outbo.apps.final_photobriefing.enums.PhotoType(
"packshot"
),
"packshot",
),
(
outbo.apps.final_photobriefing.enums.PhotoType(
"extraPhoto"
),
"extraPhoto",
),
],
max_length=30,
),
),
(
"brief",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
to="final_photobriefing.FinalBrief",
),
),
],
bases=(rules.contrib.models.RulesModelMixin, models.Model),
),
]
@@ -0,0 +1,56 @@
# Generated by Django 2.2.8 on 2019-12-20 10:14
from django.db import migrations, models
import django.db.models.deletion
import outbo.apps.final_photobriefing.enums
class Migration(migrations.Migration):
dependencies = [
("final_photobriefing", "0006_finalbriefphoto"),
]
operations = [
migrations.RemoveField(model_name="finalbriefphoto", name="category",),
migrations.AddField(
model_name="finalbriefphoto",
name="type",
field=models.CharField(
choices=[
(
outbo.apps.final_photobriefing.enums.PhotoType("<invalid>"),
"<invalid>",
),
(
outbo.apps.final_photobriefing.enums.PhotoType("arrangement"),
"arrangement",
),
(
outbo.apps.final_photobriefing.enums.PhotoType("clipping"),
"clipping",
),
(
outbo.apps.final_photobriefing.enums.PhotoType("packshot"),
"packshot",
),
(
outbo.apps.final_photobriefing.enums.PhotoType("extraPhoto"),
"extraPhoto",
),
],
default=outbo.apps.final_photobriefing.enums.PhotoType("<invalid>"),
max_length=30,
),
),
migrations.AlterField(
model_name="finalbriefphoto",
name="brief",
field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="photos",
related_query_name="photo",
to="final_photobriefing.FinalBrief",
),
),
]
@@ -0,0 +1,26 @@
# Generated by Django 2.2.10 on 2020-05-25 08:25
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
("final_photobriefing", "0007_auto_20191220_1114"),
]
operations = [
migrations.AlterField(
model_name="finalbrief",
name="brief",
field=models.OneToOneField(
on_delete=django.db.models.deletion.CASCADE,
primary_key=True,
related_name="final",
related_query_name="final",
serialize=False,
to="photobriefing.Brief",
),
),
]
Whitespace-only changes.
+63
View File
@@ -0,0 +1,63 @@
import os
from django.db import models
from django.utils.deconstruct import deconstructible
from rules.contrib.models import RulesModel
from outbo.apps.core.models import TimestampableDeletableMixin
from outbo.apps.final_photobriefing import rules
from outbo.apps.final_photobriefing.enums import PhotoType
@deconstructible
class FormatFinalPhotoBriefPhotoFilename:
def __call__(self, instance, filename):
obj = instance.brief.brief
return "/".join(
("projects", obj.product.project.slug[1:], "final-photobriefing", filename)
)
class FinalBrief(TimestampableDeletableMixin, RulesModel):
class Meta:
rules_permissions = {
"add": rules.can_create_final_brief,
"view": rules.can_read_final_brief,
"change": rules.can_update_final_brief,
"delete": rules.can_delete_final_brief,
}
brief = models.OneToOneField(
to="photobriefing.Brief",
on_delete=models.CASCADE,
related_name="final",
related_query_name="final",
primary_key=True,
)
class FinalBriefPhoto(TimestampableDeletableMixin, RulesModel):
class Meta:
rules_permissions = {
"add": rules.can_create_final_brief_photo,
"view": rules.can_read_final_brief_photo,
"change": rules.can_update_final_brief_photo,
"delete": rules.can_delete_final_brief_photo,
}
brief = models.ForeignKey(
to=FinalBrief,
on_delete=models.CASCADE,
related_query_name="photo",
related_name="photos",
)
file = models.FileField(upload_to=FormatFinalPhotoBriefPhotoFilename())
type = models.CharField(
max_length=30,
choices=[(type, type.value) for type in PhotoType],
default=PhotoType.INVALID,
)
@property
def filename(self):
return os.path.basename(self.file.name)
+13
View File
@@ -0,0 +1,13 @@
from rules import always_deny, always_allow
from outbo.apps.core.rules import is_agency
can_create_final_brief = always_deny
can_read_final_brief = always_allow
can_update_final_brief = is_agency
can_delete_final_brief = always_deny
can_create_final_brief_photo = always_deny
can_read_final_brief_photo = always_allow
can_update_final_brief_photo = is_agency
can_delete_final_brief_photo = is_agency
+13
View File
@@ -0,0 +1,13 @@
from rest_framework_extensions.routers import ExtendedSimpleRouter
from outbo.apps.final_photobriefing.viewsets import (
FinalBriefViewSet,
FinalBriefPhotoViewSet,
)
app_name = "final_photobriefing"
router = ExtendedSimpleRouter()
router.register(prefix="final-photobriefing", viewset=FinalBriefViewSet)
router.register(prefix="final-photobriefing-photo", viewset=FinalBriefPhotoViewSet)
urlpatterns = router.urls
+99
View File
@@ -0,0 +1,99 @@
from django.http import HttpResponseRedirect
from rest_framework import serializers
from rest_framework.permissions import AllowAny
from outbo.apps.core.viewsets import (
AutoPermissionViewSetMixin,
RetrieveModelMixin,
MultipleSerializerViewSet,
PartialUpdateModelMixin,
DestroyModelMixin,
)
from outbo.apps.final_photobriefing.enums import PhotoType
from outbo.apps.final_photobriefing.models import FinalBrief, FinalBriefPhoto
class FinalBriefPhotoSerializer:
class List(serializers.ModelSerializer):
url = serializers.HyperlinkedIdentityField(
view_name="final_photobriefing:finalbriefphoto-detail"
)
type = serializers.SerializerMethodField()
filename = serializers.ReadOnlyField()
class Meta:
model = FinalBriefPhoto
fields = ["url", "type", "filename"]
def get_type(self, instance):
t, val = instance.type.split(".", 1)
return PhotoType[val].value
class Create(serializers.ModelSerializer):
type = serializers.CharField()
class Meta:
model = FinalBriefPhoto
fields = ["type", "file"]
def validate_type(self, value):
try:
return PhotoType(value)
except ValueError:
raise serializers.ValidationError("Invalid photo type value")
class BaseFinalBriefSerializer(serializers.ModelSerializer):
class Meta:
model = FinalBrief
class FinalBriefSerializer:
class Retrieve(BaseFinalBriefSerializer):
photos = FinalBriefPhotoSerializer.List(many=True)
class Meta(BaseFinalBriefSerializer.Meta):
fields = ["photos", "created_at", "updated_at"]
class Update(BaseFinalBriefSerializer):
photos = FinalBriefPhotoSerializer.Create(many=True)
class Meta(BaseFinalBriefSerializer.Meta):
fields = ["photos"]
def update(self, instance, validated_data):
photos = validated_data.pop("photos", None)
if photos is not None:
for photo in photos:
FinalBriefPhoto.objects.create(brief=instance, **photo)
return instance
class FinalBriefViewSet(
AutoPermissionViewSetMixin,
RetrieveModelMixin,
PartialUpdateModelMixin,
MultipleSerializerViewSet,
):
queryset = FinalBrief.objects.all()
serializer_class_set = FinalBriefSerializer
class FinalBriefPhotoViewSet(
AutoPermissionViewSetMixin,
RetrieveModelMixin,
DestroyModelMixin,
MultipleSerializerViewSet,
):
queryset = FinalBriefPhoto.objects.all()
serializer_class_set = FinalBriefPhotoSerializer
retrieve_permission_classes = [AllowAny]
def get_permissions(self):
if self.action == "retrieve":
return [permission() for permission in self.retrieve_permission_classes]
return super().get_permissions()
def retrieve(self, request, *args, **kwargs):
photo = self.get_object()
return HttpResponseRedirect(redirect_to=photo.file.url)