Do u use any Social Networking Site like Facebook or Instagram? Yes... Than try my FriendBook.
Here u can get experience of FriendBook and it is easy to use.
Here is Demo Video:-
Functionallity of FriendBook:-
- Easy to use
- Create, Update and Delete Posts
- Like and Comment the posts
- Follow or Unfollow other users
- Find your friends on FriendBook
Source Code
models.py
from django.db import models
# Create your models here.
class User(models.Model):
full_name = models.CharField(max_length=100)
user_name = models.CharField(max_length=100)
email = models.EmailField()
password = models.CharField(max_length=50)
bio = models.TextField(default='')
profile_pic = models.ImageField(upload_to='profile_pic/', default='profile_pic/default.jpg')
date_joined = models.DateField(auto_now_add=True)
def __str__(self):
return self.full_name
class Follower(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
another_user = models.ManyToManyField(User, related_name='another_user')
def __str__(self):
return self.user.user_name
class Post(models.Model):
user = models.ForeignKey(User, on_delete = models.CASCADE)
img = models.ImageField(upload_to='post_images/')
desc = models.TextField()
likes = models.ManyToManyField(User, related_name='likes')
pub_date = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ['-pub_date']
def __str__(self):
return self.img.url
class Comment(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
post = models.ForeignKey(Post, on_delete=models.CASCADE)
comment = models.CharField(max_length=500)
admin.py
from django.contrib import admin
from .models import User, Post, Comment, Follower
# Register your models here.
@admin.register(User)
class userAdmin(admin.ModelAdmin):
list_display = ('id', 'full_name', 'user_name', 'email', 'password')
@admin.register(Comment)
class commentAdmin(admin.ModelAdmin):
list_display = ('id', 'user', 'post', 'comment')
admin.site.register(Post)
admin.site.register(Follower)
urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.index, name='index'),
path('<str:username>/profile/', views.profile, name='profile'),
path('upload/', views.upload_post, name='upload_post'),
path('update_profile/', views.update_profile, name='update_profile'),
path('add_like/', views.add_like, name='add_like'),
path('add_comment/', views.add_comment, name='add_comment'),
path('del_post/', views.del_post, name='delete_post'),
path('follow_user/', views.follow_user, name='follow_user'),
path('login/' ,views.user_login, name='user_login'),
path('logout/' ,views.user_logout, name='user_logout'),
path('signup/', views.user_signup, name='user_signup'),
path('search/' ,views.search, name='search_user'),
]
views.py
from django.shortcuts import render, redirect
from django.http import HttpResponse, JsonResponse, HttpResponseRedirect
from .models import User, Post, Comment, Follower
from django.contrib import messages
from django.urls import reverse_lazy, reverse
# Create your views here.
def index(request):
if 'user' in request.session:
session_user_obj = User.objects.get(user_name=request.session['user'])
check_follower = Follower.objects.get_or_create(user=session_user_obj)[0]
check_follower.another_user.add(session_user_obj)
following_users = Follower.objects.filter(another_user=session_user_obj)
suggest_users = User.objects.all().exclude(user_name=request.session['user'])[:8]
params = {'following_users': following_users, 'user_obj': session_user_obj, 'suggest_users': suggest_users}
return render(request, 'home.html', params)
else:
return render(request, 'welcome.html')
def profile(request, username):
try:
user_obj = User.objects.get(user_name=username)
except:
messages.warning(request, 'User does not exists.')
return HttpResponseRedirect(reverse('profile', args=[str(request.session['user'])]))
user_posts = user_obj.post_set.all().order_by('-id')
# session user object
try:
session_user_obj = User.objects.get(user_name=request.session['user'])
except:
messages.warning(request, 'You have to login first.')
return redirect('index')
# check follower
check_follower = Follower.objects.get_or_create(user=user_obj)[0]
#count following
following_user_count = Follower.objects.filter(another_user=user_obj).count()
is_followed = False
if session_user_obj in check_follower.another_user.all():
is_followed = True
params = {'posts': user_posts, 'user_data':user_obj,'session_obj':session_user_obj, 'is_followed': is_followed, 'followers_count': check_follower.another_user.count(), 'following_count': following_user_count}
return render(request, 'profile.html', params)
def update_profile(request):
if request.method == 'POST':
user_obj = User.objects.get(user_name=request.session['user'])
try:
new_img = request.FILES['new_img']
except:
new_img = user_obj.profile_pic
new_email = request.POST['mail']
new_bio = request.POST['bio']
if new_img:
user_obj.profile_pic = new_img
user_obj.email = new_email
user_obj.bio = new_bio
user_obj.save()
return HttpResponseRedirect(reverse('profile', args=[str(request.session['user'])]))
def upload_post(request):
if request.method == 'POST':
user_obj = User.objects.get(user_name=request.session['user'])
image_name = request.FILES['file_name']
desc = request.POST['desc']
upload_post = Post.objects.create(user=user_obj, img=image_name, desc=desc)
upload_post.save()
messages.success(request, 'Post uploaded successfully.')
return render(request, 'upload.html')
def add_like(request):
post_id = request.GET['postId']
user_obj = User.objects.get(user_name=request.session['user'])
post_obj = Post.objects.get(id=post_id)
is_liked = False
if user_obj in post_obj.likes.all():
post_obj.likes.remove(user_obj)
is_liked = True
else:
post_obj.likes.add(user_obj)
is_liked = False
return JsonResponse({'status': 'Ok', 'post_likes': post_obj.likes.count(), 'isLiked': is_liked})
def add_comment(request):
comment = request.GET['comment']
post_id = request.GET['post_id']
user_obj = User.objects.get(user_name=request.session['user'])
post_obj = Post.objects.get(id=post_id)
add_comment = Comment(user=user_obj, post=post_obj, comment=comment)
add_comment.save()
get_comments = Comment.objects.filter(post=post_obj)
return JsonResponse({'comment': add_comment.comment, 'user': user_obj.full_name, 'comment_count': get_comments.count()})
def follow_user(request):
userId = request.GET['userId']
# another user
user_obj = User.objects.get(id=userId)
# session user
session_user_obj = User.objects.get(user_name=request.session['user'])
# Follower obj
check_follower = Follower.objects.get_or_create(user=user_obj)[0] #It is <Follower:user_obj>
is_followed = False
if session_user_obj in check_follower.another_user.all():
is_followed = True
check_follower.another_user.remove(session_user_obj)
else:
is_followed = False
check_follower.another_user.add(session_user_obj)
print('user id: ', userId)
return JsonResponse({'status': 'Ok', 'isFollowed': is_followed, 'followers_count': check_follower.another_user.count()})
def user_login(request):
if request.method == 'POST':
userName = request.POST['uname']
userPwd = request.POST['pwd']
check_user = User.objects.filter(user_name=userName, password=userPwd)
if check_user:
request.session['user'] = userName
messages.success(request, f'You have loggedin as {userName}!')
return redirect('index')
else:
messages.warning(request, 'Invalid Username or Password.')
return redirect('index')
return redirect('index')
def user_logout(request):
del request.session['user']
return redirect('index')
def user_signup(request):
if request.method == 'POST':
fullName = request.POST['fname']
userName = request.POST['uname']
mail = request.POST['mail']
userPwd = request.POST['pwd']
new_user = User(full_name=fullName, user_name=userName, email=mail, password=userPwd)
new_user.save()
messages.success(request, 'Account has been created successfully.')
return redirect('index')
def search(request):
if request.method == 'GET':
user_query = request.GET['query']
search_users_uname = User.objects.filter(user_name__icontains=user_query)
search_users_fname = User.objects.filter(full_name__icontains=user_query)
search_results = search_users_uname.union(search_users_fname)
params = {'results': search_results}
return render(request, 'search.html', params)
def del_post(request):
if request.method == 'GET':
post_id = request.GET['postId']
post_obj = Post.objects.get(id=post_id)
post_obj.delete()
return JsonResponse({'status': 'Ok', 'id': post_id})
else:
return JsonResponse({'status': 'not Ok'})
Templates Work
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">
{% load static %}
<!-- Bootstrap CSS -->
<link rel="stylesheet" type="text/css" href="{% static 'css/css.css' %}">
<link rel="stylesheet" type="text/css" href="{% static 'css/font_awsome.css' %}">
<!--Add Jquery-->
<script type="text/javascript" src="{% static 'js/my_jquery.js' %}"></script>
<title>{% block title %}{% endblock %}</title>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<div class="container-fluid">
<a class="navbar-brand" href="#">Friend<span style="color: red;">Book</span></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 'index' %}">Home</a>
</li>
</ul>
<form class="d-flex" action="{% url 'search_user' %}" method="get">
<input class="form-control me-2" type="search" name="query" placeholder="Search User" aria-label="Search">
<button class="btn btn-outline-success" type="submit">Search</button>
</form>
{% if request.session.user %}
<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.session.user}}
</button>
<ul class="dropdown-menu dropdown-menu-end dropdown-menu-lg-start">
<li><a href="{% url 'profile' request.session.user %}" class="dropdown-item">Profile</a></li>
<li><a href="{% url 'upload_post' %}" class="dropdown-item">Upload Post</a></li>
<li><hr class="dropdown-divider"></li>
<li><a href="{% url 'user_logout' %}" class="dropdown-item text-danger">Logout</a></li>
</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 type="text/javascript" src="{% static 'js/js.js' %}"></script>
</body>
</html>
welcome.html
{% extends 'base.html' %}
{% load static %}
{% block title %}
Welcome to FriendBook
{% endblock %}
{% block body %}
<div class="container-fluid text-center">
<div class="card bg-dark text-white">
<img src="{% static 'img1.jpg' %}" class="card-img" alt="..." style="height: 400px; opacity: 0.5;">
<div class="card-img-overlay" style="margin-top: 100px;">
<h1 class="card-title" style="text-shadow: 2px 5px black; font-size: 50px;">Welcome to <span style="color: dodgerblue;">FriendBook</span></h1>
<p class="card-text" style="font-size: 20px; text-shadow: 2px 2px black;">Find your Family, Relatives, Friends and Make your Connection here</p>
</div>
</div>
</div>
<div class="container my-4">
<div class="row">
<div class="col-5 alert alert-success mx-2 my-3">
<h4>Login</h4>
<form action="{% url 'user_login' %}" method="post">
{% csrf_token %}
<div class="mb-3">
<label for="exampleFormControlInput1" class="form-label">Username</label>
<input type="text" name="uname" class="form-control" id="exampleFormControlInput" required>
</div>
<div class="mb-3">
<label for="exampleFormControlPassword" class="form-label">Password</label>
<input type="password" name="pwd" class="form-control" name="" id="exampleFormControlPassword" required>
</div>
<input type="submit" name="" value="Login" class="btn btn-outline-success">
</form>
</div>
<div class="col-6 alert alert-info my-3">
<h4>Signup</h4>
<form action="{% url 'user_signup' %}" method="post">
{% csrf_token %}
<div class="mb-3">
<label for="exampleFormControlInput1" class="form-label">Full Name</label>
<input type="text" class="form-control" name="fname" id="exampleFormControlInput" required>
</div>
<div class="mb-3">
<label for="exampleFormControlInput1" class="form-label">Username</label>
<input type="text" class="form-control" name="uname" id="exampleFormControlInput" required>
</div>
<div class="mb-3">
<label for="exampleFormControlEmail" class="form-label">Email</label>
<input type="email" class="form-control" name="mail" id="exampleFormControlEmail" required>
</div>
<div class="mb-3">
<label for="exampleFormControlPassword" class="form-label">Password</label>
<input type="password" class="form-control" name="pwd" name="" id="exampleFormControlPassword" required>
</div>
<input type="submit" value="Signup" class="btn btn-primary">
</form>
</div>
</div>
</div>
{% endblock %}
index.html
{% extends 'base.html' %}
{% load static %}
{% block body %}
<div class="container my-4">
<div class="row">
<div class="col-7 border">
{% for user in following_users %}
{% for post in user.user.post_set.all %}
<div class="card my-2 w-100">
<h5 class="card-header my-2"><a href="{% url 'profile' user.user.user_name %}" style="text-decoration: none;">{{user.user.full_name}}</a>
<span class="text-muted" style="float: right; font-size: 15px;">{{post.pub_date}}</span>
</h5>
<div class="container">
<img src="{% static post.img.url %}" class="img-thumbnail w-100" style="width: 30rem; height: 30rem;">
</div>
<div class="card-body">
<p class="card-text">{{post.desc}}</p>
<button class="btn btn-danger like_btn" id="{{post.id}}"><span id="likes_count{{post.id}}">{{post.likes.count}}</span> <span id="sign{{post.id}}">
{% if user_obj in post.likes.all %}
<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"/>
{% else %}
<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>
{% endif %}
</span></button>
<button class="btn btn-success" data-bs-toggle="modal" data-bs-target="#exampleModal{{post.id}}"><span id="comment_count{{post.id}}">{{post.comment_set.count}}</span> Comment</button>
<!--Comment Modal-->
<div class="modal fade" id="exampleModal{{post.id}}" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-scrollable">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Public Comments</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="mb-2">
<form id="comment_form{{post.id}}">
<input type="text" class="form-control" placeholder="Add Comment..." id="comment_box{{post.id}}">
</form>
</div>
<div class="mb-3">
<div class="container" id="comment_container{{post.id}}">
{% for comment in post.comment_set.all %}
<b>
{{comment.user}}
</b>
<p>
{{comment.comment}}
</p>
{% endfor %}
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary comment_btn" id="{{post.id}}">Add Comment</button>
</div>
</div>
</div>
</div>
</div>
</div>
{% endfor %}
{% endfor %}
</div>
<div class="col w-100">
<h2>Suggetions</h2>
<hr>
<div class="container">
{% for user in suggest_users %}
<div class="card">
<div class="row">
<div class="col-6">
<img src="{% static user.profile_pic.url %}" class="w-50">
</div>
<div class="col-6">
<h5 class="text-center" style="display: inline;"><a class="text-dark" href="{% url 'profile' user.user_name %}" style="text-decoration: none;">{{user.user_name}}</a></h5>
</div>
</div>
</div>
{% endfor %}
</div>
</div>
</div>
</div>
<script type="text/javascript">
var like_btn = $('.like_btn');
like_btn.on('click', function(event){
event.preventDefault();
var t = this;
// alert(t.getAttribute('id'));
$.ajax({
type: 'GET',
url: '{% url "add_like" %}',
data: {postId: t.getAttribute('id')},
dataType: 'json',
success: function(data){
$('#likes_count'+t.getAttribute('id')).text(data.post_likes);
var sign = $('#sign'+t.getAttribute('id'));
if(data.isLiked)
{
sign.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>');
}
else
{
sign.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"/>');
}
}
});
});
</script>
<script type="text/javascript">
// Add Comments
var comment_btn = $('.comment_btn');
comment_btn.on('click', function(event){
event.preventDefault();
var t = this;
var comment_val = $('#comment_box'+t.getAttribute('id')).val();
var commentContainer = $('#comment_container'+t.getAttribute('id'));
var commentCount = $('#comment_count'+t.getAttribute('id'));
$.ajax({
type: 'GET',
url: '{% url "add_comment" %}',
data: {comment: comment_val, post_id: t.getAttribute('id')},
dataType: 'json',
success: function(data){
var comment_user = '<b>'+data.user+'</b>';
var comment_para = '<p>'+data.comment+'</p>';
commentContainer.prepend(comment_para);
commentContainer.prepend(comment_user);
commentCount.text(data.comment_count);
$('#comment_form'+t.getAttribute('id')).trigger('reset');
}
});
});
</script>
{% endblock %}
profile.html
{% extends 'base.html' %}
{% load static %}
{% block title %}Profile{% endblock %}
{% block body %}
<div class="container-fluid my-4">
<div class="row">
<div class="col-4 mx-2 bg-light text-dark">
<div class="row">
<div class="col">
<div class="container my-3 text-center">
{% if user_data.profile_pic %}
<img src="{% static user_data.profile_pic.url %}" class="w-25" style="float: left;">
{% endif %}
<h3 class="text-center">{{user_data.full_name}}</h3>
<b class="mx-4 text-center"><span style="text-decoration: none;"><span id="follower_count">{{followers_count}}</span> Followers</span></b>
     
<b class="text-center"><span href="" style="text-decoration: none;">{{following_count}} Following</span></b>
<br>
{% if user_data.user_name != request.session.user %}
<button class="btn btn-outline-primary" id="follow_btn">
{% if is_followed %}
Unfollow
{% else %}
Follow
{% endif %}
</button>
{% endif %}
</div>
</div>
</div>
<div class="row">
<div class="col">
<b class="mx-4">Bio: </b>
<pre><p class="mx-4">{{user_data.bio}}</p></pre>
</div>
</div>
<hr>
<div class="container-fluid">
<span class="text-muted">Email: </span>{{user_data.email}}
<br>
<span class="text-muted">Date Joined: </span>{{user_data.date_joined}}
<br>
</div>
<hr>
{% if user_data.user_name == request.session.user %}
<button class="btn btn-primary w-100" data-bs-toggle="modal" data-bs-target="#editModal">Edit Profile</button>
{% endif %}
</div>
<!--Edit Profile Modal-->
<div class="modal fade" id="editModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-scrollable">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Edit Profile</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<form action="{% url 'update_profile' %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
<div class="mb-2">
<div class="row">
<div class="col-7">
<label for="imgSection" class="form-label"><b>Choose Image</b></label>
<input type="file" name="new_img" class="form-control" id="imgSection">
</div>
<div class="col">
<h6>Current Image</h6>
<img src="{% static user_data.profile_pic.url %}" class="w-50">
</div>
</div>
</div>
<div class="mb-2">
<label for="emailSection" class="form-label"><b>Email</b></label>
<input type="email" name="mail" class="form-control" id="emailSection" value="{{user_data.email}}">
</div>
<div class="mb-2">
<label for="bioSection" class="form-label"><b>Bio (<span id="bio_len">0</span>/150)</b></label>
<textarea class="form-control" name="bio" id="bio">{{user_data.bio}}</textarea>
</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" id="update_btn">Update</button>
</div>
</form>
</div>
</div>
</div>
</div>
<div class="col-7 mx-2">
<ul class="nav nav-pills mb-3" id="pills-tab" role="tablist">
<li class="nav-item" role="presentation">
<a class="nav-link active" id="pills-home-tab" data-bs-toggle="pill" href="#pills-home" role="tab" aria-controls="pills-home" aria-selected="true">List View</a>
</li>
<li class="nav-item" role="presentation">
<a class="nav-link" id="pills-profile-tab" data-bs-toggle="pill" href="#pills-profile" role="tab" aria-controls="pills-profile" aria-selected="false">Grid View</a>
</li>
</ul>
<hr>
<div class="tab-content" id="pills-tabContent">
<!--List View-->
<div class="tab-pane fade show active" id="pills-home" role="tabpanel" aria-labelledby="pills-home-tab">
{% if posts %}
{% for post in posts %}
<div class="card border-success bg-light text-dark" id="div{{post.id}}" style="width: 31rem;">
<img src="{% static post.img.url %}" class="card-img-top" alt="..." style="">
<div class="card-body">
<p class="card-text">{{post.desc}}</p>
<button class="btn btn-primary like_btn" id="{{post.id}}"><span id="list_likes_count{{post.id}}">{{post.likes.count}}</span> <span id="sign{{post.id}}">
{% if session_obj in post.likes.all %}
<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"/>
{% else %}
<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>
{% endif %}
</span></button>
<button type="button" class="btn btn-success" data-bs-toggle="modal" data-bs-target="#exampleModal{{post.id}}"><span id="comment_count{{post.id}}">{{post.comment_set.count}}</span> Comment</button>
{% if user_data.user_name == request.session.user %}
<button class="btn btn-danger del_btn" id="delete{{post.id}}" style="float: right;">Delete</button>
{% endif %}
<br>
<span class="text-muted">{{post.pub_date}}</span>
</div>
</div>
<hr>
<!--Comment Modal-->
<div class="modal fade" id="exampleModal{{post.id}}" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-scrollable">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Public Comments</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="mb-2">
<form id="comment_form{{post.id}}">
<input type="text" class="form-control" placeholder="Add Comment..." id="comment_box{{post.id}}">
</form>
</div>
<div class="mb-3">
<div class="container" id="comment_container{{post.id}}">
{% for comment in post.comment_set.all %}
<b>
{{comment.user}}
</b>
<p>
{{comment.comment}}
</p>
{% endfor %}
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary comment_btn" id="{{post.id}}">Add Comment</button>
</div>
</div>
</div>
</div>
{% endfor %}
{% else %}
<div class="card text-center">
<h1>No Posts Yet.</h1>
</div>
{% endif %}
</div>
<!--Grid View-->
<div class="tab-pane fade" id="pills-profile" role="tabpanel" aria-labelledby="pills-profile-tab">
{% if posts %}
<div class="row row-cols-1 row-cols-md-3 g-4">
{% for post in posts %}
<div class="col">
<div class="card" id="card{{post.id}}">
<img src="{% static post.img.url %}" class="card-img-top" alt="...">
<div class="card-body">
<p class="card-text">{{post.desc}}</p>
<p><b>
<span id="grid_likes_count{{post.id}}">{{post.likes.count}}</span>
Likes</b></p>
<p><b>
<span id="grid_comments_count{{post.id}}">{{post.comment_set.count}}</span>
Comments</b></p>
<span class="text-muted">{{post.pub_date}}</span>
</div>
</div>
</div>
{% endfor %}
</div>
{% else %}
<div class="card text-center">
<h1>No Posts Yet.</h1>
</div>
{% endif %}
</div>
</div>
</div>
</div>
</div>
<script type="text/javascript">
// Limit The Length of User Bio
var bio = $('#bio');
bio.on('input', function(){
var bio_len = $('#bio_len');
var text_length = bio.val().length;
if(text_length>150)
{
bio_len.text(text_length);
$('#bio_len').css('color', 'red');
document.getElementById('update_btn').disabled = true;
}
else
{
bio_len.text(text_length);
$('#bio_len').css('color', 'black');
document.getElementById('update_btn').disabled = false;
}
});
</script>
<script type="text/javascript">
// Add Likes
var like_btn = $('.like_btn');
var list_likes_count = $('#likes_count');
like_btn.on('click', function(event){
event.preventDefault();
var t = this;
$.ajax({
url: '{% url "add_like" %}',
data: {postId: this.getAttribute('id')},
dataType: 'json',
success: function(data){
$('#list_likes_count'+t.getAttribute('id')).text(data.post_likes);
$('#grid_likes_count'+t.getAttribute('id')).text(data.post_likes);
var sign = $('#sign'+t.getAttribute('id'));
if(data.isLiked)
{
sign.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>');
}
else
{
sign.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"/>');
}
}
});
});
</script>
<script type="text/javascript">
// Add Comments
var comment_btn = $('.comment_btn');
comment_btn.on('click', function(event){
event.preventDefault();
var t = this;
var comment_val = $('#comment_box'+t.getAttribute('id')).val();
var commentContainer = $('#comment_container'+t.getAttribute('id'));
var commentCount = $('#comment_count'+t.getAttribute('id'));
$.ajax({
type: 'GET',
url: '{% url "add_comment" %}',
data: {comment: comment_val, post_id: t.getAttribute('id')},
dataType: 'json',
success: function(data){
var comment_user = '<b>'+data.user+'</b>';
var comment_para = '<p>'+data.comment+'</p>';
commentContainer.prepend(comment_para);
commentContainer.prepend(comment_user);
commentCount.text(data.comment_count);
$('#grid_comments_count'+t.getAttribute('id')).text(data.comment_count);
$('#comment_form'+t.getAttribute('id')).trigger('reset');
}
});
});
</script>
<script type="text/javascript">
// Add Follower
var follow_btn = $('#follow_btn');
follow_btn.on('click', function(event){
event.preventDefault();
var f_count = $('#follower_count');
$.ajax({
type: 'GET',
url: '{% url "follow_user" %}',
data: {userId: '{{user_data.id}}'},
dataType: 'json',
success: function(data){
if(data.isFollowed)
{
follow_btn.text('Follow');
f_count.text(data.followers_count);
}
else
{
follow_btn.text('Unfollow');
f_count.text(data.followers_count);
}
}
})
});
</script>
<script type="text/javascript">
//delete post ajax
var del_btn = $('.del_btn');
del_btn.on('click', function(e){
e.preventDefault();
var a = confirm('Would you like to delete this post?');
var t = this;
var post_id = t.getAttribute('id').slice(6);
if(a)
{
$.ajax({
type: 'GET',
url: '{% url "delete_post" %}',
data: {postId: post_id},
dataType: 'json',
success: function(data){
$('div').remove('#div'+data.id);
$('div').remove('#card'+data.id);
}
});
}
});
</script>
{% endblock %}
upload.html
{% extends 'base.html' %}
{% block title %}Upload{% endblock %}
{% block body %}
<div class="container my-4">
<div class="row">
<div class="col">
<form action="{% url 'upload_post' %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
<div class="mb-3">
<h3>Upload<span style="color: red;">Now</span></h3>
</div>
<hr>
<div class="mb-3">
<label for="exampleFormControlInput1" class="form-label">Image</label>
<input type="file" name="file_name" accept="image/*" class="form-control" id="exampleFormControlInput" required>
</div>
<div class="mb-3">
<label for="exampleFormControlPassword" class="form-label">Description</label>
<textarea name="desc" class="form-control" style="height: 200px;"></textarea>
</div>
<input type="submit" name="" value="Upload" class="btn btn-outline-success">
</form>
</div>
</div>
</div>
{% endblock %}
search.html
{% extends 'base.html' %}
{% load static %}
{% block title %}Search Results{% endblock %}
{% block body %}
<div class="contaiiner w-50 mx-4 my-4">
<h1>Search Results: </h1>
{% if results %}
{% for result in results %}
<div class="card my-4 border border-success text-center">
<div class="row">
<div class="col-3 mx-4">
<img src="{% static result.profile_pic.url %}" class="img-thumbnail mx-4 w-50" style="border-radius: 50%;">
</div>
<div class="col-6">
<h3 class="card-title my-3"><a href="{% url 'profile' result.user_name %}" style="text-decoration: none; float: left;">{{result.user_name}}</a></h3>
</div>
</div>
</div>
{% endfor %}
{% else %}
<div class="container">
<h3 class="text-center">No Results Found.</h3>
</div>
{% endif %}
</div>
{% endblock %}
Do you like it?
Send me your feedback because it incourage me to create more amazing content.
Top comments (8)
Oh wow! Is this code available on GitHub? Having it in a post is not really easy to read.
github.com/MadhubanKhatri/friendbo...
Do you hv a Hosted site's link?!
Sounds cool
No. I didn't host it.
Anyway, it seems Great in the Video!
Very nice!
Thank h
That's nice . Great work