Hello Developers,
Do you use Online Video Sharing Website like YouTube or Vimeo?
And how to create websites like them?
Here is the example of Online Video Sharing Website:-
I am providing the source code of this project and give me feedback to this website. In this project , I disabled Deactivate Account section of this project so write a code for this section and send it to me.
On this website User can:-
- Create Account
- Watch Videos after Login
- Subscribe others
- Like the videos
- Commenting them
- See Dashboard where users can analysis their videos.
- Update their Profiles
- Deactivate Account (Write the Code for this section and send it to me)
You have to create a Django Project using this command.
django-admin startproject video_sharing
Create an App in this project
python manage.py startapp main
settings.py
# Application definition
INSTALLED_APPS = [
...
'main', #add your app here
]
STATIC_URL = '/static/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'main/static')
]
# Media Settings
MEDIA_ROOT = 'D:\\django_projects\\video_sharing\\main\\static\\media'
MEDIA_URL = 'media/'
project/urls.py
from django.contrib import admin
from django.urls import path, include
from django.conf import settings
from django.conf.urls.static import static
admin.site.site_header = "Viral Video Admin Panel"
admin.site.site_title = "Viral Video Admin Portal"
admin.site.index_title = "Welcome to Video Viral!"
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('main.urls')),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
main/models.py
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class VideoPost(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
title = models.CharField(max_length=100)
desc = models.TextField()
video_file = models.FileField(upload_to='videos/')
thumbnail = models.ImageField(upload_to='videos/thumbnail/', default='none')
category = models.CharField(max_length=50, default='none')
pub_date = models.DateField(auto_now_add=True)
likes = models.ManyToManyField(User, related_name='likes')
video_views = models.ManyToManyField(User, related_name='video_views')
def __str__(self):
return self.title
class UserData(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
about = models.TextField()
profile_pic = models.ImageField(upload_to='pic/', default='pic/default.jpg')
subscribers = models.ManyToManyField(User, related_name='subscribers')
class Comment(models.Model):
post = models.ForeignKey(VideoPost, on_delete=models.CASCADE)
user = models.ForeignKey(User, on_delete=models.CASCADE)
comment = models.CharField(max_length=300)
def __str__(self):
return self.user.username
main/admin.py
from django.contrib import admin
from .models import VideoPost, Comment, UserData
# Register your models here.
admin.site.register(VideoPost)
admin.site.register(Comment)
admin.site.register(UserData)
Add Models as Tables in Django Database like this,
python manage.py makemigrations
python manage.py migrate
You have to create a super user to access Database like this,
python manage.py createsuperuser
main/urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.home, name='home'),
path('video/<int:video_id>/', views.watch_video, name='watch_video'),
path('video/add_comment/', views.add_comment, name='add_comment'),
path('video/add_like/<int:video_id>/', views.add_like, name='add_like'),
path('<str:session_username>/profile/', views.profile, name='profile'),
path('<str:session_username>/dashboard/', views.dashboard, name='dashboard'),
path('add_subscriber/<viewer>/', views.add_sub, name='add_subscriber'),
path('upload/', views.upload_video, name='upload'),
path('edit_video/<int:video_id>', views.edit_video, name='edit_video'),
path('delete_video/', views.delete_video, name='delete_video'),
path('update_details/', views.update_details, name='update_details'),
path('signup/', views.signup, name='signup'),
path('login/', views.user_login, name='login'),
path('logout/', views.user_logout, name='logout'),
path('search/', views.search, name='search'),
]
main/views.py
from django.shortcuts import render, redirect
from django.http import HttpResponse, JsonResponse, HttpResponseRedirect
from django.urls import reverse_lazy, reverse
from django.contrib.auth.models import User
from .models import VideoPost, Comment, UserData
from django.contrib.auth import authenticate, login, logout
from django.contrib import messages
from django.core.exceptions import ObjectDoesNotExist
# Create your views here.
def home(request):
if not request.user.is_authenticated:
demo_videos = VideoPost.objects.all().order_by('-id')[:5]
params = {'videos': demo_videos}
return render(request, 'welcome.html', params)
else:
all_videos = VideoPost.objects.all().order_by('-id')
params = {'all_videos': all_videos}
return render(request, 'home.html', params)
def search(request):
query = request.GET['search_query']
try:
user_obj = User.objects.filter(username__icontains=query)
except:
user_obj = User.objects.none()
params = {'user_obj': user_obj}
return render(request, 'search_page.html', params)
def upload_video(request):
if request.method == 'POST':
title = request.POST['title']
desc = request.POST['desc']
video_file = request.FILES['fileName']
thumb_nail = request.FILES['thumbnail_img']
cate = request.POST['category']
user_obj = User.objects.get(username=request.user)
upload_video = VideoPost(user=user_obj, title=title, desc=desc, video_file=video_file, thumbnail=thumb_nail, category=cate)
upload_video.save()
messages.success(request, 'Video has been uploaded.')
return render(request, 'upload_video.html')
def watch_video(request, video_id):
try:
video_obj = VideoPost.objects.get(id=video_id)
except ObjectDoesNotExist:
return render(request, '404.html')
try:
session_obj = User.objects.get(username=request.user.username)
except:
messages.warning(request, 'You are not login to watch this video.')
return redirect('home')
video_comments = Comment.objects.filter(post=video_obj).order_by('-id')
# Increase Views of Video if User visit this page
if request.user not in video_obj.video_views.all():
video_obj.video_views.add(request.user)
# Increase Likes of Video if User like this video
is_liked = False
if session_obj in video_obj.likes.all():
is_liked = True
else:
is_liked = False
params = {'video':video_obj, 'comments': video_comments, 'is_liked':is_liked}
return render(request, 'watch_video.html', params)
def add_comment(request):
if request.method == 'GET':
video_id = request.GET['video_id']
comment = request.GET['comment_text']
video_obj = VideoPost.objects.get(id=video_id)
session_obj = User.objects.get(username=request.user.username)
video_comments = Comment.objects.filter(post=video_obj).order_by('-id')
create_comment = Comment.objects.create(post=video_obj, user=session_obj, comment=comment)
create_comment.save()
return JsonResponse({'comment':create_comment.comment, 'count_comments':video_comments.count()})
def add_like(request, video_id):
user_obj = User.objects.get(username=request.user.username)
video_obj = VideoPost.objects.get(id=video_id)
is_liked = False
if user_obj in video_obj.likes.all():
video_obj.likes.remove(user_obj)
is_liked = True
else:
video_obj.likes.add(user_obj)
is_liked = False
return JsonResponse({'is_liked':is_liked,'likes_count':video_obj.likes.all().count()})
def profile(request, session_username):
try:
session_obj = User.objects.get(username=session_username)
except ObjectDoesNotExist:
return render(request, '404.html')
profile_data = UserData.objects.get_or_create(user=session_obj)[0]
user_posts = VideoPost.objects.filter(user=session_obj).order_by('-id')
# Category wise Posts
video_cat_science = VideoPost.objects.filter(user=session_obj, category='Science & Techanology').order_by('-id')
video_cat_blogs = VideoPost.objects.filter(user=session_obj, category='Blogs').order_by('-id')
video_cat_fashion = VideoPost.objects.filter(user=session_obj, category='Fashion').order_by('-id')
video_cat_education = VideoPost.objects.filter(user=session_obj, category='Education').order_by('-id')
video_cat_food = VideoPost.objects.filter(user=session_obj, category='Food').order_by('-id')
subscribed = False
if request.user in profile_data.subscribers.all():
subscribed = True
else:
subscribed = False
params = {'subscribed':subscribed,'session_obj':session_obj,'user_data':profile_data, 'videos': user_posts, 'sci': video_cat_science, 'blogs': video_cat_blogs, 'fashion': video_cat_fashion, 'edu':video_cat_education, 'food': video_cat_food}
return render(request, 'profile.html', params)
def dashboard(request, session_username):
user_videos = VideoPost.objects.filter(user__username=request.user.username).order_by('-id')
user_data = UserData.objects.get_or_create(user=User.objects.get(username=request.user.username))[0]
user_video_likes = 0
user_videos_views = 0
for video in user_videos:
user_video_likes += video.likes.count()
user_videos_views += video.video_views.count()
params = {'videos': user_videos, 'user_data': user_data, 'total_likes':user_video_likes, 'total_views': user_videos_views}
return render(request, 'dashboard.html', params)
def add_sub(request, viewer):
viewer_obj = UserData.objects.get_or_create(user=User.objects.get(username=viewer))[0]
subscriber_obj = User.objects.get(username=request.user.username)
subscribed = False
if subscriber_obj in viewer_obj.subscribers.all():
viewer_obj.subscribers.remove(subscriber_obj)
subscribed = True
else:
viewer_obj.subscribers.add(subscriber_obj)
subscribed = False
return JsonResponse({'is_subscribed': subscribed, 'viewer_obj':viewer_obj.subscribers.all().count()})
def edit_video(request, video_id):
if request.method == 'POST':
new_title = request.POST['new_title']
new_desc = request.POST['new_desc']
new_cate = request.POST['new_cate']
video_obj = VideoPost.objects.get(id=video_id)
video_obj.title = new_title
video_obj.desc = new_desc
video_obj.category = new_cate
video_obj.save()
return HttpResponseRedirect(reverse('dashboard', args=[str(request.user.username)]))
else:
return HttpResponse('get')
def update_details(request):
if request.method == 'POST':
user_data = UserData.objects.get(user=request.user)
aboutText = request.POST['about_text']
try:
imgFile = request.FILES['img_field']
if imgFile:
user_data.profile_pic = imgFile
except:
print('some error occured')
user_data.about = aboutText
user_data.save()
return HttpResponseRedirect(reverse('dashboard', args=[str(request.user.username)]))
return redirect('dashboard')
def delete_video(request):
if request.method == 'GET':
vid = request.GET['videoId']
video_obj = VideoPost.objects.get(id=vid)
video_obj.delete()
user_videos = VideoPost.objects.filter(user__username=request.user.username)
user_video_likes = 0
for video in user_videos:
user_video_likes += video.likes.count()
return JsonResponse({'video_id': vid, 'videosCount': user_videos.count(), 'videosLikes': user_video_likes})
else:
return JsonResponse({'status': 'not ok'})
def signup(request):
if request.method == 'POST':
first_name = request.POST['fname']
last_name = request.POST['lname']
mail = request.POST['mail']
pwd = request.POST['pwd']
new_user = User.objects.create_user(f'{first_name.lower()}123', mail, pwd)
new_user.first_name = first_name
new_user.last_name = last_name
new_user.save()
messages.success(request, 'Account has been created successfully.')
return redirect('home')
def user_login(request):
if not request.user.is_authenticated:
if request.method == 'POST':
uname = request.POST['uname']
pwd = request.POST['pwd']
check_user = authenticate(username = uname, password = pwd)
if check_user is not None:
login(request, check_user)
return redirect('home')
else:
messages.warning(request, 'Invalid Username or Password.')
return redirect('home')
return redirect('home')
else:
return redirect('home')
def user_logout(request):
logout(request)
return redirect('home')
Templates Work
Create a templates folder in main app and create some HTML templates in this folder.
base.html
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!--Animation-->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css"/>
<!-- Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-giJF6kkoqNQ00vy+HMDP7azOuL0xtbfIcaT9wjKHr8RbDVddVHyTfAAsrekwKmP1" crossorigin="anonymous">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<title>ViralVideo</title>
</head>
<body>
{% load static %}
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<div class="container-fluid">
<a class="navbar-brand" href="{% url 'home' %}">ViralVideo</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="{% url 'home' %}">Home</a>
</li>
<form class="d-flex" action="{% url 'search' %}" method="get">
<input class="form-control me-2 mx-4" name="search_query" style="width: 700px;" type="search" placeholder="Search User" aria-label="Search">
<button class="btn btn-outline-success" type="submit">Search</button>
</form>
</ul>
{% if not user.is_authenticated %}
<button class="btn btn-outline-success mx-3" data-bs-toggle="modal" data-bs-target="#loginModal">Login</button>
<button class="btn btn-outline-warning" data-bs-toggle="modal" data-bs-target="#signupModal">Signup</button>
{% else %}
<div class="btn-group mx-4">
<button type="button" class="btn btn-secondary dropdown-toggle" data-bs-toggle="dropdown" data-bs-display="static" aria-expanded="false">
@{{request.user}}
</button>
<ul class="dropdown-menu dropdown-menu-end dropdown-menu-lg-start">
<a href="{% url 'profile' request.user.username %}" style="text-decoration:none;"><li><button class="dropdown-item" type="button">Your Channel</button></li></a>
<a href="{% url 'dashboard' request.user.username %}" style="text-decoration:none;"><li><button class="dropdown-item" type="button">Dashboard</button></li></a>
<a href="{% url 'upload' %}" style="text-decoration:none;"><li><button class="dropdown-item" type="button">Upload Video</button></li></a>
<li><hr class="dropdown-divider"></li>
<a href="{% url 'logout' %}" style="text-decoration:none;"><li class="text-danger"><button class="dropdown-item text-danger" type="button">Logout</button></li></a>
</ul>
</div>
{% endif %}
</div>
</div>
</nav>
{% if messages %}
{% for message in messages %}
<div class="alert alert-{{message.tags}} alert-dismissible fade show" role="alert">
<strong>{{message}}</strong>
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
{% endfor %}
{% endif %}
{% block body%}{% endblock %}
<!-- Option 1: Bootstrap Bundle with Popper -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/js/bootstrap.bundle.min.js" integrity="sha384-ygbV9kiqUc6oa4msXn9868pTtWMgiQaeYH7/t7LECLbyPA2x65Kgf80OJFdroafW" crossorigin="anonymous"></script>
</body>
</html>
welcome.html
{% extends 'base.html' %}
{% load static %}
{% block body %}
<!--Signup Modal-->
<div class="modal fade" id="signupModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Sign Up</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<form action="{% url 'signup' %}" method="post">
{% csrf_token %}
<div class="mb-3">
<label for="fname" class="form-label">First Name</label>
<input type="text" class="form-control" id="fname" name="fname">
</div>
<div class="mb-3">
<label for="lname" class="form-label">Last Name</label>
<input type="text" class="form-control" id="lname" name="lname">
</div>
<div class="mb-3">
<label for="exampleInputEmail1" class="form-label">Email address</label>
<input type="email" class="form-control" id="exampleInputEmail1" name="mail" aria-describedby="emailHelp">
</div>
<div class="mb-3">
<label for="exampleInputPassword1" class="form-label">Password</label>
<input type="password" class="form-control" name="pwd" id="exampleInputPassword1">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="submit" class="btn btn-primary">Sign Up</button>
</div>
</form>
</div>
</div>
</div>
</div>
<!--Login Modal-->
<div class="modal fade" id="loginModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Login</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<form action="{% url 'login' %}" method="post">
{% csrf_token %}
<div class="mb-3">
<label for="exampleInputEmail1" class="form-label">User Name</label>
<input type="text" class="form-control" name="uname" id="exampleInputEmail1" aria-describedby="emailHelp">
</div>
<div class="mb-3">
<label for="exampleInputPassword1" class="form-label">Password</label>
<input type="password" class="form-control" name="pwd" id="exampleInputPassword1">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="submit" class="btn btn-primary">Login</button>
</div>
</form>
</div>
</div>
</div>
</div>
<!--Welcome Content-->
<div class="container-fluid my-2">
<div class="card bg-success text-white" style="height: 400px;">
<img src="{% static 'img/bg.jpg' %}" class="card-img" style="height: 400px;" alt="...">
</div>
</div>
<div class="container my-3">
{% for video in videos %}
<div class="card mb-3" style="max-width: 540px;">
<div class="row g-0">
<div class="col-md-4">
<img src="{% static video.thumbnail.url %}" width="208rem" alt="image">
</div>
<div class="col-md-8m mx-4 w-50">
<div class="card-body">
<a href="{% url 'watch_video' video.id %}" style="text-decoration: none;">
<h5 class="card-title">{{video.title}}</h5>
</a>
<p class="card-text">{{video.desc}}</p>
<p class="card-text"><small class="text-muted">{{video.pub_date}}</small></p>
</div>
</div>
</div>
</div>
{% endfor %}
</div>
{% endblock %}
home.html
{% extends 'base.html' %}
{% load static %}
{% block body %}
<div class="container-fluid">
<div class="card bg-light text-white">
<img src="{% static 'img/bg2.jpg' %}" class="card-img" style="height: 350px;" alt="...">
<div class="card-img-overlay">
<h2 style="margin-top: 150px; margin-left: 350px;">Viral Your Video Here and get more audience</h2>
</div>
</div>
</div>
<div class="container">
<div class="row my-4">
{% for video in all_videos %}
<div class="col-3">
<a href="{% url 'watch_video' video.id %}" style="text-decoration: none;">
<img src="{% static video.thumbnail.url %}" class="w-100">
</a>
<a href="{% url 'watch_video' video.id %}" style="text-decoration: none;">
<h6>{{video.title}}</h6>
</a>
<span class="text-muted">{{video.video_views.all.count}} views • {{video.pub_date}}</span>
</div>
{% endfor %}
<hr>
</div>
{% endblock %}
upload.html
{% extends 'base.html' %}
{% load static %}
{% block body%}
<div class="container border py-4 my-4 w-75">
<form action="{% url 'upload' %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
<div class="mb-3">
<label for="title" class="form-label">Title</label>
<input type="text" name="title" class="form-control" id="title" required>
</div>
<div class="mb-3">
<label for="desc" class="form-label">Description</label>
<textarea class="form-control" name="desc" id="desc" style="height: 200px;" required></textarea>
</div>
<div class="mb-3">
<label for="filename" class="form-label">Select Video File</label>
<input type="file" name="fileName" class="form-control" id="filename" accept="video/*" required>
</div>
<div class="mb-3">
<label for="thumb" class="form-label">Select Thumbnail</label>
<input type="file" name="thumbnail_img" class="form-control" id="thumb" accept="image/*" required>
</div>
<div class="mb-3">
<label for="title" class="form-label">Select Category</label>
<select class="form-control" name="category">
<option>Science & Techanology</option>
<option>Fashion</option>
<option>Food</option>
<option>Education</option>
<option>Blogs</option>
</select>
</div>
<button type="submit" class="btn btn-primary">Upload</button>
</form>
</div>
{% endblock %}
watch_video.html
{% extends 'base.html' %}
{% load static %}
{% block body %}
<div class="row">
<div class="col-8">
<div class="container py-2 my-4 w-auto" style="position: absolute; left:100px;">
<div id="carouselExampleSlidesOnly" class="carousel slide" data-bs-ride="carousel">
<div class="carousel-inner">
<div class="carousel-item active">
<video width="750" controls>
<source src="{% static video.video_file.url %}" type="video/mp4">
</video>
</div>
</div>
</div>
<div class="card w-auto">
<div class="card-body">
<h5 class="card-title">{{video.title}}</h5>
<span class="badge rounded-pill bg-info text-dark">{{video.category}}</span>
<div class="row">
<div class="col-8">
<span class="text-muted">{{video.video_views.all.count}} views • {{video.pub_date}}</span>
</div>
<div class="col">
{% if is_liked %}
<a id="like_btn" class="btn btn-outline-danger mx-3"><span id="count_likes">{{video.likes.all.count}}</span>  <span id="like_icon"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-heart-fill" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M8 1.314C12.438-3.248 23.534 4.735 8 15-7.534 4.736 3.562-3.248 8 1.314z"/>
</svg>
</span></a>
{% else %}
<a id="like_btn" class="btn btn-outline-danger mx-3"><span id="count_likes">{{video.likes.all.count}}</span>  <span id="like_icon"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-heart" viewBox="0 0 16 16">
<path d="M8 2.748l-.717-.737C5.6.281 2.514.878 1.4 3.053c-.523 1.023-.641 2.5.314 4.385.92 1.815 2.834 3.989 6.286 6.357 3.452-2.368 5.365-4.542 6.286-6.357.955-1.886.838-3.362.314-4.385C13.486.878 10.4.28 8.717 2.01L8 2.748zM8 15C-7.333 4.868 3.279-3.04 7.824 1.143c.06.055.119.112.176.171a3.12 3.12 0 0 1 .176-.17C12.72-3.042 23.333 4.867 8 15z"/>
</svg>
</span></a>
{% endif %}
</div>
</div>
</div>
</div>
<div class="card my-2">
<div class="card-header">
<h6><b>DESCRIPTION</b></h6>
</div>
<div class="card-body">
<pre><p>{{video.desc}}</p></pre>
</div>
</div>
</div>
</div>
<div class="col-3" style="margin-left: 0px; width: 400px;">
<div class="container my-3">
<h3>Up Next</h3>
<div class="list-group my-2">
{% for v in video.user.videopost_set.all %}
<a href="{% url 'watch_video' v.id %}" class="list-group-item list-group-item-action" aria-current="true">
<div class="d-flex w-100 justify-content-between">
<h5 class="mb-1">{{v.title}}</h5>
<small>{{v.pub_date}}</small>
</div>
<p class="mb-1">{{v.desc}}</p>
<small>Donec id elit non mi porta.</small>
</a>
{% endfor %}
</div>
</div>
<div class="container my-4">
<!--Comments of this video-->
<div class="accordion accordion-flush" id="accordionFlushExample">
<div class="accordion-item">
<h2 class="accordion-header" id="flush-headingTwo">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#flush-collapseTwo" aria-expanded="false" aria-controls="flush-collapseTwo">
<b>COMMENTS (<span id='count_comment'>{{comments.count}}</span>)</b>
</button>
</h2>
<div id="flush-collapseTwo" class="accordion-collapse collapse" aria-labelledby="flush-headingTwo" data-bs-parent="#accordionFlushExample">
<div class="container my-2">
<ul class="list-group" id="menu">
{% for comment in comments %}
<b>{{comment}}</b>
<li class="list-group-item">{{comment.comment}}</li>
{% endfor %}
</ul>
</div>
<div class="accordion-body">
<form id="my_form">
<textarea class="form-control" name="comment" id="comment" placeholder="Write your comment..."></textarea>
<input class="btn btn-outline-success my-3" id="send_btn" type="submit" value="Comment">
</form>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script type="text/javascript">
var send_btn = $('#send_btn');
send_btn.on('click', function(event){
event.preventDefault();
var comment = $('#comment').val();
var ul_menu = $('#menu');
var count_comment = $('#count_comment');
$.ajax({
type: 'GET',
url: '{% url "add_comment" %}',
data: {comment_text: comment, video_id: '{{video.id}}'},
dataType: 'json',
success: function(data){
if(data.comment)
{
var comment_res = data.comment;
var li_html = "<b>{{request.user}}</b><li class='list-group-item'>"+comment_res+"</li>";
ul_menu.prepend(li_html);
count_comment.text(data.count_comments);
$('#my_form').trigger('reset');
}
}
});
});
</script>
<script type="text/javascript">
var like_btn = $('#like_btn');
like_btn.on('click', function(event){
event.preventDefault();
var count_likes = $('#count_likes');
var like_icon = $('#like_icon');
$.ajax({
url: '{% url "add_like" video.id %}',
data: {},
dataType: 'json',
success: function(data){
if(data.is_liked)
{
like_icon.html('<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-heart" viewBox="0 0 16 16"><path d="M8 2.748l-.717-.737C5.6.281 2.514.878 1.4 3.053c-.523 1.023-.641 2.5.314 4.385.92 1.815 2.834 3.989 6.286 6.357 3.452-2.368 5.365-4.542 6.286-6.357.955-1.886.838-3.362.314-4.385C13.486.878 10.4.28 8.717 2.01L8 2.748zM8 15C-7.333 4.868 3.279-3.04 7.824 1.143c.06.055.119.112.176.171a3.12 3.12 0 0 1 .176-.17C12.72-3.042 23.333 4.867 8 15z"/></svg>');
count_likes.text(data.likes_count);
}
else
{
like_icon.html('<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-heart-fill" viewBox="0 0 16 16"><path fill-rule="evenodd" d="M8 1.314C12.438-3.248 23.534 4.735 8 15-7.534 4.736 3.562-3.248 8 1.314z"/>');
count_likes.text(data.likes_count);
}
}
});
});
</script>
{% endblock %}
profile.html
{% extends 'base.html' %}
{% load static %}
{% block body %}
<!--Profile Image and Name-->
<div class="container my-4">
<div class="container">
<div class="row">
<div class="col-3">
<img src="{% static user_data.profile_pic.url %}" class="img-thumbnail" style="width: 150px;height: 200px;">
</div>
<div class="col">
<h2 style="margin-top: 80px;" >{{session_obj.first_name}} {{session_obj.last_name}}</h2>
<span class="text-muted"><span class="text-muted" id="count">{{user_data.subscribers.count}}</span> Subscribers</span>
{% if session_obj != request.user %}
{% if subscribed %}
<a id="sub_btn" class="btn btn-outline-danger mx-3">Unsubscribe</a>
{% else %}
<a id="sub_btn" class="btn btn-outline-danger mx-3">Subscribe</a>
{% endif %}
{% endif %}
</div>
</div>
</div>
</div>
<!--End of Profile Image and Name-->
<hr>
<div class="container">
<ul class="nav nav-tabs" id="myTab" role="tablist">
<li class="nav-item" role="presentation">
<a class="nav-link active" id="home-tab" data-bs-toggle="tab" href="#home" role="tab" aria-controls="home" aria-selected="true">Home</a>
</li>
<li class="nav-item" role="presentation">
<a class="nav-link" id="profile-tab" data-bs-toggle="tab" href="#profile" role="tab" aria-controls="profile" aria-selected="false">Videos</a>
</li>
<li class="nav-item" role="presentation">
<a class="nav-link" id="contact-tab" data-bs-toggle="tab" href="#contact" role="tab" aria-controls="contact" aria-selected="false">About</a>
</li>
</ul>
<div class="tab-content" id="myTabContent">
<div class="tab-pane fade show active" id="home" role="tabpanel" aria-labelledby="home-tab">
<h3 class="my-3">Category wise videos</h3>
<hr>
{% if sci %}
<div class="row">
<h4 class="text-primary">Science & Technology</h4>
{% for v in sci %}
<div class="col-3">
<a href="{% url 'watch_video' v.id %}" style="text-decoration: none;"><img src="{% static v.thumbnail.url %}" style="width: 100%;" class="img-thumbnail"></a>
<a href="{% url 'watch_video' v.id %}" style="text-decoration: none;"><h6>{{v.title}}</h6></a>
<span class="text-muted">{{v.video_views.all.count}} views • {{v.pub_date}}</span>
</div>
{% endfor %}
</div>
<hr>
{% endif %}
{% if blogs %}
<div class="row">
<h4 class="text-primary">Blogs</h4>
{% for v in blogs %}
<div class="col-3">
<a href="{% url 'watch_video' v.id %}" style="text-decoration: none;"><img src="{% static v.thumbnail.url %}" style="width: 100%;" class="img-thumbnail"></a>
<a href="{% url 'watch_video' v.id %}" style="text-decoration: none;"><h6>{{v.title}}</h6></a>
<span class="text-muted">{{v.video_views.all.count}} views • {{v.pub_date}}</span>
</div>
{% endfor %}
</div>
<hr>
{% endif %}
{% if food %}
<div class="row">
<h4 class="text-primary">Food</h4>
{% for v in food%}
<div class="col-3">
<a href="{% url 'watch_video' v.id %}" style="text-decoration: none;"><img src="{% static v.thumbnail.url %}" class="img-thumbnail w-75"></a>
<a href="{% url 'watch_video' v.id %}" style="text-decoration: none;"><h6>{{v.title}}</h6></a>
<span class="text-muted">{{v.video_views.all.count}} views • {{v.pub_date}}</span>
</div>
{% endfor %}
</div>
<hr>
{% endif %}
{% if edu %}
<div class="row">
<h4 class="text-primary">Education</h4>
{% for v in edu%}
<div class="col-3">
<a href="{% url 'watch_video' v.id %}" style="text-decoration: none;"><img src="{% static v.thumbnail.url %}" class="img-thumbnail w-75"></a>
<a href="{% url 'watch_video' v.id %}" style="text-decoration: none;"><h6>{{v.title}}</h6></a>
<span class="text-muted">{{v.video_views.all.count}} views • {{v.pub_date}}</span>
</div>
{% endfor %}
</div>
<hr>
{% endif %}
{% if fashion %}
<div class="row">
<h4 class="text-primary">Fashion</h4>
{% for v in fashion %}
<div class="col-3">
<a href="{% url 'watch_video' v.id %}" style="text-decoration: none;"><img src="{% static v.thumbnail.url %}" class="img-thumbnail w-75"></a>
<a href="{% url 'watch_video' v.id %}" style="text-decoration: none;"><h4>{{v.title}}</h4></a>
<span class="text-muted">{{v.video_views.all.count}} views • {{v.pub_date}}</span>
</div>
{% endfor %}
</div>
<hr>
{% endif %}
</div>
<div class="tab-pane fade" id="profile" role="tabpanel" aria-labelledby="profile-tab">
<div class="container">
<h3 class="my-3">Uploads</h3>
<div class="row my-3">
{% if videos %}
{% for video in videos %}
<div class="col-3">
<a href="{% url 'watch_video' video.id %}" style="text-decoration: none;"><img src="{% static video.thumbnail.url %}" style="width: 100%;" class="img-thumbnail"></a>
<a href="{% url 'watch_video' video.id %}" style="text-decoration: none;"><h6>{{video.title}}</h6></a>
<span class="text-muted">{{video.video_views.all.count}} views • {{video.pub_date}}</span>
</div>
{% endfor %}
{% else %}
<h3>No Videos.</h3>
{% endif %}
</div>
<hr>
</div>
</div>
<div class="tab-pane fade" id="contact" role="tabpanel" aria-labelledby="contact-tab">
<div class="container my-4">
<p><b>Description</b></p>
<pre style="font-family: tahoma; letter-spacing: 1px;"><p>{{user_data.about}}</p></pre>
<hr>
<p><b>Details</b></p>
<p>Email: </p>
<a href="mailto:{{session_obj.email}}"><p>{{session_obj.email}}</p></a>
<hr>
<p><b>Links: </b></p>
<p>Instagram</p>
<p>Github</p>
<p>Twitter</p>
<p>Facebook</p>
<hr>
</div>
</div>
</div>
</div>
<script type="text/javascript">
var btn = $('#sub_btn');
var count = $('#count');
// btn.text('Subscribe');
btn.on('click', function(event){
event.preventDefault();
$.ajax({
type: 'GET',
url: '{% url "add_subscriber" session_obj.username %}',
dataType: 'json',
success: function(data){
if(data.is_subscribed)
{
// alert(data.is_subscribed);
btn.text('Subscribe');
count.text(data.viewer_obj);
console.log(data.viewer_obj);
}
else
{
// alert(data.is_subscribed);
btn.text('Unsubscribe');
count.text(data.viewer_obj);
console.log(data.viewer_obj);
}
}
});
});
</script>
{% endblock %}
dashboard.html
{% extends 'base.html' %}
{% load static %}
{% block body %}
<div class="container my-3 py-3">
<div class="row">
<div class="col-sm-3">
<div class="card" style="width: 15rem;">
<div class="card border border-danger bg-danger text-light" style="width: 15rem;">
<div class="card-body">
<h2 class="card-title text-center"><span id="text_v_likes">{{total_likes}}</span> Likes</h2>
</div>
</div>
</div>
</div>
<div class="col-sm-3">
<div class="card" style="width: 15rem;">
<div class="card border border-danger bg-danger text-light" style="width: 15rem;">
<div class="card-body">
<h2 class="card-title text-center">{{user_data.subscribers.all.count}} Subscribers</h2>
</div>
</div>
</div>
</div>
<div class="col-sm-3">
<div class="card" style="width: 15rem;">
<div class="card border border-danger bg-danger text-light" style="width: 15rem;">
<div class="card-body">
<h2 class="card-title text-center"><span id='text_v_count'>{{videos.count}}</span> Videos</h2>
</div>
</div>
</div>
</div>
<div class="col-sm-3">
<div class="card" style="width: 15rem;">
<div class="card border border-danger bg-danger text-light" style="width: 15rem;">
<div class="card-body">
<h2 class="card-title text-center"><span id='text_v_count'>{{total_views}}</span> Views</h2>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="container">
<div class="d-flex align-items-start">
<div class="nav flex-column nav-pills px-4 py-4 me-3 border" id="v-pills-tab" role="tablist" aria-orientation="vertical">
<a class="nav-link active h5" id="v-pills-home-tab" data-bs-toggle="pill" href="#v-pills-home" role="tab" aria-controls="v-pills-home" aria-selected="true">Videos</a>
<a class="nav-link h5" id="v-pills-profile-tab" data-bs-toggle="pill" href="#v-pills-profile" role="tab" aria-controls="v-pills-profile" aria-selected="false">Profile</a>
</div>
<div class="tab-content" id="v-pills-tabContent">
<div class="tab-pane fade show active" id="v-pills-home" role="tabpanel" aria-labelledby="v-pills-home-tab">
<div class="container">
{% for video in videos %}
<div class="card my-3 border-dark" id="{{video.id}}">
<h5 class="card-header">{{video.title}}</h5>
<div class="card-body">
<img src="{% static video.thumbnail.url %}" class="img-thumbnail w-25">
<p class="card-text">{{video.desc|truncatewords:5}}</p>
<a href="{% url 'watch_video' video.id %}" class="btn btn-primary">Watch Now</a>
<span class="mx-4">
<button class="btn btn-danger">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-heart" viewBox="0 0 16 16">
<path d="M8 2.748l-.717-.737C5.6.281 2.514.878 1.4 3.053c-.523 1.023-.641 2.5.314 4.385.92 1.815 2.834 3.989 6.286 6.357 3.452-2.368 5.365-4.542 6.286-6.357.955-1.886.838-3.362.314-4.385C13.486.878 10.4.28 8.717 2.01L8 2.748zM8 15C-7.333 4.868 3.279-3.04 7.824 1.143c.06.055.119.112.176.171a3.12 3.12 0 0 1 .176-.17C12.72-3.042 23.333 4.867 8 15z"/>
</svg>
<b>{{video.likes.count}}</b>
</button>
<button class="btn btn-warning">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-eye-fill" viewBox="0 0 16 16">
<path d="M10.5 8a2.5 2.5 0 1 1-5 0 2.5 2.5 0 0 1 5 0z"/>
<path d="M0 8s3-5.5 8-5.5S16 8 16 8s-3 5.5-8 5.5S0 8 0 8zm8 3.5a3.5 3.5 0 1 0 0-7 3.5 3.5 0 0 0 0 7z"/>
</svg>
<b>{{video.video_views.count}}</b>
</button>
<button class="btn btn-info">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-vector-pen" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M10.646.646a.5.5 0 0 1 .708 0l4 4a.5.5 0 0 1 0 .708l-1.902 1.902-.829 3.313a1.5 1.5 0 0 1-1.024 1.073L1.254 14.746 4.358 4.4A1.5 1.5 0 0 1 5.43 3.377l3.313-.828L10.646.646zm-1.8 2.908l-3.173.793a.5.5 0 0 0-.358.342l-2.57 8.565 8.567-2.57a.5.5 0 0 0 .34-.357l.794-3.174-3.6-3.6z"/>
<path fill-rule="evenodd" d="M2.832 13.228L8 9a1 1 0 1 0-1-1l-4.228 5.168-.026.086.086-.026z"/>
</svg>
<b>{{video.comment_set.all.count}}</b>
</button>
</span>
<a class="btn btn-outline-danger mx-2 del_btn" id="{{video.id}}" style="float: right;">Delete</a>
<a href="#" class="btn btn-outline-success mx-2" data-bs-toggle="modal" data-bs-target="#exampleModal{{video.id}}" style="float: right;">Edit</a>
<!-- Button trigger modal -->
<!-- Edit Video Modal -->
<div class="modal fade" id="exampleModal{{video.id}}" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Edit Video Details</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<form action="{% url 'edit_video' video.id %}" method="post">
{% csrf_token %}
<div class="form-floating">
<input type="text" placeholder="Title" name="new_title" class="form-control my-2 new_title" id="new_title{{video.id}}" value="{{video.title}}">
<label for="floatingInput" >Title</label>
</div>
<div class="form-floating">
<textarea class="form-control my-2 new_desc" id="new_desc{{video.id}}" placeholder="Description" name="new_desc" style="height: 300px;">{{video.desc}}</textarea>
<label for="floatingInput">Description</label>
</div>
<div class="form-floating">
<select name="new_cate" class="form-control new_cate" id="new_cate{{video.id}}" name="category">
<option>{{video.category}}</option>
<option>Science & Techanology</option>
<option>Fashion</option>
<option>Food</option>
<option>Education</option>
<option>Blogs</option>
</select>
<label for="floatingInput">Category</label>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="submit" id="edit_btn{{video.id}}" class="btn btn-primary edit_btn">Save changes</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
{% endfor %}
</div>
</div>
<div class="tab-pane fade " style="width:800px;" id="v-pills-profile" role="tabpanel" aria-labelledby="v-pills-profile-tab">
<div class="container">
<div class="container">
<h3>Additional Data</h3>
<form action="{% url 'update_details' %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
<div class="row">
<div class="col-sm-8 my-auto">
<input type="file" name="img_field" accept="image/*" class="form-control">
</div>
<div class="col-sm-4">
<b><label>Current Profile Pic</label></b>
<img src="{% static user_data.profile_pic.url %}" class="rounded" style="width: 150px; height: 200px;" alt="{{user_data.profile_pic}}">
</div>
</div>
<div class="row">
<div class="col-sm-8">
<b><label for="about_text">About</label></b>
<textarea placeholder="About yourself..." class="form-control" style="height: 100px;" name="about_text">{{user_data.about}}</textarea>
</div>
</div>
<input type="submit" id="update_btn" value="Update" class="btn btn-outline-success my-3">
</form>
</div>
<hr>
<div class="container">
<h3 class="text-danger">Danger Zone</h3>
<form>
<input type="text" name="" placeholder="Type Your Username to Verify" class="form-control">
<input type="submit" name="" value="Deactivate Your Account" class="btn btn-outline-danger my-3">
</form>
</div>
</div>
</div>
</div>
</div>
</div>
<script type="text/javascript">
var btn = $('.del_btn');
btn.on('click',function(event){
event.preventDefault();
var vid = $(this).attr('id');
var v_count = $('#text_v_count');
var v_likes = $('#text_v_likes');
$.ajax({
type: 'GET',
url: '{% url "delete_video" %}',
data: {videoId: vid},
dataType: 'json',
success: function(data){
if(data.video_id)
{
var vid = data.video_id;
$('div').remove('#'+vid);
v_count.text(data.videosCount);
v_likes.text(data.videosLikes);
}
}
});
});
</script>
{% endblock %}
search_page.html
{% extends 'base.html' %}
{% load static %}
{% block body %}
<div class="container my-4">
<h3>Search Results: </h3>
{% if user_obj %}
<div class="row">
{% for user in user_obj %}
<div class="col-4">
<div class="card my-3" style="width: 18rem;">
<img src="{% static user.userdata.profile_pic.url %}" class="img-thumbnail card-img-top" style="height: 250px;" alt="...">
<div class="card-body">
<h5 class="card-title">{{user.username}}</h5>
<p class="card-text">{{user.userdata.about|truncatewords:6}}</p>
<a href="{% url 'profile' user.username %}" class="btn btn-primary">View Profile</a>
</div>
</div>
</div>
{% endfor %}
</div>
{% else %}
<div class="container">
<h5>No Results Found.</h5>
</div>
{% endif %}
</div>
{% endblock %}
404.html
{% extends 'base.html' %}
{% block body %}
<div class="container py-4 w-25 text-center bg-danger" style="margin-left: 40%; margin-top: 100px;">
<h1 class="animate__animated animate__swing">404</h1>
Not Found
</div>
{% endblock %}
That's it.
If you face any problem related to the source code than comment below.
I have worked very hard on this project. So I request you to support my hard work.
Top comments (10)
Thanks for the detailed tutorial.
I started my website to share CapCut Templates on WordPress and its slow a bit, Now i am trying to make custom page so i can meet google Core Web Vitals.
Thanks for the detailed tutorial.
I started my website to share CapCut Templates on WordPress and its slow a bit, Now i am trying to make custom page so i can meet google Core Web Vitals.
Good good
Thanks
def watch_video(request, video_id):
try:
video_obj = VideoPost.objects.get(id=video_id)
except ObjectDoesNotExist:
return render(request, '404.html')
use django.shortcuts.get_object_or_404()
Nice Work bro
Thanks..
Hello sir thank for the tutorial am a new developer...could you please share the static files for the project...thanks
nice
Amazing work keep it up.