An actual minimum viable product, maybe? #11
|
@ -24,6 +24,9 @@ urlpatterns = [
|
||||||
# / routes to index.html
|
# / routes to index.html
|
||||||
path('', views.index, name='homepage'),
|
path('', views.index, name='homepage'),
|
||||||
|
|
||||||
|
# /reviews routes to the endpoint for POSTing new reviews.
|
||||||
|
path('reviews', views.post_review, name='post_review'),
|
||||||
|
|
||||||
# /universities routes to a list of universities.
|
# /universities routes to a list of universities.
|
||||||
path('universities', views.universities, name='universities_list'),
|
path('universities', views.universities, name='universities_list'),
|
||||||
|
|
||||||
|
|
Binary file not shown.
|
@ -0,0 +1,12 @@
|
||||||
|
from django import forms
|
||||||
|
|
||||||
|
# The form for creating a review for any sort of rateable entity.
|
||||||
|
class EntityReviewForm(forms.Form):
|
||||||
|
# The integer rating from 1 to 5.
|
||||||
|
rating = forms.IntegerField(min_value=1, max_value=5)
|
||||||
|
# The title of the review.
|
||||||
|
title = forms.CharField(max_length=128)
|
||||||
|
# The textual content of the review.
|
||||||
|
content = forms.CharField(widget=forms.Textarea)
|
||||||
|
# The id of the entity for which the review is created.
|
||||||
|
entity_id = forms.IntegerField()
|
|
@ -36,6 +36,8 @@ class RateableEntity(models.Model):
|
||||||
rating_sum = 0
|
rating_sum = 0
|
||||||
for review in reviews:
|
for review in reviews:
|
||||||
rating_sum += review.rating
|
rating_sum += review.rating
|
||||||
|
if reviews.count() == 0:
|
||||||
|
return None
|
||||||
return rating_sum / reviews.count()
|
return rating_sum / reviews.count()
|
||||||
|
|
||||||
# Simply returns the name as the string representation.
|
# Simply returns the name as the string representation.
|
||||||
|
|
|
@ -4,11 +4,13 @@
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
<h2>Name: {{ entity.name }}</h2> Average rating: {{ entity.average_rating }}
|
<h2>Name: {{ entity.name }}</h2> Average rating: {{ entity.average_rating|floatformat:"-2" }}
|
||||||
|
|
||||||
|
{# Child templates can redefine this block for displaying data pertaining to that specific entity. #}
|
||||||
{% block entity_info %}
|
{% block entity_info %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
{# This section displays all reviews for a given entity. #}
|
||||||
<section>
|
<section>
|
||||||
<h3>Reviews</h3>
|
<h3>Reviews</h3>
|
||||||
<ul>
|
<ul>
|
||||||
|
@ -21,4 +23,28 @@
|
||||||
</ul>
|
</ul>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
{# This section is where the user can write a review for a particular entity and submit it. #}
|
||||||
|
<section>
|
||||||
|
<h3>Write a Review</h3>
|
||||||
|
<form method="post" action="/reviews">
|
||||||
|
<label for="rating_input">Rating:</label>
|
||||||
|
<input id="rating_input" name="rating" type="number" step="1" min="1" max="5" required>
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<label for="title_input">Title:</label>
|
||||||
|
<input id="title_input" name="title" type="text" required>
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<label for="content_input">Content:</label>
|
||||||
|
<textarea id="content_input" name="content" required></textarea>
|
||||||
|
<br>
|
||||||
|
|
||||||
|
{# The following csrf_token and input fields are hidden values needed for form submission. #}
|
||||||
|
{% csrf_token %}
|
||||||
|
<input type="hidden" name="entity_id" value="{{ entity.pk }}">
|
||||||
|
|
||||||
|
<button type="submit">Submit Review</button>
|
||||||
|
</form>
|
||||||
|
</section>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
|
@ -1,6 +1,7 @@
|
||||||
from django.shortcuts import render
|
from django.shortcuts import render
|
||||||
from django.http import HttpResponse, Http404
|
from django.http import HttpResponse, Http404, HttpResponseBadRequest, HttpResponseRedirect
|
||||||
from postings.models import *
|
from postings.models import *
|
||||||
|
from postings.forms import *
|
||||||
|
|
||||||
# Create your views here.
|
# Create your views here.
|
||||||
|
|
||||||
|
@ -41,4 +42,34 @@ def course_entity(request, course_id):
|
||||||
course = Course.objects.get(pk=course_id)
|
course = Course.objects.get(pk=course_id)
|
||||||
except Course.DoesNotExist:
|
except Course.DoesNotExist:
|
||||||
raise Http404("Course does not exist")
|
raise Http404("Course does not exist")
|
||||||
return render(request, 'postings/entity_pages/course.html', {'entity': course})
|
return render(request, 'postings/entity_pages/course.html', {'entity': course})
|
||||||
|
|
||||||
|
# The view for receiving POST requests for new reviews.
|
||||||
|
def post_review(request):
|
||||||
|
if request.method == 'POST':
|
||||||
|
form = EntityReviewForm(request.POST)
|
||||||
|
if form.is_valid():
|
||||||
|
# Only if the request is a POST and the form is valid do we do anything.
|
||||||
|
rating = form.cleaned_data['rating']
|
||||||
|
title = form.cleaned_data['title']
|
||||||
|
content = form.cleaned_data['content']
|
||||||
|
entity_id = form.cleaned_data['entity_id']
|
||||||
|
entity = RateableEntity.objects.get(pk=entity_id)
|
||||||
|
|
||||||
|
# Creates the new Review object from the posted data.
|
||||||
|
review = Review.objects.create(
|
||||||
|
rating=rating,
|
||||||
|
title=title,
|
||||||
|
content=content,
|
||||||
|
rateable_entity=entity
|
||||||
|
)
|
||||||
|
|
||||||
|
# Send the user back to the entity they were viewing.
|
||||||
|
redirect_path = '/'
|
||||||
|
if entity.entity_type == RateableEntity.UNIVERSITY:
|
||||||
|
redirect_path = '/universities/' + str(entity_id)
|
||||||
|
elif entity.entity_type == RateableEntity.COURSE:
|
||||||
|
redirect_path = '/courses/' + str(entity_id)
|
||||||
|
return HttpResponseRedirect(redirect_path)
|
||||||
|
|
||||||
|
return HttpResponseBadRequest("Bad Request")
|
Loading…
Reference in New Issue