DEV Community

loading...
Cover image for FriendBook - The Social Media

FriendBook - The Social Media

madhubankhatri profile image Madhuban Khatri ・17 min read

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)

Enter fullscreen mode Exit fullscreen mode

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)

Enter fullscreen mode Exit fullscreen mode

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'),

]
Enter fullscreen mode Exit fullscreen mode

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'})
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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 %}
Enter fullscreen mode Exit fullscreen mode

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 %}
Enter fullscreen mode Exit fullscreen mode

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>
                        &nbsp &nbsp &nbsp
                        <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 %}
Enter fullscreen mode Exit fullscreen mode

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 %}
Enter fullscreen mode Exit fullscreen mode

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 %}
Enter fullscreen mode Exit fullscreen mode

Do you like it?
Send me your feedback because it incourage me to create more amazing content.

Discussion (8)

pic
Editor guide
Collapse
neatcoder profile image
Neat Coder

Do you hv a Hosted site's link?!
Sounds cool

Collapse
madhubankhatri profile image
Madhuban Khatri Author

No. I didn't host it.

Collapse
neatcoder profile image
Neat Coder

Anyway, it seems Great in the Video!

Collapse
rishitkhandelwal profile image
Rishit Khandelwal

Oh wow! Is this code available on GitHub? Having it in a post is not really easy to read.

Collapse
madhubankhatri profile image
Collapse
iceorfiresite profile image
Ice or Fire

Very nice!

Collapse
madhubankhatri profile image
Collapse
devparkk profile image
Dev Prakash

That's nice . Great work