Building a Video Sharing Website: Part 4 Adding Comments and Categories to Videos

LegionScript
5 min readSep 24, 2020

--

Video Tutorial

Code on Github

In this tutorial we are going to continue building the video sharing web application. We will add comments to videos and add categories to videos. We will use the categories later on for more features but for now we will just set them up. Let’s start with that first.

Adding Categories to Videos

First, let’s add a category model to our videos/models.py:

class Category(models.Model):
name = models.CharField(max_length=20)
def __str__(self):
return self.name
class Meta:
verbose_name = "Category"
verbose_name_plural = "Categories"

We also need to add a category field to our videos model in the same file, to do this we will add a foreign key field to the video model, the final file should look like this:

from django.db import models
from django.utils import timezone
from django.core.validators import FileExtensionValidator
from django.contrib.auth.models import User
class Video(models.Model):
uploader = models.ForeignKey(User, on_delete=models.CASCADE)
title = models.CharField(max_length=100)
description = models.TextField()
video_file = models.FileField(upload_to='uploads/video_files', validators = [FileExtensionValidator(allowed_extensions=['mp4'])])
thumbnail = models.FileField(upload_to='uploads/thumbnails', validators = [FileExtensionValidator(allowed_extensions=['png', 'jpg', 'jpeg'])])
date_posted = models.DateTimeField(default=timezone.now)
category = models.ForeignKey('Category', on_delete=models.CASCADE)
class Category(models.Model):
name = models.CharField(max_length=20)
def __str__(self):
return self.name
class Meta:
verbose_name = "Category"
verbose_name_plural = "Categories"

Now let’s log into the admin page and add some categories. Let’s register the Category model first in the videos/admin.py file:

from django.contrib import admin
from .models import Video, Category
admin.site.register(Video)
admin.site.register(Category)

Now in the admin page, the Categories model should be showing. All of the categories need to be added here before it will work correctly in the web application. Now with that done, let’s add the field to the CreateVideo view and then everything will be set up. All we will need to do is add ‘category’ to the fields variable:

class CreateVideo(LoginRequiredMixin, CreateView):
model = Video
fields = ['title', 'description', 'video_file', 'thumbnail', 'category']
template_name = 'videos/create_video.html'
def form_valid(self, form):
form.instance.uploader = self.request.user
return super().form_valid(form)
def get_success_url(self):
return reverse('video-detail', kwargs={'pk': self.object.pk})

This is where we are going to stop with the categories for now. We will come back and use this in the future for other features that we are going to add. Now let’s add the ability to post comments to the videos that are posted.

Adding the Ability to Post Comments to Videos

Let’s build the comment data structure in the models.py file:

class Comment(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
video = models.ForeignKey('Video', on_delete=models.CASCADE)
comment = models.TextField()
created_on = models.DateTimeField(auto_now_add=True)
def __str__(self):
return f'Author: {self.author} | Created On: {self.created_on.strftime("%b %d %Y %I:%M %p")}'

In this file, we add a user who is posting the comment, the video the comment is going on, the actual comment and then the date it was created.

Now we need to create an actual form that we will use to post comments. Let’s create a file called forms.py inside of our videos directory. This form will be pretty simple, we just need a comment field that will have a text area widget:

from django import formsclass CommentForm(forms.Form):
comment = forms.CharField(widget=forms.Textarea(
attrs={
"class": "form-control",
"placeholder": "Leave a Comment!",
}))

We will add two attributes, the first being a class that will use bootstrap styles to make it look a little better, and the second one is a placeholder for the field.

Now we need to build the view for this. For the view for this, we will have to rebuild the detail view. We are going to change it from a DetailView to just a View. We will then need to write two methods, a get method and a post method. The get method will run when a get request is handled, and the post method will run when we handle a post request, which will happen when a user posts a comment. Let’s start with the get method:

from django.views import Viewclass DetailVideo(View):

def get(self, request, pk, *args, **kwargs):
video = Video.objects.get(pk=pk)
form = CommentForm()
comments = Comment.objects.filter(video=video).order_by('-created_on')
context = {
'object': video,
'comments': comments,
'form': form
}
return render(request, 'videos/detail_video.html', context)

We need to create a form instance, and then we need to grab all of the comments already posted on the video. We can then pass the video, comments, and form to the template.

Now let’s build the post method:

def post(self, request, pk, *args, **kwargs):
video = Video.objects.get(pk=pk)
form = CommentForm(request.POST)
if form.is_valid():
comment = Comment(
user = self.request.user,
comment = form.cleaned_data['comment'],
video = video
)
comment.save()
comments = Comment.objects.filter(video=video).order_by('-created_on')
context = {
'object': video,
'comments': comments,
'form': form
}
return render(request, 'videos/detail_video.html', context)

We need to create a form instance but now we need to pass the post request into the form. Then we need to check if the form is vaild and if it is, create a comment and save it into the database. Then we will grab all of the comments posted on the video. We can then pass the video, comments, and form into the template.

Now let’s just add some html to show the form and comments and then we will be finished. This will be added to the bottom of detail_video.html:

<div class="row mt-3">
<div class="col-md-8 col-sm-12">
{% if user.is_authenticated %}
<form method="POST">
{% csrf_token %}
<legend class="border-bottom mb-4">Leave a Comment</legend>
{{ form | crispy }}
<button class="btn btn-outline-info btn-block">Post</button>
</form>
{% else %}
<!-- <h5><a href="{% url 'account_login' %}">Sign In To Post a Comment!</a></h5> -->
<a class="btn btn-outline-info btn-block" href="{% url 'account_login' %}">Sign In To Post a Comment!</a>
{% endif %}
</div>
</div>
{% for comment in comments %}
<div class="row mt-3">
<div class="col-md-8 col-sm-12 border-bottom">
<h5>{{ comment.user }} says:</h5>
<p>{{ comment.comment }}</p>
</div>
</div>
{% endfor %}
</div>
{% endblock content %}

All we are doing is adding the form and using crispy forms to make it look better, and then we are looping through all of the comments and display them in rows.

That is where we are going to stop for this tutorial. We will come back and add more features in the future to continue to make this

--

--

No responses yet