Skip to content

Commit

Permalink
first working prototype
Browse files Browse the repository at this point in the history
  • Loading branch information
ephes committed Nov 7, 2018
1 parent 948ec47 commit 5d0384d
Show file tree
Hide file tree
Showing 63 changed files with 3,080 additions and 49 deletions.
9 changes: 9 additions & 0 deletions .gitignore
Expand Up @@ -48,3 +48,12 @@ docs/_build

# environmen
.env

# gitignore
.gitignore.swp

# django files
CACHE
cast_images
cast_videos
django_cast.egg-info
3 changes: 3 additions & 0 deletions Makefile
Expand Up @@ -30,6 +30,9 @@ clean-pyc: ## remove Python file artifacts
lint: ## check style with flake8
flake8 cast tests

black: ## paint it black
black cast tests

test: ## run tests quickly with the default Python
python runtests.py tests

Expand Down
2 changes: 1 addition & 1 deletion cast/__init__.py
@@ -1 +1 @@
__version__ = '0.1.0'
__version__ = "0.1.0"
68 changes: 68 additions & 0 deletions cast/admin.py
@@ -0,0 +1,68 @@
import logging

from django.contrib import admin

from .models import Blog, Post, File, Image, Video, Gallery

logger = logging.getLogger(__name__)


class AdminUserMixin:
def get_changeform_initial_data(self, request):
return {"user": request.user, "author": request.user}


class BlogModelAdmin(AdminUserMixin, admin.ModelAdmin):
list_display = ("title", "user")


admin.site.register(Blog, BlogModelAdmin)


class PostModelAdmin(AdminUserMixin, admin.ModelAdmin):
list_display = ("title", "author", "blog")

class Media:
js = ("js/cast/ckeditor_fix.js",)


admin.site.register(Post, PostModelAdmin)


class ImageModelAdmin(AdminUserMixin, admin.ModelAdmin):
list_display = ("pk", "original", "user")
fields = ("user", "original")


admin.site.register(Image, ImageModelAdmin)


class FileAdmin(AdminUserMixin, admin.ModelAdmin):
list_display = ("original", "user")
fields = ("user", "original")


admin.site.register(File, FileAdmin)


class VideoModelAdmin(AdminUserMixin, admin.ModelAdmin):
list_display = ("pk", "user")

def save_model(self, request, obj, form, change):
logger.info("poster: {}".format(obj.poster))
logger.info("form: {}".format(form.cleaned_data))
if change and not form.cleaned_data["poster"]:
logger.info("poster was cleared")
obj.calc_poster = False
super().save_model(request, obj, form, change)


admin.site.register(Video, VideoModelAdmin)


class GalleryModelAdmin(AdminUserMixin, admin.ModelAdmin):
list_display = ("pk",)
fields = ("user", "images")


admin.site.register(Gallery, GalleryModelAdmin)
Binary file added cast/api/.serializers.py.swp
Binary file not shown.
Empty file added cast/api/__init__.py
Empty file.
44 changes: 44 additions & 0 deletions cast/api/serializers.py
@@ -0,0 +1,44 @@
import logging

from rest_framework import serializers

from ..models import Image, Video, Gallery

logger = logging.getLogger(__name__)


class ImageSerializer(serializers.HyperlinkedModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name="cast:api:image_detail")
srcset = serializers.ReadOnlyField()
thumbnail_src = serializers.ReadOnlyField()
full_src = serializers.ReadOnlyField()

class Meta:
model = Image
fields = ("id", "url", "original", "srcset", "thumbnail_src", "full_src")


class VideoSerializer(serializers.HyperlinkedModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name="cast:api:video_detail")
poster = serializers.ImageField(read_only=True, allow_empty_file=True)
poster_thumbnail = serializers.ImageField(read_only=True, allow_empty_file=True)

class Meta:
model = Video
fields = ("id", "url", "original", "poster", "poster_thumbnail")


class GallerySerializer(serializers.HyperlinkedModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name="cast:api:gallery_detail")
images = serializers.PrimaryKeyRelatedField(many=True, queryset=Image.objects.all())

def create(self, validated_data):
user = self.context["request"].user
gallery = Gallery.objects.create(user=user)
for image in validated_data["images"]:
gallery.images.add(image)
return gallery

class Meta:
model = Gallery
fields = ("id", "url", "images")
40 changes: 40 additions & 0 deletions cast/api/urls.py
@@ -0,0 +1,40 @@
from django.conf.urls import url

from rest_framework.schemas import get_schema_view

from . import views

app_name = "api"
schema_view = get_schema_view(title="Cast API")

urlpatterns = [
url(r"^schema/$", schema_view),
url(r"^$", views.api_root, name="root"),
# image
url(r"^images/?$", views.ImageListView.as_view(), name="image_list"),
url(
r"^images/(?P<pk>\d+)/?$", views.ImageDetailView.as_view(), name="image_detail"
),
url(
regex=r"^upload_image/$",
view=views.ImageCreateView.as_view(),
name="upload_image",
),
# gallery
url(r"^gallery/?$", views.GalleryListView.as_view(), name="gallery_list"),
url(
r"^gallery/(?P<pk>\d+)/?$",
views.GalleryDetailView.as_view(),
name="gallery_detail",
),
# video
url(r"^videos/?$", views.VideoListView.as_view(), name="video_list"),
url(
r"^videos/(?P<pk>\d+)/?$", views.VideoDetailView.as_view(), name="video_detail"
),
url(
regex=r"^upload_video/$",
view=views.VideoCreateView.as_view(),
name="upload_video",
),
]
16 changes: 16 additions & 0 deletions cast/api/viewmixins.py
@@ -0,0 +1,16 @@
import logging

from django.http import HttpResponse


logger = logging.getLogger(__name__)


class FileUploadResponseMixin:
def get_success_url(self):
return None

def form_valid(self, form):
model = form.save(commit=False)
super().form_valid(form)
return HttpResponse("{}".format(model.pk), status=201)
113 changes: 113 additions & 0 deletions cast/api/views.py
@@ -0,0 +1,113 @@
import logging

from collections import OrderedDict

from django.views.generic import CreateView

from django.contrib.auth.mixins import LoginRequiredMixin

from django.urls import reverse

from rest_framework import generics
from rest_framework.response import Response
from rest_framework.decorators import api_view
from rest_framework.permissions import IsAuthenticated
from rest_framework.pagination import PageNumberPagination

from .serializers import ImageSerializer, VideoSerializer, GallerySerializer

from ..forms import ImageForm, VideoForm

from ..viewmixins import AddRequestUserMixin
from .viewmixins import FileUploadResponseMixin

from ..models import Image, Video, Gallery

logger = logging.getLogger(__name__)


@api_view(["GET"])
def api_root(request):
"""
Show API contents.
If you add any object types, add them here!
"""
root_api_urls = (
("images", request.build_absolute_uri(reverse("cast:api:image_list"))),
("galleries", request.build_absolute_uri(reverse("cast:api:gallery_list"))),
("videos", request.build_absolute_uri(reverse("cast:api:video_list"))),
)
return Response(OrderedDict(root_api_urls))


class ImageCreateView(
LoginRequiredMixin, AddRequestUserMixin, FileUploadResponseMixin, CreateView
):
model = Image
form_class = ImageForm
user_field_name = "user"


class VideoCreateView(
LoginRequiredMixin, AddRequestUserMixin, FileUploadResponseMixin, CreateView
):
model = Video
form_class = VideoForm
user_field_name = "user"


class StandardResultsSetPagination(PageNumberPagination):
page_size = 20
page_size_query_param = "pageSize"
max_page_size = 10000


class ImageListView(generics.ListCreateAPIView):
serializer_class = ImageSerializer
pagination_class = StandardResultsSetPagination
permission_classes = (IsAuthenticated,)

def get_queryset(self):
user = self.request.user
qs = Image.objects.all().filter(user=user)
return qs.order_by("-created")


class ImageDetailView(generics.RetrieveDestroyAPIView):
queryset = Image.objects.all()
serializer_class = ImageSerializer
permission_classes = (IsAuthenticated,)


class VideoListView(generics.ListCreateAPIView):
serializer_class = VideoSerializer
pagination_class = StandardResultsSetPagination
permission_classes = (IsAuthenticated,)

def get_queryset(self):
user = self.request.user
qs = Video.objects.all().filter(user=user)
return qs.order_by("-created")


class VideoDetailView(generics.RetrieveDestroyAPIView):
queryset = Video.objects.all()
serializer_class = VideoSerializer
permission_classes = (IsAuthenticated,)


class GalleryListView(generics.ListCreateAPIView):
serializer_class = GallerySerializer
pagination_class = StandardResultsSetPagination
permission_classes = (IsAuthenticated,)

def get_queryset(self):
user = self.request.user
qs = Gallery.objects.all().filter(user=user)
return qs.order_by("-created")


class GalleryDetailView(generics.RetrieveDestroyAPIView):
queryset = Gallery.objects.all()
serializer_class = GallerySerializer
permission_classes = (IsAuthenticated,)
2 changes: 1 addition & 1 deletion cast/apps.py
Expand Up @@ -3,4 +3,4 @@


class CastConfig(AppConfig):
name = 'cast'
name = "cast"
64 changes: 64 additions & 0 deletions cast/forms.py
@@ -0,0 +1,64 @@
from __future__ import absolute_import

from django import forms
from django.utils import timezone
from django.utils.translation import ugettext_lazy as _

from .models import Post, Image, Video


class PostForm(forms.ModelForm):
is_published = forms.BooleanField(required=False)
pub_date = forms.DateTimeField(input_formats=["%Y-%m-%dT%H:%M"])

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields["slug"].required = False
self.fields["title"].widget.attrs["size"] = 80
self.fields["pub_date"].required = False
self.fields["pub_date"].widget = forms.DateTimeInput(
attrs={"type": "datetime-local"}
)
self.fields["pub_date"].label = _("Publication date")
self.fields["pub_date"].help_text = _(
"Article will be published after this date/time."
)
self.fields["visible_date"].required = False
self.fields["visible_date"].widget = forms.DateInput(attrs={"type": "date"})
self.fields["visible_date"].label = _("Visible date")
self.fields["visible_date"].help_text = _("Date to be shown above article.")

def _set_pub_date(self, cleaned_data):
pub_date = cleaned_data.get("pub_date")
is_published = cleaned_data.get("is_published")
if pub_date is None and is_published:
cleaned_data["pub_date"] = timezone.now()
return cleaned_data

def clean(self):
cleaned_data = super().clean()
cleaned_data = self._set_pub_date(cleaned_data)
return cleaned_data

class Meta:
model = Post
fields = [
"title",
"content",
"pub_date",
"visible_date",
"is_published",
"slug",
]


class ImageForm(forms.ModelForm):
class Meta:
model = Image
fields = ["original"]


class VideoForm(forms.ModelForm):
class Meta:
model = Video
fields = ["original"]
Binary file added cast/management/.DS_Store
Binary file not shown.
Binary file added cast/management/commands/.s3_stale.py.swp
Binary file not shown.
Empty file.

0 comments on commit 5d0384d

Please sign in to comment.