gm-148: finish

This commit is contained in:
Anatoly 2019-09-30 15:40:28 +03:00
parent 7f79ce8945
commit 501b8833ed
12 changed files with 229 additions and 9 deletions

View File

@ -0,0 +1,41 @@
# Generated by Django 2.2.4 on 2019-09-30 07:14
from django.db import migrations, models
import django.db.models.deletion
import easy_thumbnails.fields
import utils.methods
class Migration(migrations.Migration):
dependencies = [
('gallery', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='image',
name='orientation',
field=models.PositiveSmallIntegerField(blank=True, choices=[(0, 'Horizontal'), (1, 'Vertical')], default=None, null=True, verbose_name='image orientation'),
),
migrations.AddField(
model_name='image',
name='parent',
field=models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.SET_DEFAULT, related_name='parent_image', to='gallery.Image', verbose_name='parent image'),
),
migrations.AddField(
model_name='image',
name='source',
field=models.PositiveSmallIntegerField(choices=[(0, 'Mobile'), (1, 'Web'), (2, 'All')], default=0, verbose_name='Source'),
),
migrations.AddField(
model_name='image',
name='title',
field=models.CharField(default='', max_length=255, verbose_name='title'),
),
migrations.AlterField(
model_name='image',
name='image',
field=easy_thumbnails.fields.ThumbnailerImageField(upload_to=utils.methods.image_path, verbose_name='image file'),
),
]

View File

@ -9,6 +9,8 @@ class ImageSerializer(serializers.ModelSerializer):
file = serializers.ImageField(source='image',
write_only=True)
title = serializers.CharField()
orientation = serializers.ChoiceField(choices=models.Image.ORIENTATIONS,
write_only=True)
# RESPONSE
url = serializers.ImageField(source='image',

View File

@ -6,5 +6,5 @@ from . import views
app_name = 'gallery'
urlpatterns = [
path('upload/', views.ImageUploadView.as_view(), name='upload-image')
path('upload/', views.ImageBaseView.as_view(), name='upload-image'),
]

View File

@ -3,8 +3,17 @@ from rest_framework import generics
from . import models, serializers
class ImageUploadView(generics.CreateAPIView):
"""Upload image to gallery"""
class ImageBaseView(generics.CreateAPIView):
"""Upload image to gallery."""
model = models.Image
queryset = models.Image.objects.all()
serializer_class = serializers.ImageSerializer
class NewsImageListView(ImageBaseView, generics.ListAPIView):
"""Return list of uploaded images for news object."""
def get_queryset(self):
"""Override get_queryset method."""
qs = super(NewsImageListView, self).get_queryset()
return qs.filter(news_gallery__news=self.kwargs.get('news_id'))

View File

@ -1,4 +1,5 @@
from django.contrib import admin
from news import models
@ -12,3 +13,8 @@ class NewsTypeAdmin(admin.ModelAdmin):
@admin.register(models.News)
class NewsAdmin(admin.ModelAdmin):
"""News admin."""
@admin.register(models.NewsGallery)
class NewsGalleryAdmin(admin.ModelAdmin):
"""News gallery admin."""

View File

@ -0,0 +1,21 @@
# Generated by Django 2.2.4 on 2019-09-26 11:56
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('news', '0013_auto_20190924_0806'),
]
operations = [
migrations.RemoveField(
model_name='news',
name='image_url',
),
migrations.RemoveField(
model_name='news',
name='preview_image_url',
),
]

View File

@ -0,0 +1,27 @@
# Generated by Django 2.2.4 on 2019-09-30 08:57
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('gallery', '0002_auto_20190930_0714'),
('news', '0014_auto_20190926_1156'),
]
operations = [
migrations.CreateModel(
name='NewsGallery',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('image', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='news_gallery', to='gallery.Image', verbose_name='gallery')),
('news', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='news_gallery', to='news.News', verbose_name='news')),
],
options={
'verbose_name': 'news gallery',
'verbose_name_plural': 'news galleries',
},
),
]

View File

@ -0,0 +1,19 @@
# Generated by Django 2.2.4 on 2019-09-30 12:06
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('gallery', '0002_auto_20190930_0714'),
('news', '0015_newsgallery'),
]
operations = [
migrations.AddField(
model_name='news',
name='gallery',
field=models.ManyToManyField(through='news.NewsGallery', to='gallery.Image'),
),
]

View File

@ -83,6 +83,8 @@ class News(BaseAttributes, TranslatedFieldsMixin):
verbose_name=_('country'))
tags = generic.GenericRelation(to='main.MetaDataContent')
gallery = models.ManyToManyField('gallery.Image', through='news.NewsGallery')
objects = NewsQuerySet.as_manager()
class Meta:
@ -103,7 +105,7 @@ class NewsGalleryQuerySet(models.QuerySet):
"""QuerySet for model News"""
def originals(self):
"""Return QuerySet with originals images."""
"""Return QuerySet with original images."""
return self.filter(gallery__parent__isnull=True)
def crops(self):
@ -117,10 +119,10 @@ class NewsGallery(models.Model):
related_name='news_gallery',
on_delete=models.SET_NULL,
verbose_name=_('news'))
gallery = models.ForeignKey('gallery.Image', null=True,
related_name='news_gallery',
on_delete=models.SET_NULL,
verbose_name=_('gallery'))
image = models.ForeignKey('gallery.Image', null=True,
related_name='news_gallery',
on_delete=models.SET_NULL,
verbose_name=_('gallery'))
objects = NewsGalleryQuerySet.as_manager()

View File

@ -1,6 +1,9 @@
"""News app common serializers."""
from django.utils.translation import gettext_lazy as _
from rest_framework import serializers
from gallery.models import Image
from gallery.serializers import ImageSerializer
from location import models as location_models
from location.serializers import CountrySimpleSerializer
from main.serializers import MetaDataContentSerializer
@ -28,6 +31,7 @@ class NewsBaseSerializer(serializers.ModelSerializer):
# related fields
news_type = NewsTypeSerializer(read_only=True)
tags = MetaDataContentSerializer(read_only=True, many=True)
gallery = ImageSerializer(read_only=True, many=True)
slug = serializers.SlugField(allow_blank=False, required=True, max_length=50)
@ -43,6 +47,7 @@ class NewsBaseSerializer(serializers.ModelSerializer):
'news_type',
'tags',
'slug',
'gallery',
)
@ -100,3 +105,43 @@ class NewsBackOfficeDetailSerializer(NewsBackOfficeBaseSerializer,
'country_id',
)
class NewsBackOfficeGallerySerializer(serializers.ModelSerializer):
"""Serializer class for model NewsGallery."""
image = ImageSerializer(read_only=True)
class Meta:
"""Meta class"""
model = models.NewsGallery
fields = [
'id',
'image',
]
def get_request_kwargs(self):
"""Get url kwargs from request."""
return self.context.get('request').parser_context.get('kwargs')
def validate(self, attrs):
"""Override validate method."""
news_pk = self.get_request_kwargs().get('pk')
image_id = self.get_request_kwargs().get('image_id')
news_qs = models.News.objects.filter(pk=news_pk)
image_qs = Image.objects.filter(id=image_id)
if not news_qs.exists():
raise serializers.ValidationError({'detail': _('News not found')})
if not image_qs.exists():
raise serializers.ValidationError({'detail': _('Image not found')})
news = news_qs.first()
image = image_qs.first()
if news.news_gallery.filter(image=image).exists():
raise serializers.ValidationError({'detail': _('Image is already added')})
attrs['news'] = news
attrs['image'] = image
return attrs

View File

@ -1,5 +1,6 @@
"""News app urlpatterns for backoffice"""
from django.urls import path
from news import views
app_name = 'news'
@ -7,5 +8,9 @@ app_name = 'news'
urlpatterns = [
path('', views.NewsBackOfficeLCView.as_view(), name='list-create'),
path('<int:pk>/', views.NewsBackOfficeRUDView.as_view(),
name='retrieve-update-destroy'),
name='gallery-retrieve-update-destroy'),
path('<int:pk>/gallery/', views.NewsBackOfficeGalleryListView.as_view(),
name='gallery-list'),
path('<int:pk>/gallery/<int:image_id>/', views.NewsBackOfficeGalleryCreateDestroyView.as_view(),
name='gallery-create-destroy'),
]

View File

@ -1,5 +1,8 @@
"""News app views."""
from django.shortcuts import get_object_or_404
from rest_framework import generics, permissions
from gallery.serializers import ImageSerializer
from news import filters, models, serializers
@ -59,6 +62,46 @@ class NewsBackOfficeLCView(NewsBackOfficeMixinView,
return super().get_serializer_class()
class NewsBackOfficeGalleryCreateDestroyView(NewsBackOfficeMixinView,
generics.CreateAPIView,
generics.DestroyAPIView):
"""Resource for a create gallery for news for back-office users."""
serializer_class = serializers.NewsBackOfficeGallerySerializer
def get_object(self):
"""
Returns the object the view is displaying.
"""
news_qs = self.filter_queryset(self.get_queryset())
news = get_object_or_404(news_qs, pk=self.kwargs['pk'])
gallery = get_object_or_404(news.news_gallery, image_id=self.kwargs['image_id'])
# May raise a permission denied
self.check_object_permissions(self.request, gallery)
return gallery
class NewsBackOfficeGalleryListView(NewsBackOfficeMixinView, generics.ListAPIView):
"""Resource for returning gallery for news for back-office users."""
serializer_class = ImageSerializer
def get_object(self):
"""Override get_object method."""
qs = super(NewsBackOfficeGalleryListView, self).get_queryset()
news = get_object_or_404(qs, pk=self.kwargs['pk'])
# May raise a permission denied
self.check_object_permissions(self.request, news)
return news
def get_queryset(self):
"""Override get_queryset method."""
return self.get_object().gallery.all()
class NewsBackOfficeRUDView(NewsBackOfficeMixinView,
generics.RetrieveUpdateDestroyAPIView):
"""Resource for detailed information about news for back-office users."""