replace comment model from establishment app, added new app comment

This commit is contained in:
Anatoly 2019-09-04 18:47:06 +03:00
parent cfc2d512ed
commit 605c81b33c
25 changed files with 271 additions and 60 deletions

0
apps/comment/__init__.py Normal file
View File

8
apps/comment/admin.py Normal file
View File

@ -0,0 +1,8 @@
from django.contrib import admin
from . import models
@admin.register(models.Comment)
class CommentModelAdmin(admin.ModelAdmin):
"""Model admin for model Comment"""

8
apps/comment/apps.py Normal file
View File

@ -0,0 +1,8 @@
from django.apps import AppConfig
from django.utils.translation import gettext_lazy as _
class CommentConfig(AppConfig):
name = 'comment'
verbose_name = _('comment')
verbose_name_plural = _('comments')

View File

@ -0,0 +1,36 @@
# Generated by Django 2.2.4 on 2019-09-04 14:03
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import django.utils.timezone
class Migration(migrations.Migration):
initial = True
dependencies = [
('contenttypes', '0002_remove_content_type_name'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='Comment',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created', models.DateTimeField(default=django.utils.timezone.now, editable=False, verbose_name='Date created')),
('modified', models.DateTimeField(auto_now=True, verbose_name='Date updated')),
('text', models.TextField(verbose_name='Comment text')),
('mark', models.PositiveIntegerField(blank=True, default=None, null=True, verbose_name='Mark')),
('object_id', models.PositiveIntegerField()),
('content_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.ContentType')),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='comments', to=settings.AUTH_USER_MODEL, verbose_name='User')),
],
options={
'verbose_name': 'Comment',
'verbose_name_plural': 'Comments',
},
),
]

View File

51
apps/comment/models.py Normal file
View File

@ -0,0 +1,51 @@
"""Models for app comment."""
from django.contrib.contenttypes import fields as generic
from django.db import models
from django.utils.translation import gettext_lazy as _
from account.models import User
from utils.models import ProjectBaseMixin
class CommentQuerySet(models.QuerySet):
"""QuerySets for Comment model."""
def by_user(self, user: User):
"""Return comments by author"""
return self.filter(user=user)
def annotate_is_mine_status(self, user):
"""Annotate belonging status"""
return self.annotate(is_mine=models.Case(
models.When(
models.Q(user=user),
then=True
),
default=False,
output_field=models.BooleanField(default=False)
))
class Comment(ProjectBaseMixin):
"""Comment model."""
text = models.TextField(verbose_name=_('Comment text'))
mark = models.PositiveIntegerField(blank=True, null=True, default=None,
verbose_name=_('Mark'))
user = models.ForeignKey('account.User',
related_name='comments',
on_delete=models.CASCADE,
verbose_name=_('User'))
content_type = models.ForeignKey(generic.ContentType, on_delete=models.CASCADE)
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey('content_type', 'object_id')
objects = CommentQuerySet.as_manager()
class Meta:
"""Meta class"""
verbose_name = _('Comment')
verbose_name_plural = _('Comments')
def __str__(self):
"""String representation"""
return str(self.user)

View File

View File

@ -0,0 +1,60 @@
"""Common serializers for app comment."""
from rest_framework import serializers
from comment import models
from establishment.models import Establishment
class CommentBaseMixin(serializers.Serializer):
"""Comment base serializer mixin"""
# RESPONSE
nickname = serializers.CharField(read_only=True,
source='user.username')
profile_pic = serializers.ImageField(read_only=True,
source='user.image')
class CommentSerializer(CommentBaseMixin, serializers.ModelSerializer):
"""Comment serializer"""
is_mine = serializers.BooleanField(read_only=True)
class Meta:
"""Serializer for model Comment"""
model = models.Comment
fields = [
'id',
'user_id',
'is_mine',
'created',
'text',
'mark',
'nickname',
'profile_pic'
]
class EstablishmentCommentCreateSerializer(CommentSerializer):
"""Create comment serializer"""
mark = serializers.IntegerField()
establishment_id = serializers.PrimaryKeyRelatedField(queryset=Establishment.objects.all(),
source='content_object',
write_only=True)
class Meta:
"""Serializer for model Comment"""
model = models.Comment
fields = [
'created',
'text',
'mark',
'nickname',
'profile_pic',
'establishment_id',
]
def create(self, validated_data):
"""Override create method"""
validated_data.update({
'user': self.context.get('request').user
})
return super().create(validated_data)

View File

View File

@ -0,0 +1 @@
"""Serializers for app comment."""

1
apps/comment/tests.py Normal file
View File

@ -0,0 +1 @@
# Create your tests here.

View File

View File

@ -0,0 +1,12 @@
"""Comment urlpaths."""
from django.urls import path
from comment.views import common as views
app_name = 'comment'
urlpatterns = [
path('', views.CommentListView.as_view(), name='comment-list'),
path('create/', views.CommentCreateView.as_view(), name='comment-create'),
path('<int:pk>/', views.CommentRUD.as_view(), name='comment-rud'),
]

View File

@ -0,0 +1,9 @@
"""Mobile urlpaths."""
from comment.urls.common import urlpatterns as common_urlpatterns
app_name = 'comment'
urlpatterns_api = []
urlpatterns = common_urlpatterns + \
urlpatterns_api

9
apps/comment/urls/web.py Normal file
View File

@ -0,0 +1,9 @@
"""Web urlpaths."""
from comment.urls.common import urlpatterns as common_urlpatterns
app_name = 'comment'
urlpatterns_api = []
urlpatterns = common_urlpatterns + \
urlpatterns_api

View File

View File

@ -0,0 +1,34 @@
"""Views for app comment."""
from rest_framework import generics
from rest_framework.permissions import AllowAny
from comment.models import Comment
from comment.serializers import common as serializers
class CommentViewMixin:
"""Mixin for Comment views"""
queryset = Comment.objects.order_by('-created')
serializer_class = serializers.CommentSerializer
class CommentListView(CommentViewMixin, generics.ListAPIView):
"""View for retrieving list of comments."""
permission_classes = (AllowAny, )
def get_queryset(self):
"""Override get_queryset method."""
return self.queryset.annotate_is_mine_status(user=self.request.user)
class CommentCreateView(CommentViewMixin, generics.CreateAPIView):
"""View for create new comment."""
serializer_class = serializers.EstablishmentCommentCreateSerializer
class CommentRUD(CommentViewMixin, generics.RetrieveUpdateDestroyAPIView):
"""View for retrieve/update/destroy view."""
def get_queryset(self):
"""Override get_queryset method."""
return self.queryset.by_user(self.request.user)

View File

View File

View File

@ -1,10 +1,12 @@
"""Establishment admin conf.""" """Establishment admin conf."""
from django.contrib import admin from django.contrib import admin
from django.contrib.contenttypes.admin import GenericTabularInline from django.contrib.contenttypes.admin import GenericTabularInline
from django.utils.translation import gettext_lazy as _
from comment.models import Comment
from establishment import models from establishment import models
from main.models import Award, MetaDataContent from main.models import Award, MetaDataContent
from review import models as review_models from review import models as review_models
from django.utils.translation import gettext_lazy as _
@admin.register(models.EstablishmentType) @admin.register(models.EstablishmentType)
@ -44,13 +46,18 @@ class ReviewInline(GenericTabularInline):
extra = 0 extra = 0
class CommentInline(GenericTabularInline):
model = Comment
extra = 0
@admin.register(models.Establishment) @admin.register(models.Establishment)
class EstablishmentAdmin(admin.ModelAdmin): class EstablishmentAdmin(admin.ModelAdmin):
"""Establishment admin.""" """Establishment admin."""
inlines = [ inlines = [
AwardInline, MetaDataContentInline, AwardInline, MetaDataContentInline,
ContactPhoneInline, ContactEmailInline, ContactPhoneInline, ContactEmailInline,
ReviewInline] ReviewInline, CommentInline]
@admin.register(models.EstablishmentSchedule) @admin.register(models.EstablishmentSchedule)
@ -58,11 +65,6 @@ class EstablishmentSchedule(admin.ModelAdmin):
"""Establishment schedule""" """Establishment schedule"""
@admin.register(models.Comment)
class EstablishmentComment(admin.ModelAdmin):
"""Establishment comments."""
@admin.register(models.Position) @admin.register(models.Position)
class PositionAdmin(admin.ModelAdmin): class PositionAdmin(admin.ModelAdmin):
"""Position admin.""" """Position admin."""

View File

@ -0,0 +1,16 @@
# Generated by Django 2.2.4 on 2019-09-04 13:12
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('establishment', '0014_establishment_website'),
]
operations = [
migrations.DeleteModel(
name='Comment',
),
]

View File

@ -1,11 +1,13 @@
"""Establishment models.""" """Establishment models."""
from functools import reduce from functools import reduce
from django.contrib.contenttypes import fields as generic from django.contrib.contenttypes import fields as generic
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.db import models from django.db import models
from django.utils import timezone from django.utils import timezone
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from phonenumber_field.modelfields import PhoneNumberField from phonenumber_field.modelfields import PhoneNumberField
from location.models import Address from location.models import Address
from utils.models import (ProjectBaseMixin, ImageMixin, TJSONField, from utils.models import (ProjectBaseMixin, ImageMixin, TJSONField,
TranslatedFieldsMixin, BaseAttributes) TranslatedFieldsMixin, BaseAttributes)
@ -129,6 +131,7 @@ class Establishment(ProjectBaseMixin, ImageMixin, TranslatedFieldsMixin):
awards = generic.GenericRelation(to='main.Award') awards = generic.GenericRelation(to='main.Award')
tags = generic.GenericRelation(to='main.MetaDataContent') tags = generic.GenericRelation(to='main.MetaDataContent')
reviews = generic.GenericRelation(to='review.Review') reviews = generic.GenericRelation(to='review.Review')
comments = generic.GenericRelation(to='comment.Comment')
objects = EstablishmentQuerySet.as_manager() objects = EstablishmentQuerySet.as_manager()
@ -345,38 +348,3 @@ class Menu(TranslatedFieldsMixin, BaseAttributes):
class Meta: class Meta:
verbose_name = _('menu') verbose_name = _('menu')
verbose_name_plural = _('menu') verbose_name_plural = _('menu')
class CommentQuerySet(models.QuerySet):
"""QuerySets for Comment model."""
def by_author(self, author):
"""Return comments by author"""
return self.filter(author=author)
class Comment(ProjectBaseMixin):
"""Comment model."""
text = models.TextField(verbose_name=_('Comment text'))
mark = models.PositiveIntegerField(blank=True, null=True,
default=None,
verbose_name=_('Mark'))
author = models.ForeignKey('account.User',
related_name='comments',
on_delete=models.CASCADE,
verbose_name=_('Author'))
establishment = models.ForeignKey(Establishment,
related_name='comments',
on_delete=models.CASCADE,
verbose_name=_('Establishment'))
objects = CommentQuerySet.as_manager()
class Meta:
"""Meta class"""
verbose_name = _('Comment')
verbose_name_plural = _('Comments')
def __str__(self):
"""String representation"""
return str(self.author)

View File

@ -1,6 +1,7 @@
"""Establishment serializers.""" """Establishment serializers."""
from rest_framework import serializers from rest_framework import serializers
from comment.serializers.common import CommentSerializer
from establishment import models from establishment import models
from location.serializers import AddressSerializer from location.serializers import AddressSerializer
from main.serializers import MetaDataContentSerializer, AwardSerializer, CurrencySerializer from main.serializers import MetaDataContentSerializer, AwardSerializer, CurrencySerializer
@ -106,23 +107,6 @@ class ReviewSerializer(serializers.ModelSerializer):
) )
class CommentSerializer(serializers.ModelSerializer):
"""Comment serializer"""
nickname = serializers.CharField(source='author.username')
profile_pic = serializers.ImageField(source='author.image')
class Meta:
"""Serializer for model Comment"""
model = models.Comment
fields = (
'created',
'text',
'mark',
'nickname',
'profile_pic'
)
class EstablishmentEmployeeSerializer(serializers.ModelSerializer): class EstablishmentEmployeeSerializer(serializers.ModelSerializer):
"""Serializer for actual employees.""" """Serializer for actual employees."""
@ -154,7 +138,8 @@ class EstablishmentSerializer(serializers.ModelSerializer):
phones = ContactPhonesSerializer(read_only=True, many=True, ) phones = ContactPhonesSerializer(read_only=True, many=True, )
emails = ContactEmailsSerializer(read_only=True, many=True, ) emails = ContactEmailsSerializer(read_only=True, many=True, )
reviews = ReviewSerializer(source='reviews.last', allow_null=True) reviews = ReviewSerializer(source='reviews.last', allow_null=True)
comments = CommentSerializer(many=True, allow_null=True) # comments = CommentSerializer(many=True, allow_null=True)
comments = serializers.SerializerMethodField()
employees = EstablishmentEmployeeSerializer(source='actual_establishment_employees', employees = EstablishmentEmployeeSerializer(source='actual_establishment_employees',
many=True) many=True)
menu = MenuSerializers(source='menu_set', many=True, read_only=True) menu = MenuSerializers(source='menu_set', many=True, read_only=True)
@ -198,6 +183,15 @@ class EstablishmentSerializer(serializers.ModelSerializer):
'best_price_carte' 'best_price_carte'
) )
def get_comments(self, obj):
"""Serializer method for comment field"""
request = self.context.get('request')
if request.user.is_authenticated:
return CommentSerializer(obj.comments.all().annotate_is_mine_status(user=request.user),
many=True).data
else:
return CommentSerializer(obj.comments.all(), many=True).data
def get_preview_image(self, obj): def get_preview_image(self, obj):
"""Get preview image""" """Get preview image"""
return obj.get_full_image_url(request=self.context.get('request'), return obj.get_full_image_url(request=self.context.get('request'),

View File

@ -67,6 +67,7 @@ PROJECT_APPS = [
'configuration.apps.ConfigurationConfig', 'configuration.apps.ConfigurationConfig',
'timetable.apps.TimetableConfig', 'timetable.apps.TimetableConfig',
'review.apps.ReviewConfig', 'review.apps.ReviewConfig',
'comment.apps.CommentConfig',
] ]
EXTERNAL_APPS = [ EXTERNAL_APPS = [

View File

@ -28,4 +28,5 @@ urlpatterns = [
path('location/', include('location.urls')), path('location/', include('location.urls')),
path('main/', include('main.urls')), path('main/', include('main.urls')),
path('translation/', include('translation.urls')), path('translation/', include('translation.urls')),
path('comments/', include('comment.urls.web')),
] ]