linking JavaScript code to Django database upon clicking on a button

Question:

I’m asked to work on a networking website that is like Twitter. I work with HTML,CSS, Javascript for the client-side and Django for the server-side. I’m trying to link between Javascript and Django using JSON and fetch as I want to create a button in each of the users’ profile that upon being clicked by the registered user, it makes the registered follow the profile as it is saved in django database as a model containing the follower(follower) and the user followed(following) but upon clicking on follow button (in user.html) it doesn’t save any data in the database

in models.py:

class follow(models.Model):
    follower = models.ForeignKey("User",on_delete=models.CASCADE, related_name="follower")
    following = models.ForeignKey("User",on_delete=models.CASCADE, related_name="following") 

in user.html(contains the script):

<html>
    <head>
        <script>
            document.addEventListener('DOMContentLoaded',function(){
                document.querySelectorAll('input').forEach(input =>{
                    input.addEventListener('click', function(){
                        console.log(input.id);
                        let follow_username = input.id
                        fetch('/follow/'+ follow_id, {
                            method:'PUT',
                            body: JSON.stringify({
                                follow: true
                            })
                        })
                    })
                } 
                )
                });
        </script>
    </head>
    <body>
        <h2>{{x.username}}</h2>
<form>
    {% csrf_token %}
<input type="submit" value="follow" name ="follow" id={{x.username}}>
</form>
    </body>
</html>

in urls.py:

from django.urls import path

from . import views

urlpatterns = [
            path("follow/<str:name>", views.Users, name="follow")
]

in views.py:

def Users(request, name):
    x = User.objects.get(username = name)
    if request.method == 'PUT':
        data = json.loads(request.body)
        if data.get('follow') is not None:
            user = request.user
            anotherr = User.objects.filter(username = name)
            another = User.objects.get(username = anotherr).id
            follow.objects.create(follower = user, following = another)
    return render (request, "network/user.html",{"x":x})

upon clicking on the follow button that present in user.html, no data is created in the database. so what is the problem?

Asked By: Mostafa Mohamed

||

Answers:

I’ll throw my best guesses on what’s happening.. Just some improper syntax and undefined variables

View

  1. another / anotherr no, just use x you’re already fetching the user at the top of the view
  2. get_or_create will not allow you to have duplicates / follow someone twice (generally a good idea)
  3. Prints are just debugging, remove after you know it’s working
def Users(request, name):
    x = User.objects.get(username=name)
    
    if request.method == 'PUT':
        print('we've hit put')

        data = json.loads(request.body)

        if data.get('follow') is not None:
            print('in follow')

            # Note: [User Obj Itself]
            #   follower = request.user  (is: <User Obj>)
            #   following = x            (is: <User Obj>)

            followObj, createdBool = follow.objects.get_or_create(follower=request.user, following=x)

            print('followObj', followObj)
            print('created?', createdBool)
        
        print('past follow')

    print('about to render')
    return render (request, "network/user.html",{"x":x})

Template

  1. Idk what follow_id is, just use input.id
<html>
    <head>
        <script>
            document.addEventListener('DOMContentLoaded',function(){
                document.querySelectorAll('input').forEach(input =>{
                    input.addEventListener('click', function(){
                        
                        // this should be true
                        console.log(input.id == '{{x.username}}');


                        console.log('Fetch Url:t' + '/follow/'+ input.id);

                        fetch('/follow/'+ input.id, {
                            method:'PUT',
                            body: JSON.stringify({
                                follow: true
                            })
                        })
                    })
                } 
                )
            });
        </script>
    </head>
    <body>
        <h2>{{x.username}}</h2>
        <form>
            {% csrf_token %}
            <input type="submit" value="follow" name ="follow" id={{x.username}}>
        </form>
    </body>
</html>

If these don’t work, tell me what print or console.log got hit or didn’t get hit- that’ll really help narrow down the issue even more


Edit

Supposedly this, putting a token in a header, will work if you don’t want to put a @csrf_exempt decorator (which might be a good idea tbh)

fetch('/follow/'+ input.id, {
    method:'PUT',
    headers: { 'X-CSRFToken': $('[name=csrfmiddlewaretoken]').val() },
    body: JSON.stringify({
        follow: true
    })
})
Answered By: Nealium