From 15f259f0ee746f6433386c76fda930ee1131398c Mon Sep 17 00:00:00 2001 From: andrewlalis Date: Tue, 25 Sep 2018 22:52:38 +0200 Subject: [PATCH] Went on a coding binge and added api support for all new model objects. --- backend/RateMyCourse/urls.py | 3 + backend/db.sqlite3 | Bin 139264 -> 212992 bytes backend/postings/admin.py | 10 ++- backend/postings/api/serializers.py | 60 ++++++++++++- backend/postings/api/urls.py | 24 +++++- backend/postings/api/views.py | 44 +++++++++- .../migrations/0004_auto_20180925_1941.py | 81 ++++++++++++++++++ .../migrations/0005_auto_20180925_2032.py | 18 ++++ backend/postings/models.py | 2 +- 9 files changed, 234 insertions(+), 8 deletions(-) create mode 100644 backend/postings/migrations/0004_auto_20180925_1941.py create mode 100644 backend/postings/migrations/0005_auto_20180925_2032.py diff --git a/backend/RateMyCourse/urls.py b/backend/RateMyCourse/urls.py index 6dc6b61..e6da862 100644 --- a/backend/RateMyCourse/urls.py +++ b/backend/RateMyCourse/urls.py @@ -19,7 +19,10 @@ from django.urls import re_path,path,include from . import views urlpatterns = [ + # / Shows the main index page of the website. path('', views.index, name='index'), + # /universities/1/ Shows the page for a university. + # TODO: add pages for each rateable entity. path('admin/', admin.site.urls), re_path(r'^api/postings/', include(('postings.api.urls','postings'), namespace='api-postings')), ] diff --git a/backend/db.sqlite3 b/backend/db.sqlite3 index dd149749b5ff21502b348ff3073e7b7f4192e4f4..f7ec70412271c104bf80fb3b6a26a472837ef078 100644 GIT binary patch delta 8520 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 B7%Tt) diff --git a/backend/postings/admin.py b/backend/postings/admin.py index 05a8ce7..5961a97 100644 --- a/backend/postings/admin.py +++ b/backend/postings/admin.py @@ -1,6 +1,12 @@ from django.contrib import admin -from .models import UniversityReview +from .models import * # Register your models here. -admin.site.register(UniversityReview) \ No newline at end of file +admin.site.register(UniversityReview) +admin.site.register(Review) +admin.site.register(RateableEntity) +admin.site.register(ReviewHelpfulVote) +admin.site.register(University) +admin.site.register(Professor) +admin.site.register(Course) \ No newline at end of file diff --git a/backend/postings/api/serializers.py b/backend/postings/api/serializers.py index c129084..433639f 100644 --- a/backend/postings/api/serializers.py +++ b/backend/postings/api/serializers.py @@ -1,5 +1,5 @@ from rest_framework import serializers -from postings.models import UniversityReview +from postings.models import * class UniversityReviewSerializer(serializers.ModelSerializer): @@ -16,4 +16,62 @@ class UniversityReviewSerializer(serializers.ModelSerializer): read_only_fields =[ 'pk', 'username' + ] + +# Serializes the generic Review object. +class ReviewSerializer(serializers.ModelSerializer): + class Meta: + model = Review + fields = [ + 'pk', + 'rating', + 'title', + 'content', + 'rateable_entity', + 'created_date', + 'last_updated_date' + ] + read_only_fields = [ + 'pk', + 'created_date', + 'rateable_entity' + ] + +# Serializes Universities. +class UniversitySerializer(serializers.ModelSerializer): + class Meta: + model = University + fields = [ + 'pk', + 'name' + ] + read_only_fields = [ + 'pk' + ] + +# Serializes Courses. +class CourseSerializer(serializers.ModelSerializer): + class Meta: + model = Course + fields = [ + 'pk', + 'name', + 'taught_at_university', + 'professors' + ] + read_only_fields = [ + 'pk' + ] + +# Serializes Professors. +class ProfessorSerializer(serializers.ModelSerializer): + class Meta: + model = Professor + fields = [ + 'pk', + 'name', + 'universities' + ] + read_only_fields = [ + 'pk' ] \ No newline at end of file diff --git a/backend/postings/api/urls.py b/backend/postings/api/urls.py index d310315..1b6e317 100644 --- a/backend/postings/api/urls.py +++ b/backend/postings/api/urls.py @@ -1,11 +1,31 @@ -from .views import UniReviewRudView,UniReviewAPIView -from django.urls import re_path +from .views import * +from django.urls import path, re_path urlpatterns = [ + # /api/postings/reviews/ Lists all review objects. + path('reviews/', ReviewsView.as_view(), name='reviews'), + # /api/postings/reviews/1/ Returns data for one Review. + path('reviews/', ReviewView.as_view(), name='review'), + # /api/postings/universities/ Lists all university objects. + path('universities/', UniversitiesView.as_view(), name='universities'), + # /api/postings/universities/1/ Returns data for one University. + path('universities/', UniversityView.as_view(), name='university'), + + # /api/postings/courses/ Lists all course objects. + path('courses/', CoursesView.as_view(), name='courses'), + # /api/postings/courses/1/ Returns data for one Course. + path('courses/', CourseView.as_view(), name='course'), + + # /api/postings/professors/ Lists all professor objects. + path('professors/', ProfessorsView.as_view(), name='professors'), + # /api/postings/professors/1/ Returns data for one Professor. + path('professors/', ProfessorView.as_view(), name='professor'), + + # Deprecated re_path(r'^(?P\d+)/$', UniReviewRudView.as_view(), name='post-rud'), re_path(r'^$', UniReviewAPIView.as_view(), name='post-create') ] \ No newline at end of file diff --git a/backend/postings/api/views.py b/backend/postings/api/views.py index 8f22d4e..70cf3d6 100644 --- a/backend/postings/api/views.py +++ b/backend/postings/api/views.py @@ -1,6 +1,6 @@ from rest_framework import generics, mixins -from postings.models import UniversityReview -from .serializers import UniversityReviewSerializer +from postings.models import UniversityReview, Review +from .serializers import * from django.db.models import Q @@ -26,3 +26,43 @@ class UniReviewAPIView(mixins.CreateModelMixin, generics.ListAPIView): def post(self,request,*args,**kwargs): return self.create(request, *args, **kwargs) + +# The view for listing all generic Review objects. +class ReviewsView(mixins.CreateModelMixin, generics.ListAPIView): + queryset = Review.objects.all() + serializer_class = ReviewSerializer + +# View for an individual Review object. +class ReviewView(generics.RetrieveUpdateDestroyAPIView): + queryset = Review.objects.all() + serializer_class = ReviewSerializer + +# The view for listing all Universities. +class UniversitiesView(generics.ListAPIView): + serializer_class = UniversitySerializer + queryset = University.objects.all() + +# The view for an individual University. +class UniversityView(generics.RetrieveUpdateDestroyAPIView): + queryset = University.objects.all() + serializer_class = UniversitySerializer + +# The view for listing all Courses. +class CoursesView(generics.ListAPIView): + serializer_class = CourseSerializer + queryset = Course.objects.all() + +# The view for an individual Course. +class CourseView(generics.RetrieveUpdateDestroyAPIView): + queryset = Course.objects.all() + serializer_class = CourseSerializer + +# The view for listing all Professors. +class ProfessorsView(generics.ListAPIView): + queryset = Professor.objects.all() + serializer_class = ProfessorSerializer + +# The view for an individual Professor. +class ProfessorView(generics.RetrieveUpdateDestroyAPIView): + queryset = Professor.objects.all() + serializer_class = ProfessorSerializer \ No newline at end of file diff --git a/backend/postings/migrations/0004_auto_20180925_1941.py b/backend/postings/migrations/0004_auto_20180925_1941.py new file mode 100644 index 0000000..a3a0581 --- /dev/null +++ b/backend/postings/migrations/0004_auto_20180925_1941.py @@ -0,0 +1,81 @@ +# Generated by Django 2.1.1 on 2018-09-25 19:41 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('postings', '0003_universityreview_title'), + ] + + operations = [ + migrations.CreateModel( + name='RateableEntity', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=256)), + ], + ), + migrations.CreateModel( + name='Review', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('rating', models.IntegerField(default=1)), + ('title', models.CharField(max_length=128)), + ('content', models.TextField()), + ('created_date', models.DateTimeField(auto_now_add=True)), + ('last_updated_date', models.DateTimeField(auto_now=True)), + ], + ), + migrations.CreateModel( + name='ReviewHelpfulVote', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('helpful', models.BooleanField()), + ('review', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='postings.Review')), + ], + ), + migrations.CreateModel( + name='Course', + fields=[ + ('rateableentity_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='postings.RateableEntity')), + ], + bases=('postings.rateableentity',), + ), + migrations.CreateModel( + name='Professor', + fields=[ + ('rateableentity_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='postings.RateableEntity')), + ], + bases=('postings.rateableentity',), + ), + migrations.CreateModel( + name='University', + fields=[ + ('rateableentity_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='postings.RateableEntity')), + ], + bases=('postings.rateableentity',), + ), + migrations.AddField( + model_name='review', + name='rateable_entity', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='postings.RateableEntity'), + ), + migrations.AddField( + model_name='professor', + name='university', + field=models.ManyToManyField(to='postings.University'), + ), + migrations.AddField( + model_name='course', + name='professors', + field=models.ManyToManyField(to='postings.Professor'), + ), + migrations.AddField( + model_name='course', + name='taught_at_university', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='postings.University'), + ), + ] diff --git a/backend/postings/migrations/0005_auto_20180925_2032.py b/backend/postings/migrations/0005_auto_20180925_2032.py new file mode 100644 index 0000000..94e10b8 --- /dev/null +++ b/backend/postings/migrations/0005_auto_20180925_2032.py @@ -0,0 +1,18 @@ +# Generated by Django 2.1.1 on 2018-09-25 20:32 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('postings', '0004_auto_20180925_1941'), + ] + + operations = [ + migrations.RenameField( + model_name='professor', + old_name='university', + new_name='universities', + ), + ] diff --git a/backend/postings/models.py b/backend/postings/models.py index bc1038a..1896970 100644 --- a/backend/postings/models.py +++ b/backend/postings/models.py @@ -35,7 +35,7 @@ class University(RateableEntity): # A RateableEntity for professors, who belong to one or more university. class Professor(RateableEntity): # The universities that this professor teaches or has taught at. - university = models.ManyToManyField('postings.University') + universities = models.ManyToManyField('postings.University') # A RateableEntity for courses, which belong to a university, and have one or more professors. class Course(RateableEntity):