steps

 1. making virtual environment and creating django project -twittercloneproject

2.creating tweet app for tweet homepage(same dir. of manage.py)-tweets

3.inside tweets->models.py : creating models for tweet

        class Tweet

4. opening manage.py shell and creating some objects of model

      i. python manage.py shell

     ii. from tweets.models import Tweet

   iii.

 or you can create this by creating superuser and going to admin page: but you must register model in admin page

5.register tweets app in settings.py

6.in  urls.py 

    from tweets.views import collect_all_data_from_models_and_render_it_as_json_format ,

path('tweet/',collect_all_data_from_models_and_render_it_as_json_format ),

      

7.in views.py

from .models import Tweet
from django.http.response import JsonResponse
def collect_all_data_from_models_and_render_it_as_json_format(request,*args, **kwargs):
    all_objects=Tweet.objects.all()
    data=[{"id":x.id,"content":x.content,'likes':random.randint(0,100)}for x in all_objects] 
    json_data={"response":data}
    return JsonResponse(json_data) 

you will get json data as API in     http://127.0.0.1:8000/tweet/

8. create model form 

  inside tweets->forms.py

from django import forms
from .models import Tweet
class TweetForm(forms.ModelForm):
    class Meta:
        model=Tweet
fields=['content'] #you can add others also inside this list   
        labels={'content':'enter your content'}
        help_text={'content':'enter your content'} 
        error_messages={'content':{'required':'name is compulsory'}}  #you can give extra error messages giving comma
        widgets={'name':forms.TextInput(attrs={'class':'content','placeholder':'enter content'})}
        #widgets={'password':forms.PasswordInput}   for not showing password if any error occurs 


9.create a form page to add content to your model 

from tweets.views import tweet_form,
path('form',tweet_form),

 in views.py

   def tweet_form(request, *args, **kwargs):

def tweet_form(request, *args, **kwargs):
    if request.method=="POST":
        fm=TweetForm(request.POST)# this will send your all the data to modelform and create new form there
        if fm.is_valid():
            content=fm.cleaned_data['content']
            fm=TweetForm() 
            obj_of_model=Tweet(content=content)
            obj_of_model.save()
   else:
        fm=TweetForm()    
    return render(request, 'components/forms.html',{"form":fm})    



9. create forms.html

{% extends 'base.html' %}
{% block title %}form{% endblock title %}
{% block content %}
<form method="POST">{% csrf_token %}
{{form.as_p}}
<button type="submit" class="btn btn-primary">submit</button>
</form>
{% endblock content %}

to make template you go to tweeterclone i.e base dir : create a folder-> templates

register that template in settings.py

 'DIRS': [os.path.join(BASE_DIR,"templates")],

   inside:

     ->tweets

              ->form.html

              ->navbar.html

            =->footer.html

     ->pages

         ->home.html

     ->components

    base.html

   base.html looks like:

  <!doctype html>

<html lang="en">
  <head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/css/bootstrap.min.css" integrity="sha384-B0vP5xmATw1+K9KRQjQERJvTumQW0nPEzvF6L/Z6nronJ3oUOFUFpCjEUQouq2+l" crossorigin="anonymous">

    <title>{% block title %}{% endblock title %}</title>
  </head>
  <style>
  .bg_tweetme{background-color: brown;}
  </style>
  <body>
    {% include "components/navbar.html" %}
    <div class="container">
    {% block content %}
    {% endblock content %}
    </div>

    <!-- Optional JavaScript; choose one of the two! -->

    <!-- Option 1: jQuery and Bootstrap Bundle (includes Popper) -->
    <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-Piv4xVNRyMGpqkS2by6br4gNJ7DXjqk09RmUpJ8jgGtD7zP9yug3goQfGII0yAns" crossorigin="anonymous"></script>

    <!-- Option 2: Separate Popper and Bootstrap JS -->
    <!--
    <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/js/bootstrap.min.js" integrity="sha384-+YQ4JLhjyBLPDQt//I+STsc9iw4uQqACwlvpslubQzn4u2UU2UFM80nGisd026JF" crossorigin="anonymous"></script>
    -->
  </body>
</html>

navbar.html is 

<nav class="navbar navbar-expand-lg navbar-dark bg_tweetme mb-4">
  <a class="navbar-brand" href="/">tweetme</a>
  <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
    <span class="navbar-toggler-icon"></span>
  </button>

  <div class="collapse navbar-collapse d-none" id="navbarSupportedContent">
    <ul class="navbar-nav mr-auto d-none">
      <li class="nav-item active">
        <a class="nav-link" href="#">Home <span class="sr-only">(current)</span></a>
      </li>
      <li class="nav-item">
        <a class="nav-link" href="#">Link</a>
      </li>
      <li class="nav-item dropdown">
        <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
          Dropdown
        </a>
        <div class="dropdown-menu" aria-labelledby="navbarDropdown">
          <a class="dropdown-item" href="#">Action</a>
          <a class="dropdown-item" href="#">Another action</a>
          <div class="dropdown-divider"></div>
          <a class="dropdown-item" href="#">Something else here</a>
        </div>
      </li>
      <li class="nav-item">
        <a class="nav-link disabled" href="#" tabindex="-1" aria-disabled="true">Disabled</a>
      </li>
    </ul>
    <form class="form-inline my-2 my-lg-0 d-none">
      <input class="form-control mr-sm-2" type="search" placeholder="Search" aria-label="Search">
      <button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button>
    </form>
  </div>

</nav>\


if you go to check json data there will be new data as you entered /form


10. time to render it in homepage:

    in urls.py

    from tweets.views import homeview,

path('',homeview ),


 in views.py

from django.shortcuts import redirect, render
def homeview(request):
    #return HttpResponse("<h1>helloworld</h1>")

    return render(request,"pages/home.html",context={},status=200) 


home.html

 {% extends 'base.html' %}

{% block title %}
this is jinja template
{% endblock title %}
{% block content %}
<h1 class="text-center">welcome to tweetme.to</h1>
<div id="place_inside">
</div>
<script>
var div=document.getElementById("place_inside")
const loadtweets=()=>{
    console.log("fine working")
const xhr=new XMLHttpRequest()
xhr.open("GET","tweet",true);
xhr.onload= function(){
    let response=JSON.parse(xhr.responseText)
    let array=response.response
    array.forEach(function(name){
    let id=name.id
    let content=name.content
    let likes=name.likes
    let handle_tweet=tweet_render(id,content,likes)
    div.innerHTML+=handle_tweet
})
}
xhr.send()

}  
var tweet_render=(id,content,likes)=>{
    let html=`` 
    html=html+` <div id="tweet-${id}" class=" border py-4 px-2 my-2">
                    <span>${id}</span>
                    <span>${content}</span>
                    <div class="mx-4 my-2">
                    <button class="btn btn-primary" onclick=handledidlike(${id},${likes})>${likes} Likes</button>
                    </div>
               </div>
               ` 
    return(html)
}

loadtweets()

let handledidlike=(id,likes)=>{
    console.log(id,likes)
}
</script>
{% endblock content %}


now if you add something in form than it will render in home .HTML

but not in sequential order i.e your data will load at last in homepage

 to render in FIF render

   inside models.py

  class Meta:

        ordering=['-id']
   

 

11. Now add form to your homepage manually

   in home.html add

    <div class="row">

    <div class="col-md-4 mx-auto col-10" >
        <form class="form" method="POST" action="form" id="form">{% csrf_token %}
            <input type="hidden" name="url_redirect" value="/">
            <textarea class="form-control" name="content" placeholder="your tweet" required id="value"></textarea>
            <button class="btn btn-primary" type="submit">tweet</button>    
        </form>
    </div>

  </div>        


 const tweet_control=(e)=>{
          console.log("submitted")
          const myform=e.target
          console.log(myform)
          e.preventDefault()
          const myformdata= new FormData(myform)
          for (const iterator of myformdata.entries()) {
              console.log(iterator)
          }
          let method=myform.getAttribute("method")
          let url=myform.getAttribute("action")
          console.log(method,url)
          const xhr=new XMLHttpRequest()
          xhr.open(method,url,true);
           
        xhr.setRequestHeader("HTTP_X_REQUESTED_WITH"," XMLHttpRequest")  //normally no ajax is there so to pass ajax we use 2 of the
        xhr.setRequestHeader("X-Requested-With"," XMLHttpRequest")     //and it is done so that the response from django views->tweet_form wont return all the html page :

         xhr.onload= function(){
         let response=JSON.parse(xhr.responseText)
         console.log(typeof response)
         console.log(response)
         let id=response.id
         let content=response.content
         let likes=response.likes
         let tweet_to_append=tweet_render(id,content,likes)
         let oghtml=div.innerHTML
         div.innerHTML=tweet_to_append + oghtml
         myform.reset()  //to reset the innerhtml value of form after clicking submit
         }
         xhr.send(myformdata)
         

        
        
    }
form.addEventListener("submit",tweet_control)


update tweet_form as 


def tweet_form(request, *args, **kwargs):
    if request.method=="POST":
        fm=TweetForm(request.POST)# this will send your all the data to modelform and create new form there
        print(fm)
        url_redirect=request.POST.get("url_redirect") #get name of input from home.html(for future use to redirect to home page if clicked on submit :action purpose)
        print("post data is",request.POST) #normally Post request of form will send you all content inside form: i.e name and value: in the form of "name":["value"]
        print("your form will redirect to",url_redirect) #normal printing to know what is happening 
        print(request.is_ajax())  #checking if the req is ajaax or not
        if fm.is_valid():
            content=fm.cleaned_data['content']
            fm=TweetForm() 
            obj_of_model=Tweet(content=content)
            obj_of_model.save()
            if request.is_ajax():  
                return JsonResponse(obj_of_model.serializer(), status=200) #it will go and will print to console and same is the thing for serializer concept :look upppp
            if url_redirect!=None and is_safe_url(url_redirect,ALLOWED_HOSTS):
                return redirect(url_redirect) #redirect is used to redirect to any url while in the middle of working

           
    else:
        fm=TweetForm()    
    return render(request, 'components/forms.html',{"form":fm})    



note: serializer is added so that code is reduced  

  inside models.py


    def serializer(self):
        return {
            "id":self.id,
            "content":self.content,
            'likes':random.randint(0,100)

        }



   




Comments