diff --git a/BACKEND/__pycache__/settings.cpython-37.pyc b/BACKEND/__pycache__/settings.cpython-37.pyc index 7727879..653229f 100644 Binary files a/BACKEND/__pycache__/settings.cpython-37.pyc and b/BACKEND/__pycache__/settings.cpython-37.pyc differ diff --git a/BACKEND/__pycache__/urls.cpython-37.pyc b/BACKEND/__pycache__/urls.cpython-37.pyc index 838b0fb..95fd03d 100644 Binary files a/BACKEND/__pycache__/urls.cpython-37.pyc and b/BACKEND/__pycache__/urls.cpython-37.pyc differ diff --git a/BACKEND/settings.py b/BACKEND/settings.py index 87b88e9..fe4083e 100644 --- a/BACKEND/settings.py +++ b/BACKEND/settings.py @@ -2,6 +2,7 @@ import datetime import json import django_heroku +import socket CORS_ORIGIN_WHITELIST = [ "http://localhost:4200", @@ -14,9 +15,15 @@ # SECURITY WARNING: keep the secret key used in production secret! SECRET_KEY = "eko5y90dv=o)+-h-#hlk(is4&bbsq#1au(*f*kmgyd618d_mg4" # SECURITY WARNING: don't run with debug turned on in production! -DEBUG = True -ALLOWED_HOSTS = [] +if socket.gethostname() == "server_name": + DEBUG = False + ALLOWED_HOSTS = [".herokuapp.com",] +else: + DEBUG = True + ALLOWED_HOSTS = ["localhost", "127.0.0.1",] + + AUTH_USER_MODEL = 'accounts.User' diff --git a/BACKEND/urls.py b/BACKEND/urls.py index cbba441..c9cdf06 100644 --- a/BACKEND/urls.py +++ b/BACKEND/urls.py @@ -25,7 +25,7 @@ path('admin/', admin.site.urls), path('auth/', include('accounts.urls')), path('essays/', include('Essay.urls')), - path('essays/reviews/', include('EssayReviews.urls')), + path('essaysreviews/', include('EssayReviews.urls')), path('contact-us/', include('contacts.urls')), path('waiting-list/', include('main.urls')), #path('swagger(?P\.json|\.yaml)$', schema_view.without_ui(cache_timeout=0), name='schema-json'), diff --git a/Essay/__pycache__/models.cpython-37.pyc b/Essay/__pycache__/models.cpython-37.pyc index 933604a..3052067 100644 Binary files a/Essay/__pycache__/models.cpython-37.pyc and b/Essay/__pycache__/models.cpython-37.pyc differ diff --git a/Essay/__pycache__/permission.cpython-37.pyc b/Essay/__pycache__/permission.cpython-37.pyc index 8a7a915..e255c0c 100644 Binary files a/Essay/__pycache__/permission.cpython-37.pyc and b/Essay/__pycache__/permission.cpython-37.pyc differ diff --git a/Essay/__pycache__/serializers.cpython-37.pyc b/Essay/__pycache__/serializers.cpython-37.pyc index c21730d..c9f11db 100644 Binary files a/Essay/__pycache__/serializers.cpython-37.pyc and b/Essay/__pycache__/serializers.cpython-37.pyc differ diff --git a/Essay/__pycache__/urls.cpython-37.pyc b/Essay/__pycache__/urls.cpython-37.pyc index 3b63c43..b980aeb 100644 Binary files a/Essay/__pycache__/urls.cpython-37.pyc and b/Essay/__pycache__/urls.cpython-37.pyc differ diff --git a/Essay/__pycache__/views.cpython-37.pyc b/Essay/__pycache__/views.cpython-37.pyc index a44b912..df3c1f0 100644 Binary files a/Essay/__pycache__/views.cpython-37.pyc and b/Essay/__pycache__/views.cpython-37.pyc differ diff --git a/Essay/migrations/0001_initial.py b/Essay/migrations/0001_initial.py index 2991f5d..0dff8d7 100644 --- a/Essay/migrations/0001_initial.py +++ b/Essay/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 3.0.14 on 2022-03-13 21:54 +# Generated by Django 3.0.14 on 2022-03-21 14:53 from django.conf import settings from django.db import migrations, models @@ -19,10 +19,15 @@ class Migration(migrations.Migration): fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('Title', models.TextField(max_length=512)), - ('Topic', models.CharField(choices=[('Art', 'Art'), ('Anatomy', 'Anatomy'), ('Biology', 'Biology'), ('Blockchain', 'Blockchain'), ('Business', 'Business'), ('Comedy', 'Comedy'), ('Communication', 'Communication'), ('Design', 'Design'), ('Education', 'Education'), ('Engineering', 'Engineering'), ('Finance', 'Finance'), ('Health', 'Health'), ('History', 'History'), ('Games', 'Games'), ('Law', 'Law'), ('Linguistics', 'Linguistics'), ('Literature', 'Literature'), ('Politics', 'Politics'), ('Philosophy', 'Philosophy'), ('Religion', 'Religion'), ('Sciences', 'Sciences'), ('Others', 'Others')], max_length=255)), + ('Topic', models.CharField(choices=[('Art', 'Art'), ('Anatomy', 'Anatomy'), ('Biology', 'Biology'), ('Blockchain', 'Blockchain'), ('Business', 'Business'), ('Comedy', 'Comedy'), ('Communication', 'Communication'), ('Design', 'Design'), ('Education', 'Education'), ('Engineering', 'Engineering'), ('Finance', 'Finance'), ('Health', 'Health'), ('History', 'History'), ('Games', 'Games'), ('Law', 'Law'), ('Linguistics', 'Linguistics'), ('Literature', 'Literature'), ('Politics', 'Politics'), ('Philosophy', 'Philosophy'), ('Religion', 'Religion'), ('Sciences', 'Sciences'), ('Others', 'Others')], max_length=50)), + ('EssayContent', models.TextField(default=False)), ('Created_at', models.DateTimeField(auto_now=True)), + ('No_of_Reviewer', models.IntegerField(default=2)), ('TokenCost', models.IntegerField()), ('Author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), ], + options={ + 'ordering': ['-Created_at'], + }, ), ] diff --git a/Essay/migrations/0002_auto_20220315_1025.py b/Essay/migrations/0002_auto_20220315_1025.py deleted file mode 100644 index 5e7d8d6..0000000 --- a/Essay/migrations/0002_auto_20220315_1025.py +++ /dev/null @@ -1,22 +0,0 @@ -# Generated by Django 3.0.14 on 2022-03-15 09:25 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('Essay', '0001_initial'), - ] - - operations = [ - migrations.AlterModelOptions( - name='essay', - options={'ordering': ['-Created_at']}, - ), - migrations.AddField( - model_name='essay', - name='EssayContent', - field=models.TextField(default=False), - ), - ] diff --git a/Essay/migrations/0002_auto_20220323_1129.py b/Essay/migrations/0002_auto_20220323_1129.py new file mode 100644 index 0000000..9554e32 --- /dev/null +++ b/Essay/migrations/0002_auto_20220323_1129.py @@ -0,0 +1,52 @@ +# Generated by Django 3.0.14 on 2022-03-23 11:29 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('Essay', '0001_initial'), + ] + + operations = [ + migrations.RenameField( + model_name='essay', + old_name='No_of_Reviewer', + new_name='No_of_Reviewers', + ), + migrations.RenameField( + model_name='essay', + old_name='Author', + new_name='user', + ), + migrations.RemoveField( + model_name='essay', + name='Title', + ), + migrations.AddField( + model_name='essay', + name='draft', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='essay', + name='read_time', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='essay', + name='slug', + field=models.SlugField(null=True, unique=True), + ), + migrations.AddField( + model_name='essay', + name='title', + field=models.TextField(max_length=50, null=True), + ), + migrations.AlterField( + model_name='essay', + name='EssayContent', + field=models.TextField(null=True), + ), + ] diff --git a/Essay/migrations/__pycache__/0001_initial.cpython-37.pyc b/Essay/migrations/__pycache__/0001_initial.cpython-37.pyc index 7a45c53..2e28f8c 100644 Binary files a/Essay/migrations/__pycache__/0001_initial.cpython-37.pyc and b/Essay/migrations/__pycache__/0001_initial.cpython-37.pyc differ diff --git a/Essay/models.py b/Essay/models.py index 948d281..4763f92 100644 --- a/Essay/models.py +++ b/Essay/models.py @@ -1,5 +1,28 @@ from django.db import models +from django.utils import timezone +from django.contrib.contenttypes.models import ContentType +from django.utils.text import slugify +from django.utils.safestring import mark_safe +from django.urls import reverse +from django.db.models.signals import pre_save +from django.conf import settings + from accounts.models import User +from .utils import count_words + +from markdown_deux import markdown + +class EssayManager(models.Manager): + + def active(self, *args, **kwargs): + return super(EssayManager, self).filter(draft=False).filter(publish_lte =timezone.now()) + +def upload_location(instance, filename): + EssayModel = instance.__class__ + new_id = EssayModel.objects.order_by("id").last().id + 1 + + return "%s/%s" %(new_id, filename) + class Essay(models.Model): @@ -27,17 +50,70 @@ class Essay(models.Model): ('Sciences', 'Sciences'), ('Others', 'Others'), ] - Author = models.ForeignKey(to = User, on_delete=models.CASCADE) - Title = models.TextField(max_length = 512) + + user = models.ForeignKey(to = User, on_delete=models.CASCADE) + title = models.TextField(max_length = 50, null=True) + slug = models.SlugField(unique= True, null=True) Topic = models.CharField(choices = CATEGORY_OPTIONS, max_length=50) - EssayContent = models.TextField(default=False) - Created_at = models.DateTimeField(auto_now=True) + draft = models.BooleanField(default=False) + EssayContent = models.TextField(null=True) + Created_at = models.DateTimeField(auto_now=True, auto_now_add= False) + read_time = models.IntegerField(default=0) + No_of_Reviewers = models.IntegerField(default = 2) TokenCost = models.IntegerField() + #UserRating = models.PositiveIntegerField(default= 0) + #timestamp = models.DateTimeField( auto_now_add = True, default = 0) + + objects = EssayManager() class Meta: ordering = ["-Created_at"] + def __unicode__(self): + return self.title + def __str__(self): - return str(self.Author)+" is created the **"+str(self.Title)+"** Essay" + return str(self.user)+" is created the **"+str(self.title)+"** Essay" + + def get_absolute_url(self): + return reverse('essays:essay-detail', kwargs={"slug": self.slug}) + + def get_api_url(self): + return reverse('essays-api:essay-detail', kwargs={"slug": self.slug}) + + def get_markdown(self): + EssayContent = self.EssayContent + markdown_text = markdown(EssayContent) + return mark_safe(markdown_text) + + @property + def get_content_type(self): + instance = self + content_type = ContentType.objects.get_for_model(instance.__class__) + return content_type + +def create_slug(instance, new_slug=None): + slug = slugify(instance.title) + if new_slug is not None: + slug = new_slug + qs = Essay.objects.filter(slug=slug).order_by("-id") + exists = qs.exists() + + if exists: + new_slug = "%s-%s" %(slug, qs.first().id) + return create_slug(instance, new_slug=new_slug) + return slug + +def pre_save_essay_receiver(sender, instance, *args, **kwargs): + if not instance.slug: + instance.slug = create_slug(instance) + + if instance.EssayContent: + html_string = instance.get_markdown() + words_count = count_words(html_string) + instance.count_words = words_count + if instance.count_words < 100: + return ("Minimum word count must be 100") +pre_save.connect(pre_save_essay_receiver, sender= Essay) diff --git a/Essay/pagination.py b/Essay/pagination.py new file mode 100644 index 0000000..22d1e4c --- /dev/null +++ b/Essay/pagination.py @@ -0,0 +1,11 @@ +from rest_framework.pagination import ( + LimitOffsetPagination, + PageNumberPagination +) + +class EssayLimitOffsetPagination(LimitOffsetPagination): + default_limit = 5 + max_limit = 10, + +class EssayPageNumberPagination(PageNumberPagination): + page_size = 2 diff --git a/Essay/permission.py b/Essay/permission.py index c9e1619..51860f0 100644 --- a/Essay/permission.py +++ b/Essay/permission.py @@ -2,7 +2,7 @@ from rest_framework import permissions -class IsAuthor(permissions.BasePermission): +class Isuser(permissions.BasePermission): def has_object_permission(self, request, view, obj): - return obj.Author == request.user \ No newline at end of file + return obj.user == request.user \ No newline at end of file diff --git a/Essay/serializers.py b/Essay/serializers.py index 3593de4..ba5204c 100644 --- a/Essay/serializers.py +++ b/Essay/serializers.py @@ -1,18 +1,84 @@ from rest_framework import serializers +from EssayReviews.serializers import EssayReviewListSerializer +from EssayReviews.models import EssayReview + + from .models import Essay -class EssaySerializer(serializers.ModelSerializer): +class EssayCreateSerializer(serializers.ModelSerializer): + class Meta: + + model = Essay + + fields = [ + #'id', + 'title', + 'user', + #'slug', + 'Topic', + 'EssayContent', + 'Created_at', + 'No_of_Reviewers', + 'TokenCost', + #'UserRating', + + ] + +class EssayListSerializer(serializers.ModelSerializer): + + url = serializers.HyperlinkedIdentityField( + view_name=':essay-detail', + lookup_field = 'id' + ) + user = serializers.SerializerMethodField() class Meta: model = Essay fields = [ 'id', + 'url', + 'user', + 'title', + 'slug', + 'Topic', 'EssayContent', 'Created_at', + "No_of_Reviewers", 'TokenCost', +] + + def get_user(self, obj): + return str(obj.user.username) + +class EssayDetailSerializer(serializers.ModelSerializer): + + essayreviews = serializers.SerializerMethodField() + + class Meta: + + model = Essay + + fields = [ + 'id', + 'user', + 'title', + 'slug', 'Topic', - 'Title' - ] \ No newline at end of file + 'EssayContent', + 'Created_at', + 'TokenCost', + 'No_of_Reviewers', + #'UserRating', + 'essayreviews', + + ] + def get_essayreviews(self, obj): + # content_type = obj.get_content_type + # object_id = obj.id + r_qs = EssayReview.objects.filter_by_instance(obj) + essayreviews = EssayReviewListSerializer(r_qs, many = True).data + return essayreviews + diff --git a/Essay/urls.py b/Essay/urls.py index 7e1c589..1610eff 100644 --- a/Essay/urls.py +++ b/Essay/urls.py @@ -1,8 +1,16 @@ from django.urls import path -from . import views +from .views import ( + EssayCreateAPIView, + EssayDeleteAPIView, + EssayDetailAPIView, + EssayListAPIView + +) urlpatterns = [ - path('', views.EssayListAPIView.as_view(), name = "essays"), - path('', views.EssayDetailAPIView.as_view(), name = "essay"), + path('', EssayListAPIView.as_view(), name = "essays"), + path('', EssayDetailAPIView.as_view(), name = "essay-detail"), + path('/create', EssayCreateAPIView.as_view(), name='create-essay'), + path('/delete', EssayDeleteAPIView.as_view(), name = 'delete-essay'), ] diff --git a/Essay/utils.py b/Essay/utils.py new file mode 100644 index 0000000..fba08e1 --- /dev/null +++ b/Essay/utils.py @@ -0,0 +1,13 @@ +import math +from django.utils.html import strip_tags + + +def count_words(html_string): + + word_string = strip_tags(html_string) + count = len(word_string.split()) + return count + +def average_user_rating(): + + pass \ No newline at end of file diff --git a/Essay/views.py b/Essay/views.py index 157d1b6..bad5882 100644 --- a/Essay/views.py +++ b/Essay/views.py @@ -1,35 +1,74 @@ from django.shortcuts import render -from rest_framework.generics import ListCreateAPIView, RetrieveUpdateDestroyAPIView +from rest_framework.generics import ( + #ListCreateAPIView, + RetrieveAPIView, + CreateAPIView, + DestroyAPIView, + ListAPIView + +) + +from rest_framework.filters import ( + SearchFilter, + OrderingFilter +) + from rest_framework import permissions -from .serializers import EssaySerializer +from .serializers import ( + EssayListSerializer, + EssayDetailSerializer, + EssayCreateSerializer, +) + from .models import Essay -from .permission import IsAuthor +from .permission import Isuser +from .pagination import EssayLimitOffsetPagination, EssayPageNumberPagination -class EssayListAPIView(ListCreateAPIView): +class EssayListAPIView(ListAPIView): + serializer_class = EssayListSerializer + queryset = Essay.objects.all() + filter_backends = [SearchFilter, OrderingFilter] + search_fields = ['title', 'user', 'Topic'] + pagination_class = EssayLimitOffsetPagination + permission_classes = (permissions.IsAuthenticated, permissions.IsAdminUser,) + + def get_queryset(self): + return self.queryset.filter(user=self.request.user) + - serializer_class = EssaySerializer +class EssayCreateAPIView(CreateAPIView): + serializer_class = EssayCreateSerializer queryset = Essay.objects.all() - permission_classes = (permissions.IsAuthenticated,) + lookup_field = 'id' + + permission_classes = (permissions.IsAuthenticated, permissions.IsAdminUser,) def perform_create(self, serializer): - return serializer.save(Author=self.request.user) + return serializer.save(user=self.request.user) def get_queryset(self): - return self.queryset.filter(Author=self.request.user) + return self.queryset.filter(user=self.request.user) + +class EssayDeleteAPIView(DestroyAPIView): + serializer_class = EssayDetailSerializer + queryset = Essay.objects.all() + lookup_field = 'id' + + permission_classes = (permissions.IsAuthenticated,) -class EssayDetailAPIView(RetrieveUpdateDestroyAPIView): - serializer_class = EssaySerializer +class EssayDetailAPIView(RetrieveAPIView): + serializer_class = EssayDetailSerializer queryset = Essay.objects.all() - permission_classes = (permissions.IsAuthenticated, IsAuthor) + permission_classes = (permissions.IsAuthenticated, Isuser) lookup_fields = "id" # def perform_create(self, serializer): - # return serializer.save(Author=self.request.user) + # return serializer.save(user=self.request.user) def get_queryset(self): - return self.queryset.filter(Author=self.request.user) + return self.queryset.filter(user=self.request.user) diff --git a/EssayReviews/__pycache__/models.cpython-37.pyc b/EssayReviews/__pycache__/models.cpython-37.pyc index 2a3c39e..2eed038 100644 Binary files a/EssayReviews/__pycache__/models.cpython-37.pyc and b/EssayReviews/__pycache__/models.cpython-37.pyc differ diff --git a/EssayReviews/__pycache__/permissions.cpython-37.pyc b/EssayReviews/__pycache__/permissions.cpython-37.pyc index 4314ff0..f08ddf4 100644 Binary files a/EssayReviews/__pycache__/permissions.cpython-37.pyc and b/EssayReviews/__pycache__/permissions.cpython-37.pyc differ diff --git a/EssayReviews/__pycache__/serializers.cpython-37.pyc b/EssayReviews/__pycache__/serializers.cpython-37.pyc index 894726e..ea4dd51 100644 Binary files a/EssayReviews/__pycache__/serializers.cpython-37.pyc and b/EssayReviews/__pycache__/serializers.cpython-37.pyc differ diff --git a/EssayReviews/__pycache__/urls.cpython-37.pyc b/EssayReviews/__pycache__/urls.cpython-37.pyc index 27c0d60..277be7b 100644 Binary files a/EssayReviews/__pycache__/urls.cpython-37.pyc and b/EssayReviews/__pycache__/urls.cpython-37.pyc differ diff --git a/EssayReviews/__pycache__/views.cpython-37.pyc b/EssayReviews/__pycache__/views.cpython-37.pyc index 52877e0..7938afb 100644 Binary files a/EssayReviews/__pycache__/views.cpython-37.pyc and b/EssayReviews/__pycache__/views.cpython-37.pyc differ diff --git a/EssayReviews/migrations/0002_auto_20220321_1121.py b/EssayReviews/migrations/0002_auto_20220321_1121.py new file mode 100644 index 0000000..7ad6639 --- /dev/null +++ b/EssayReviews/migrations/0002_auto_20220321_1121.py @@ -0,0 +1,23 @@ +# Generated by Django 3.0.14 on 2022-03-21 11:21 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('EssayReviews', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='essayreview', + name='Title', + field=models.TextField(max_length=50), + ), + migrations.AlterField( + model_name='essayreview', + name='Topic', + field=models.CharField(choices=[('Art', 'Art'), ('Anatomy', 'Anatomy'), ('Blockchain', 'Blockchain'), ('Business', 'Business'), ('Comedy', 'Comedy'), ('Communication', 'Communication'), ('Design', 'Design'), ('Education', 'Education'), ('Engineering', 'Engineering'), ('Finance', 'Finance'), ('Health', 'Health'), ('History', 'History'), ('Games', 'Games'), ('Law', 'Law'), ('Linguistics', 'Linguistics'), ('Literature', 'Literature'), ('Politics', 'Politics'), ('Philosophy', 'Philosophy'), ('Religion', 'Religion'), ('Sciences', 'Sciences'), ('Others', 'Others')], max_length=255), + ), + ] diff --git a/EssayReviews/migrations/0003_auto_20220323_1129.py b/EssayReviews/migrations/0003_auto_20220323_1129.py new file mode 100644 index 0000000..7abc6d5 --- /dev/null +++ b/EssayReviews/migrations/0003_auto_20220323_1129.py @@ -0,0 +1,48 @@ +# Generated by Django 3.0.14 on 2022-03-23 11:29 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('contenttypes', '0002_remove_content_type_name'), + ('EssayReviews', '0002_auto_20220321_1121'), + ] + + operations = [ + migrations.RenameField( + model_name='essayreview', + old_name='Reviewer', + new_name='user', + ), + migrations.RemoveField( + model_name='essayreview', + name='Title', + ), + migrations.RemoveField( + model_name='essayreview', + name='Topic', + ), + migrations.AddField( + model_name='essayreview', + name='content_type', + field=models.ForeignKey(default=False, on_delete=django.db.models.deletion.CASCADE, to='contenttypes.ContentType'), + ), + migrations.AddField( + model_name='essayreview', + name='object_id', + field=models.PositiveIntegerField(default=0), + ), + migrations.AddField( + model_name='essayreview', + name='parent', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='EssayReviews.EssayReview'), + ), + migrations.AlterField( + model_name='essayreview', + name='EssayReviewContent', + field=models.TextField(null=True), + ), + ] diff --git a/EssayReviews/models.py b/EssayReviews/models.py index 2d13ea4..6b65ad2 100644 --- a/EssayReviews/models.py +++ b/EssayReviews/models.py @@ -1,11 +1,50 @@ -from django.db import models +from __future__ import unicode_literals +from audioop import reverse + from accounts.models import User +from django.conf import settings +from django.db import models +from django.contrib.contenttypes.fields import GenericForeignKey +from django.contrib.contenttypes.models import ContentType + + +class EssayReviewManager(models.Manager): + def all(self): + qs = super(EssayReviewManager, self).filter(parent = None) + return qs + + def filter_by_instance(self, instance): + content_type = ContentType.objects.get_for_model(instance.__class__) + obj_id = instance.id + qs = super(EssayReviewManager, self).filter(content_type=content_type, object_id = obj_id).filter(parent=None) + return qs + + def create_by_model_type(self, model_type, slug, EssayReviewContent, user, parent_obj=None): + model_qs = ContentType.objects.filter(model = model_type) + if model_qs.exists(): #or model_qs.count() != 1: + SomeModel = model_qs.first().model_class() + obj_qs = SomeModel.objects.filter(slug, self.slug) + if obj_qs.exists() and obj_qs.count() == 1: + instance = self.model() + instance.EssayReviewContent = EssayReviewContent + instance.user = user + instance.content_type = model_qs.first() + instance.object_id = obj_qs.first().id + if parent_obj: + instance.parent= parent_obj + instance.save() + return instance + return None + + + class EssayReview(models.Model): CATEGORY_OPTIONS = [ ('Art', 'Art'), ('Anatomy', 'Anatomy'), + ('Biology', 'Biology'), ('Blockchain', 'Blockchain'), ('Business', 'Business'), ('Comedy', 'Comedy'), @@ -26,16 +65,34 @@ class EssayReview(models.Model): ('Sciences', 'Sciences'), ('Others', 'Others'), ] - - Reviewer = models.ForeignKey(to = User, on_delete=models.CASCADE) - Title = models.TextField(max_length = 50) - Topic = models.CharField(choices = CATEGORY_OPTIONS, max_length=255) - EssayReviewContent = models.TextField(default=False) + + user = models.ForeignKey(to = User, on_delete=models.CASCADE) + #Title = models.TextField(max_length = 50) + object_id = models.PositiveIntegerField(default = 0) + parent = models.ForeignKey("self", null=True, blank=True, on_delete=models.CASCADE) + content_type = models.ForeignKey(ContentType,default=False, on_delete=models.CASCADE) + content_object = GenericForeignKey('content_type', 'object_id') + EssayReviewContent = models.TextField(null = True) submitted_at = models.DateTimeField(auto_now=True) + #timestamp = models.DateTimeField(auto_now_add= True) + + #objects = class Meta: ordering = ['-submitted_at'] + + def __unicode__(self): + return str(self.user.username) def __str__(self): - return str(self.Reviewer)+" reviewed an Essay" \ No newline at end of file + return str(self.user)+" reviewed an Essay" + + def get_delete_url(self): + return reverse("EssayReviews:delete", kwargs={'id': self.id}) + + @property + def is_parent(self): + if self.parent is not None: + return False + return True diff --git a/EssayReviews/permissions.py b/EssayReviews/permissions.py index 17bc5b5..51860f0 100644 --- a/EssayReviews/permissions.py +++ b/EssayReviews/permissions.py @@ -2,7 +2,7 @@ from rest_framework import permissions -class IsReviewer(permissions.BasePermission): +class Isuser(permissions.BasePermission): def has_object_permission(self, request, view, obj): - return obj.Reviewer == request.user \ No newline at end of file + return obj.user == request.user \ No newline at end of file diff --git a/EssayReviews/serializers.py b/EssayReviews/serializers.py index a04bdb6..4c8e5ba 100644 --- a/EssayReviews/serializers.py +++ b/EssayReviews/serializers.py @@ -1,15 +1,132 @@ -from rest_framework import serializers +from rest_framework.serializers import ( + ModelSerializer, HyperlinkedIdentityField, + SerializerMethodField, + ValidationError +) + +from django.contrib.auth import get_user_model +from django.contrib.contenttypes.models import ContentType from .models import EssayReview -class EssayReviewSerializer(serializers.ModelSerializer): +User = get_user_model() +def create_essaysreviews_serializer(model_type='post', slug =None, parent_id=None, user=None): + class EssayReviewCreateSerializer(ModelSerializer): + + class Meta: + model = EssayReview + fields = [ + 'id', + #'object_id', + #'content_type', + #'content_object', + #'parent', + 'EssayReviewContent', + 'submitted_at', + #'Title' + ] + + def __init__(self, *args, **kwargs): + self.model_type = model_type + self.slug= slug + self.parent_obj = None + if parent_id: + parent_qs = EssayReview.objects.filter(id=parent_id) + if parent_qs.exists() and parent_qs.count()==1: + self.parent_obj = parent_qs.first() + return super(EssayReviewCreateSerializer, self).__init__(*args, **kwargs) + + def validate(self, data): + model_type = self.model_type + model_qs = ContentType.objects.filter(model = model_type) + if not model_qs.exists() or model_qs.count() != 1: + raise ValidationError("This is not a valid content type") + + SomeModel = model_qs.first().model_class() + obj_qs = SomeModel.objects.filter(slug = self.slug) + if not obj_qs.exists() or obj_qs.count() != 1: + raise ValidationError("This is not a slug for this content type") + return data + + def create(self, validated_data): + EssayReviewContent = validated_data.get("EssayReviewContent") + if user: + main_user = user + else: + main_user = User.objects.all().first() + #user = User.objects.all().first() + + model_type = self.model_type + slug = self.slug + parent_obj = self.parent_obj + essayreview = EssayReview.objects.create_by_model_type( + model_type, slug, EssayReviewContent, main_user, + parent_obj= parent_obj, + ) + return essayreview + + return EssayReviewCreateSerializer + +class EssayReviewListSerializer(ModelSerializer): + url = HyperlinkedIdentityField( + view_name = 'EssayReviews-api:essays-reviews-details', + ) + reviews_count = SerializerMethodField() + class Meta: + model = EssayReview + fields = [ + 'url', + 'id', + #'object_id', + #'content_type', + #'content_object', + # 'parent', + 'EssayReviewContent', + 'reviews_count', + 'submitted_at', + #'Title' + ] + + def get_reviews_count(self, obj): + if obj.is_parent: + return obj.children().count() + return 0 +class EssayReviewDetailSerializer(ModelSerializer): + user = UserDetail + reviews_count = SerializerMethodField() + content_object_url = SerializerMethodField() + reviews = SerializerMethodField() class Meta: model = EssayReview fields = [ 'id', + #'object_id', + #'content_type', + #'content_object', + #'parent', 'EssayReviewContent', + 'reviews_count', 'submitted_at', - 'Topic', - 'Title' - ] \ No newline at end of file + 'content_object_url', + #'Title' + ] + + read_only_fields = [ + #'object_id', + #'content_type', + 'reviews_count', + 'reviews', + + ] + + def get_content_object_url(self, obj): + try: + return obj.content_object.get_api_url() + except: + return None + + def get_reviews_count(self, obj): + if obj.is_parent: + return obj.children().count() + return 0 diff --git a/EssayReviews/urls.py b/EssayReviews/urls.py index bd41b25..b2c768d 100644 --- a/EssayReviews/urls.py +++ b/EssayReviews/urls.py @@ -1,8 +1,14 @@ from django.urls import path -from . import views +from .views import ( + EssayReviewListAPIView, + EssayReviewDetailAPIView, + EssayReviewCreateAPIView +) urlpatterns = [ - path('', views.EssayReviewListAPIView.as_view(), name = "essays reviews"), - path('', views.EssayReviewDetailAPIView.as_view(), name = "essay reviews"), + path('', EssayReviewListAPIView.as_view(), name = 'essay-reviews-list'), + path('create/', EssayReviewCreateAPIView.as_view(), name = 'essay-reviews-create'), + path('/', EssayReviewDetailAPIView.as_view(), name = "essays-reviews-details"), + #path('/edit', EssayReviewDetailAPIView.as_view(), name = "essay reviews-edit"),#delete ] diff --git a/EssayReviews/views.py b/EssayReviews/views.py index d45675a..6501db4 100644 --- a/EssayReviews/views.py +++ b/EssayReviews/views.py @@ -1,35 +1,84 @@ from django.shortcuts import render +from django.db.models import Q -from rest_framework.generics import ListCreateAPIView, RetrieveUpdateDestroyAPIView +from rest_framework.generics import ( + #ListCreateAPIView, + RetrieveAPIView, + CreateAPIView, + DestroyAPIView, + ListAPIView +) + +from rest_framework.filters import ( + SearchFilter, + OrderingFilter +) + +from rest_framework.mixins import DestroyModelMixin, UpdateModelMixin from rest_framework import permissions -from .serializers import EssayReviewSerializer -from .models import EssayReview -from .permissions import IsReviewer +from EssayReviews.permissions import Isuser -class EssayReviewListAPIView(ListCreateAPIView): +from .serializers import ( + EssayReviewListSerializer, + EssayReviewDetailSerializer, + create_essaysreviews_serializer, +) - serializer_class = EssayReviewSerializer - queryset = EssayReview.objects.all() - permission_classes = (permissions.IsAuthenticated,) +from .models import EssayReview + +from Essay.permission import Isuser +from Essay.pagination import EssayLimitOffsetPagination, EssayPageNumberPagination - def perform_create(self, serializer): - return serializer.save(Reviewer=self.request.user) +class EssayReviewListAPIView(ListAPIView): + serializer_class = EssayReviewListSerializer + #queryset = EssayReview.objects.all() + filter_backends = [SearchFilter, OrderingFilter] + search_fields = ['EssayReview', 'user__first_name'] + pagination_class = EssayLimitOffsetPagination + permission_classes = (permissions.IsAuthenticated, permissions.IsAdminUser,) - def get_queryset(self): - return self.queryset.filter(Reviewer=self.request.user) + def get_queryset(self, *args, **kwargs): + queryset_list = EssayReview.objects.filter(id__gte=0) + query = self.request.GET.get('q') + if query: + queryset_list = queryset_list.filter( + Q(content__icontains=query) | + Q(user__first_name_icontains=query) | + Q(user__last_name_icontains=query) + ).distinct() + return queryset_list -class EssayReviewDetailAPIView(RetrieveUpdateDestroyAPIView): + #return self.queryset.filter(user=self.request.user) + - serializer_class = EssayReviewSerializer +class EssayReviewCreateAPIView(CreateAPIView): + #serializer_class = EssayReviewCreateSerializer queryset = EssayReview.objects.all() - permission_classes = (permissions.IsAuthenticated, IsReviewer) - lookup_fields = "id" + lookup_field = 'slug' + permission_classes = [permissions.IsAuthenticated] + + def get_serializer_class(self): + model_type = self.request.GET.get('type') + slug = self.request.GET.get('slug') + parent_id = self.request.GET.get('parent_id', None) + return create_essaysreviews_serializer( + model_type=model_type, + slug =slug, + parent_id=parent_id, + user = self.request.user + ) + #super().get_serializer_class() + +class EssayReviewDetailAPIView(DestroyModelMixin, UpdateModelMixin, RetrieveAPIView): + queryset = EssayReview.objects.filter(id__gte=0) + serializer_class = EssayReviewDetailSerializer + permission_classes = (permissions.IsAuthenticated, Isuser) - # def perform_create(self, serializer): - # return serializer.save(Reviewer=self.request.user) + def put(self, request, *args, **kwargs): + return self.update(request, *args, **kwargs) - def get_queryset(self): - return self.queryset.filter(Reviewer=self.request.user) + def delete(self, request, *args, **kwargs): + return self.destroy(request, *args, **kwargs) diff --git a/accounts/__pycache__/models.cpython-37.pyc b/accounts/__pycache__/models.cpython-37.pyc index 76bd7dc..b5dfa94 100644 Binary files a/accounts/__pycache__/models.cpython-37.pyc and b/accounts/__pycache__/models.cpython-37.pyc differ diff --git a/accounts/models.py b/accounts/models.py index 5716940..dc9b4a2 100644 --- a/accounts/models.py +++ b/accounts/models.py @@ -46,6 +46,7 @@ class User(AbstractBaseUser, PermissionsMixin): is_staff = models.BooleanField(default=False) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) + USERNAME_FIELD = 'email' REQUIRED_FIELDS = ['username', 'first_name', 'last_name'] diff --git a/db.sqlite3 b/db.sqlite3 index af8df62..c8d912a 100644 Binary files a/db.sqlite3 and b/db.sqlite3 differ diff --git a/main/__pycache__/models.cpython-37.pyc b/main/__pycache__/models.cpython-37.pyc index f60f7ff..339c810 100644 Binary files a/main/__pycache__/models.cpython-37.pyc and b/main/__pycache__/models.cpython-37.pyc differ diff --git a/main/migrations/0005_auto_20220321_1121.py b/main/migrations/0005_auto_20220321_1121.py new file mode 100644 index 0000000..8a47964 --- /dev/null +++ b/main/migrations/0005_auto_20220321_1121.py @@ -0,0 +1,18 @@ +# Generated by Django 3.0.14 on 2022-03-21 11:21 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('main', '0004_delete_contact_us'), + ] + + operations = [ + migrations.AlterField( + model_name='waitinglist', + name='name', + field=models.CharField(max_length=100), + ), + ] diff --git a/social_auth/__init__.py b/social_auth/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/social_auth/admin.py b/social_auth/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/social_auth/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/social_auth/apps.py b/social_auth/apps.py new file mode 100644 index 0000000..f6758a6 --- /dev/null +++ b/social_auth/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class SocialAuthConfig(AppConfig): + name = 'social_auth' diff --git a/social_auth/facebook.py b/social_auth/facebook.py new file mode 100644 index 0000000..e69de29 diff --git a/social_auth/migrations/__init__.py b/social_auth/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/social_auth/models.py b/social_auth/models.py new file mode 100644 index 0000000..71a8362 --- /dev/null +++ b/social_auth/models.py @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. diff --git a/social_auth/serializers.py b/social_auth/serializers.py new file mode 100644 index 0000000..236cd38 --- /dev/null +++ b/social_auth/serializers.py @@ -0,0 +1 @@ +from rest_framework import serializers diff --git a/social_auth/tests.py b/social_auth/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/social_auth/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/social_auth/twitterhelper.py b/social_auth/twitterhelper.py new file mode 100644 index 0000000..e69de29 diff --git a/social_auth/urls.py b/social_auth/urls.py new file mode 100644 index 0000000..e69de29 diff --git a/social_auth/views.py b/social_auth/views.py new file mode 100644 index 0000000..2536b37 --- /dev/null +++ b/social_auth/views.py @@ -0,0 +1 @@ +from django.shortcuts import render