commit 0508d8cd9a03395d560430c1fdc833f779a1c634 Author: j Date: Tue Sep 28 15:10:22 2021 +0200 aab21 diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..3be662d --- /dev/null +++ b/.editorconfig @@ -0,0 +1,23 @@ +[*] +end_of_line = lf +insert_final_newline = true + +[*.py] +indent_style = space +indent_size = 4 + +[*.sass] +indent_style = space +indent_size = 2 + +[*.scss] +indent_style = space +indent_size = 2 + +[*.html] +indent_style = tab +indent_size = 4 + +[*.js] +indent_style = space +indent_size = 4 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..27aa007 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +venv +__pycache__ +db.sqlite3 +www/ diff --git a/app/__init__.py b/app/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/asgi.py b/app/asgi.py new file mode 100644 index 0000000..895c0e0 --- /dev/null +++ b/app/asgi.py @@ -0,0 +1,16 @@ +""" +ASGI config for app project. + +It exposes the ASGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/3.2/howto/deployment/asgi/ +""" + +import os + +from django.core.asgi import get_asgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'app.settings') + +application = get_asgi_application() diff --git a/app/page/__init__.py b/app/page/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/page/admin.py b/app/page/admin.py new file mode 100644 index 0000000..c6fe108 --- /dev/null +++ b/app/page/admin.py @@ -0,0 +1,2 @@ +from django.contrib import admin + diff --git a/app/page/apps.py b/app/page/apps.py new file mode 100644 index 0000000..6ab5e1e --- /dev/null +++ b/app/page/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class PageConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'page' diff --git a/app/page/migrations/__init__.py b/app/page/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/page/models.py b/app/page/models.py new file mode 100644 index 0000000..c5ba80c --- /dev/null +++ b/app/page/models.py @@ -0,0 +1,5 @@ +import logging + +from django.db import models + +# Create your models here. diff --git a/app/page/tests.py b/app/page/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/app/page/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/app/page/views.py b/app/page/views.py new file mode 100644 index 0000000..91ea44a --- /dev/null +++ b/app/page/views.py @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here. diff --git a/app/settings.py b/app/settings.py new file mode 100644 index 0000000..e45e806 --- /dev/null +++ b/app/settings.py @@ -0,0 +1,145 @@ +""" +Django settings for app project. + +Generated by 'django-admin startproject' using Django 3.2.7. + +For more information on this file, see +https://docs.djangoproject.com/en/3.2/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/3.2/ref/settings/ +""" + +from pathlib import Path + +# Build paths inside the project like this: BASE_DIR / 'subdir'. +BASE_DIR = Path(__file__).resolve().parent.parent + + +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/3.2/howto/deployment/checklist/ + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = 'django-insecure-4^*01ba-twojkikte8_7q_%zc96f@i%^gwg-36*xlr1&l4w-im' + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = True + +ALLOWED_HOSTS = [] + + +# Application definition + +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + + 'sass_processor', + + 'app', + 'app.user', + 'app.video', + 'app.text', + +] + +MIDDLEWARE = [ + 'django.middleware.security.SecurityMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', +] + +ROOT_URLCONF = 'app.urls' + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.debug', + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + ], + 'builtins': [ + 'django.templatetags.static', + ] + }, + }, +] + +WSGI_APPLICATION = 'app.wsgi.application' + + +# Database +# https://docs.djangoproject.com/en/3.2/ref/settings/#databases + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': BASE_DIR / 'db.sqlite3', + } +} + + +# Password validation +# https://docs.djangoproject.com/en/3.2/ref/settings/#auth-password-validators + +AUTH_PASSWORD_VALIDATORS = [ + { + 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', + }, +] +AUTH_USER_MODEL = 'user.User' + + +# Internationalization +# https://docs.djangoproject.com/en/3.2/topics/i18n/ + +LANGUAGE_CODE = 'en-us' + +TIME_ZONE = 'UTC' + +USE_I18N = True + +USE_L10N = True + +USE_TZ = True + + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/3.2/howto/static-files/ + +STATIC_URL = '/static/' +STATIC_ROOT = BASE_DIR / 'www' / 'static' +MEDIA_ROOT = BASE_DIR / 'data' / 'media' + +STATICFILES_FINDERS = [ + 'django.contrib.staticfiles.finders.FileSystemFinder', + 'django.contrib.staticfiles.finders.AppDirectoriesFinder', + 'sass_processor.finders.CssFinder', +] + +# Default primary key field type +# https://docs.djangoproject.com/en/3.2/ref/settings/#default-auto-field + +DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' diff --git a/app/static/css/style.scss b/app/static/css/style.scss new file mode 100644 index 0000000..438b94c --- /dev/null +++ b/app/static/css/style.scss @@ -0,0 +1,12 @@ +body { + background: #000; + color: #fff; + font-family: "Noto Sans"; + font-size: 20px; +} + +nav { + a { + color: #fff; + } +} diff --git a/app/templates/about.html b/app/templates/about.html new file mode 100644 index 0000000..e65d078 --- /dev/null +++ b/app/templates/about.html @@ -0,0 +1,5 @@ +{% extends "base.html" %} +{% block main %} +about page +{% endblock %} + diff --git a/app/templates/base.html b/app/templates/base.html new file mode 100644 index 0000000..c16fdf7 --- /dev/null +++ b/app/templates/base.html @@ -0,0 +1,32 @@ +{% load sass_tags static %} + + + + + + {% block title %} + Phantas.ma/polis – 2021 Asian Art Biennial + {% endblock title %} + + + {% block head %}{% endblock head %} + + +

+ phtantasmapolis: Looking Back to the Future +
+ 未竟之城:回顧未來 +

+ +
+ {% block main %}{% endblock main %} +
+ {% block end %}{% endblock end %} + + diff --git a/app/templates/edit.html b/app/templates/edit.html new file mode 100644 index 0000000..8d368ac --- /dev/null +++ b/app/templates/edit.html @@ -0,0 +1,4 @@ +{% extends "base.html" %} +{% block main %} +some overview page with stuff +{% endblock %} diff --git a/app/templates/edit_play.html b/app/templates/edit_play.html new file mode 100644 index 0000000..5248d87 --- /dev/null +++ b/app/templates/edit_play.html @@ -0,0 +1,7 @@ +{% extends "base.html" %} +{% block main %} +

{{ edit.data.title }}

+{% if edit.vimeo_id %} + +{% endif %} +{% endblock %} diff --git a/app/templates/edits.html b/app/templates/edits.html new file mode 100644 index 0000000..8d368ac --- /dev/null +++ b/app/templates/edits.html @@ -0,0 +1,4 @@ +{% extends "base.html" %} +{% block main %} +some overview page with stuff +{% endblock %} diff --git a/app/templates/essays.html b/app/templates/essays.html new file mode 100644 index 0000000..8d368ac --- /dev/null +++ b/app/templates/essays.html @@ -0,0 +1,4 @@ +{% extends "base.html" %} +{% block main %} +some overview page with stuff +{% endblock %} diff --git a/app/templates/film.html b/app/templates/film.html new file mode 100644 index 0000000..ebaaea3 --- /dev/null +++ b/app/templates/film.html @@ -0,0 +1,9 @@ +{% extends "base.html" %} +{% block main %} + + + +

{{ film.data.title | safe }}

+

{{ film.data.director|join:", "|safe }}

+

{{ film.data.summary|safe }}

+{% endblock %} diff --git a/app/templates/film_play.html b/app/templates/film_play.html new file mode 100644 index 0000000..a508050 --- /dev/null +++ b/app/templates/film_play.html @@ -0,0 +1,7 @@ +{% extends "base.html" %} +{% block main %} +

{{ film.data.title }}

+{% if film.vimeo_id %} + +{% endif %} +{% endblock %} diff --git a/app/templates/films.html b/app/templates/films.html new file mode 100644 index 0000000..67cb2f2 --- /dev/null +++ b/app/templates/films.html @@ -0,0 +1,10 @@ +{% extends "base.html" %} +{% block main %} +some overview page with stuff +{% for film in films %} +
+ {{ film.data.title | safe }} + {{ film.data.director|join:", "|safe }} +
+{% endfor %} +{% endblock %} diff --git a/app/templates/index.html b/app/templates/index.html new file mode 100644 index 0000000..8d368ac --- /dev/null +++ b/app/templates/index.html @@ -0,0 +1,4 @@ +{% extends "base.html" %} +{% block main %} +some overview page with stuff +{% endblock %} diff --git a/app/templates/tv.html b/app/templates/tv.html new file mode 100644 index 0000000..ca9a7a1 --- /dev/null +++ b/app/templates/tv.html @@ -0,0 +1,5 @@ +{% extends "base.html" %} +{% block title %}TV{% endblock%} +{% block main %} +here be TV stuff +{% endblock %} diff --git a/app/text/__init__.py b/app/text/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/text/admin.py b/app/text/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/app/text/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/app/text/apps.py b/app/text/apps.py new file mode 100644 index 0000000..8c4ee5f --- /dev/null +++ b/app/text/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class TextConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'app.text' diff --git a/app/text/migrations/0001_initial.py b/app/text/migrations/0001_initial.py new file mode 100644 index 0000000..b749a86 --- /dev/null +++ b/app/text/migrations/0001_initial.py @@ -0,0 +1,42 @@ +# Generated by Django 3.2.7 on 2021-09-28 12:09 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Essay', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created', models.DateTimeField(auto_now_add=True)), + ('modified', models.DateTimeField(auto_now=True)), + ('slug', models.SlugField()), + ('public', models.BooleanField(default=False)), + ('data', models.JSONField(default=dict)), + ('title', models.TextField()), + ('teaser', models.TextField()), + ('body', models.TextField()), + ], + ), + migrations.CreateModel( + name='Page', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created', models.DateTimeField(auto_now_add=True)), + ('modified', models.DateTimeField(auto_now=True)), + ('slug', models.SlugField()), + ('public', models.BooleanField(default=False)), + ('data', models.JSONField(default=dict)), + ('title', models.TextField()), + ('teaser', models.TextField()), + ('body', models.TextField()), + ], + ), + ] diff --git a/app/text/migrations/__init__.py b/app/text/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/text/models.py b/app/text/models.py new file mode 100644 index 0000000..94058f7 --- /dev/null +++ b/app/text/models.py @@ -0,0 +1,33 @@ +import logging + +from django.contrib.auth import get_user_model +from django.db import models + +logger = logging.getLogger(__name__) +User = get_user_model() + +class Page(models.Model): + created = models.DateTimeField(auto_now_add=True) + modified = models.DateTimeField(auto_now=True) + + slug = models.SlugField() + public = models.BooleanField(default=False) + + data = models.JSONField(default=dict) + + title = models.TextField() + teaser = models.TextField() + body = models.TextField() + +class Essay(models.Model): + created = models.DateTimeField(auto_now_add=True) + modified = models.DateTimeField(auto_now=True) + + slug = models.SlugField() + public = models.BooleanField(default=False) + + data = models.JSONField(default=dict) + + title = models.TextField() + teaser = models.TextField() + body = models.TextField() diff --git a/app/text/tests.py b/app/text/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/app/text/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/app/text/views.py b/app/text/views.py new file mode 100644 index 0000000..8f33951 --- /dev/null +++ b/app/text/views.py @@ -0,0 +1,21 @@ +from django.shortcuts import render, redirect, get_object_or_404 + +from . import models + +def index(request): + context = {} + return render(request, 'index.html', context) + +def about(request): + context = {} + return render(request, 'about.html', context) + +def essays(request): + context = {} + context['essays'] = models.Essay.objects.filter(public=True).order_by('created') + return render(request, 'essays.html', context) + +def essay(request, slug): + context = {} + context['essay'] = get_object_or_404(models.Essay, slug=slug) + return render(request, 'essay.html', context) diff --git a/app/urls.py b/app/urls.py new file mode 100644 index 0000000..9e0d008 --- /dev/null +++ b/app/urls.py @@ -0,0 +1,35 @@ +"""app URL Configuration + +The `urlpatterns` list routes URLs to views. For more information please see: + https://docs.djangoproject.com/en/3.2/topics/http/urls/ +Examples: +Function views + 1. Add an import: from my_app import views + 2. Add a URL to urlpatterns: path('', views.home, name='home') +Class-based views + 1. Add an import: from other_app.views import Home + 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') +Including another URLconf + 1. Import the include() function: from django.urls import include, path + 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) +""" +from django.contrib import admin +from django.urls import path + +from .video import views as video +from .text import views as text + +urlpatterns = [ + path('admin/', admin.site.urls), + path('films/', video.films, name='films'), + path('film//play', video.film_play, name='film_play'), + path('film//', video.film, name='film'), + path('edits/', video.edits, name='edits'), + path('edit//play', video.edit_play, name='edit_play'), + path('edit//', video.edit, name='edit'), + path('tv/', video.tv, name='tv'), + path('essays/', text.essays, name='essays'), + path('essay//', text.essay, name='essay'), + path('about/', text.about, name='about'), + path('', text.index, name='index'), +] diff --git a/app/user/__init__.py b/app/user/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/user/admin.py b/app/user/admin.py new file mode 100644 index 0000000..dd16e1b --- /dev/null +++ b/app/user/admin.py @@ -0,0 +1,8 @@ +from django.contrib import admin + +from . import models + + +@admin.decorators.register(models.User) +class UserAdmin(admin.ModelAdmin): + pass diff --git a/app/user/apps.py b/app/user/apps.py new file mode 100644 index 0000000..30d6aa2 --- /dev/null +++ b/app/user/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class UserConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'app.user' diff --git a/app/user/migrations/0001_initial.py b/app/user/migrations/0001_initial.py new file mode 100644 index 0000000..1032658 --- /dev/null +++ b/app/user/migrations/0001_initial.py @@ -0,0 +1,46 @@ +# Generated by Django 3.2.7 on 2021-09-28 12:09 + +import django.contrib.auth.models +import django.contrib.auth.validators +from django.db import migrations, models +import django.utils.timezone + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('auth', '0012_alter_user_first_name_max_length'), + ] + + operations = [ + migrations.CreateModel( + name='User', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('password', models.CharField(max_length=128, verbose_name='password')), + ('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')), + ('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')), + ('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=150, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='username')), + ('first_name', models.CharField(blank=True, max_length=150, verbose_name='first name')), + ('last_name', models.CharField(blank=True, max_length=150, verbose_name='last name')), + ('email', models.EmailField(blank=True, max_length=254, verbose_name='email address')), + ('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')), + ('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')), + ('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')), + ('modified', models.DateTimeField(auto_now=True)), + ('data', models.JSONField(default=dict)), + ('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.Group', verbose_name='groups')), + ('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.Permission', verbose_name='user permissions')), + ], + options={ + 'verbose_name': 'user', + 'verbose_name_plural': 'users', + 'abstract': False, + }, + managers=[ + ('objects', django.contrib.auth.models.UserManager()), + ], + ), + ] diff --git a/app/user/migrations/__init__.py b/app/user/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/user/models.py b/app/user/models.py new file mode 100644 index 0000000..4657d00 --- /dev/null +++ b/app/user/models.py @@ -0,0 +1,10 @@ +import logging + +from django.db import models +from django.contrib.auth.models import AbstractUser + +logger = logging.getLogger(__name__) + +class User(AbstractUser): + modified = models.DateTimeField(auto_now=True) + data = models.JSONField(default=dict, blank=True, editable=False) diff --git a/app/user/tests.py b/app/user/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/app/user/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/app/user/views.py b/app/user/views.py new file mode 100644 index 0000000..91ea44a --- /dev/null +++ b/app/user/views.py @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here. diff --git a/app/video/__init__.py b/app/video/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/video/admin.py b/app/video/admin.py new file mode 100644 index 0000000..c0d501f --- /dev/null +++ b/app/video/admin.py @@ -0,0 +1,12 @@ +from django.contrib import admin + +from . import models + + +@admin.decorators.register(models.Film) +class FilmAdmin(admin.ModelAdmin): + pass + +@admin.decorators.register(models.Edit) +class EditAdmin(admin.ModelAdmin): + pass diff --git a/app/video/apps.py b/app/video/apps.py new file mode 100644 index 0000000..535d17a --- /dev/null +++ b/app/video/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class VideoConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'app.video' diff --git a/app/video/management/commands/load_titles.py b/app/video/management/commands/load_titles.py new file mode 100644 index 0000000..f04998c --- /dev/null +++ b/app/video/management/commands/load_titles.py @@ -0,0 +1,30 @@ +from django.core.management.base import BaseCommand + +import ox +from ... import models + +class Command(BaseCommand): + help = 'import titles from pan.do/ra' + + def add_arguments(self, parser): + parser.add_argument("--api", dest="api", type=str, default='https://pad.ma/api/'), + parser.add_argument("--group", dest="group", type=str, default='Asian Art Biennial 2021'), + + def handle(self, *args, **options): + api = ox.api.signin(options['api']) + query = { + 'query': { + 'conditions': [{'key': 'groups', 'value': options['group'], 'operator': '=='}] + }, + 'keys': ['id', 'title', 'director', 'summary', 'source'], + 'range': [0, 1000] + } + for item in api.find(**query)['data']['items']: + print(item) + f, c = models.Film.objects.get_or_create(padma_id=item['id']) + for key, value in item.items(): + if key != 'id': + f.data[key] = value + f.public = True + f.slug = item['id'] + f.save() diff --git a/app/video/migrations/0001_initial.py b/app/video/migrations/0001_initial.py new file mode 100644 index 0000000..4a9db4e --- /dev/null +++ b/app/video/migrations/0001_initial.py @@ -0,0 +1,41 @@ +# Generated by Django 3.2.7 on 2021-09-28 12:09 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Edit', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created', models.DateTimeField(auto_now_add=True)), + ('modified', models.DateTimeField(auto_now=True)), + ('slug', models.SlugField()), + ('public', models.BooleanField(default=False)), + ('padma_id', models.CharField(max_length=1024)), + ('annotation_user', models.CharField(max_length=1024)), + ('vimeo_id', models.CharField(default=None, max_length=255, null=True)), + ('data', models.JSONField(default=dict)), + ], + ), + migrations.CreateModel( + name='Film', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created', models.DateTimeField(auto_now_add=True)), + ('modified', models.DateTimeField(auto_now=True)), + ('slug', models.SlugField()), + ('public', models.BooleanField(default=False)), + ('padma_id', models.CharField(max_length=255)), + ('vimeo_id', models.CharField(default=None, max_length=255, null=True)), + ('data', models.JSONField(default=dict)), + ], + ), + ] diff --git a/app/video/migrations/__init__.py b/app/video/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/video/models.py b/app/video/models.py new file mode 100644 index 0000000..8c0ab91 --- /dev/null +++ b/app/video/models.py @@ -0,0 +1,40 @@ +import logging + +from django.contrib.auth import get_user_model +from django.db import models + +logger = logging.getLogger(__name__) +User = get_user_model() + + +class Film(models.Model): + created = models.DateTimeField(auto_now_add=True) + modified = models.DateTimeField(auto_now=True) + + slug = models.SlugField() + public = models.BooleanField(default=False) + + padma_id = models.CharField(max_length=255) + vimeo_id = models.CharField(max_length=255, default=None, null=True) + + data = models.JSONField(default=dict, blank=True) + + def __str__(self): + return self.data.get('title', self.slug) + + +class Edit(models.Model): + created = models.DateTimeField(auto_now_add=True) + modified = models.DateTimeField(auto_now=True) + + slug = models.SlugField() + public = models.BooleanField(default=False) + + padma_id = models.CharField(max_length=1024) + annotation_user = models.CharField(max_length=1024) + vimeo_id = models.CharField(max_length=255, default=None, null=True) + + data = models.JSONField(default=dict, blank=True) + + def __str__(self): + return self.data.get('title', self.slug) diff --git a/app/video/tests.py b/app/video/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/app/video/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/app/video/views.py b/app/video/views.py new file mode 100644 index 0000000..b6872c2 --- /dev/null +++ b/app/video/views.py @@ -0,0 +1,37 @@ +from django.shortcuts import render, redirect, get_object_or_404 + +from . import models + +def films(request): + context = {} + context['films'] = models.Film.objects.filter(public=True).order_by('created') + return render(request, 'films.html', context) + +def film(request, slug): + context = {} + context['film'] = get_object_or_404(models.Film, slug=slug) + return render(request, 'film.html', context) + +def film_play(request, slug): + context = {} + context['film'] = get_object_or_404(models.Film, slug=slug) + return render(request, 'film_play.html', context) + +def edits(request): + context = {} + context['edits'] = models.Edit.objects.filter(public=True).order_by('created') + return render(request, 'edits.html', context) + +def edit(request, slug): + context = {} + context['edit'] = get_object_or_404(models.Edit, slug=slug) + return render(request, 'edit.html', context) + +def edit_play(request, slug): + context = {} + context['edit'] = get_object_or_404(models.Edit, slug=slug) + return render(request, 'edit_play.html', context) + +def tv(request): + context = {} + return render(request, 'tv.html', context) diff --git a/app/wsgi.py b/app/wsgi.py new file mode 100644 index 0000000..768c6e4 --- /dev/null +++ b/app/wsgi.py @@ -0,0 +1,16 @@ +""" +WSGI config for app project. + +It exposes the WSGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/3.2/howto/deployment/wsgi/ +""" + +import os + +from django.core.wsgi import get_wsgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'app.settings') + +application = get_wsgi_application() diff --git a/manage.py b/manage.py new file mode 100755 index 0000000..a787340 --- /dev/null +++ b/manage.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python +"""Django's command-line utility for administrative tasks.""" +import os +import sys + +def activate_venv(base): + if os.path.exists(base): + old_os_path = os.environ.get('PATH', '') + os.environ['PATH'] = os.path.join(base, 'bin') + os.pathsep + old_os_path + site_packages = os.path.join(base, 'lib', 'python%s' % sys.version[:3], 'site-packages') + prev_sys_path = list(sys.path) + import site + site.addsitedir(site_packages) + sys.real_prefix = sys.prefix + sys.prefix = base + # Move the added items to the front of the path: + new_sys_path = [] + for item in list(sys.path): + if item not in prev_sys_path: + new_sys_path.append(item) + sys.path.remove(item) + sys.path[:0] = new_sys_path + + +def main(): + """Run administrative tasks.""" + root_dir = os.path.normpath(os.path.abspath(os.path.dirname(__file__))) + activate_venv(os.path.normpath(os.path.join(root_dir, 'venv'))) + + os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'app.settings') + try: + from django.core.management import execute_from_command_line + except ImportError as exc: + raise ImportError( + "Couldn't import Django. Are you sure it's installed and " + "available on your PYTHONPATH environment variable? Did you " + "forget to activate a virtual environment?" + ) from exc + execute_from_command_line(sys.argv) + + +if __name__ == '__main__': + main() diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..8e59a6d --- /dev/null +++ b/requirements.txt @@ -0,0 +1,8 @@ +Django +psycopg2 +libsass +django-sass-processor +django-sass-processor + +ox +lxml