Implementing a dynamic star rating system with Django using AJAX and JavaScript

Currently, I am in the process of integrating a star rating system into my Django website.

After some research, I came across a star design that I really like on this page: https://www.w3schools.com/howto/howto_css_star_rating.asp

My knowledge of JavaScript, AJAX, and Django is limited at the moment. I'm looking for guidance on how to incorporate the star ratings from the provided example using AJAX and Django to allow database updates without requiring a page refresh when users select a rating.

Additionally, it's crucial that each user can only vote once, meaning they should not be able to rate a page multiple times. To achieve this, an IP check must be implemented. I find the code confusing and need assistance with it.

models.py:

class Rating(models.Model):
    ip = models.CharField(max_length=15)
    post = models.ForeignKey(Post, related_name='ratings', on_delete=models.CASCADE)
    score = models.IntegerField(default=0, 
        validators=[
            MaxValueValidator(5), 
            MinValueValidator(0),
        ]
    )

    def __str__(self):
        return str(self.pk)

views.py:

def RatingView(request):
    obj = Rating.objects.filter(score=0).order_by("?").first()
    context ={
        'object': obj
    }

    return render(request, 'blog/post_detail.html', context)

# def get_client_ip(self, request):
#       x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
#       if x_forwarded_for:
#           ip = x_forwarded_for.split(',')[0]
#       else:
#           ip = request.META.get('REMOTE_ADDR')
#       return ip

def RateView(request):
    if request.method == 'POST':
        element_id = int(request.POST.get('element_id'))
        val = request.POST.get('val')
        print(val)
        obj = Rating.objects.get(id=element_id)
        obj.score = val
        obj.save()
        return JsonResponse({'success':'true', 'score': val}, safe=False)
    return JsonResponse({'success':'false'})

urls.py:

urlpatterns = [
    path('rate/', views.RateView, name='rate'),
    path('<slug:slug>/<slug:post_slug>/', views.PostDetailView.as_view(), name='detail'),
    path('<slug:slug>/', views.CategoryView.as_view(), name='category'),
    path('', views.HomeView.as_view(), name='home'),
]

html:

<div class="col text-center">
    <form class="rate-form" action="" method="POST" id="{{ object.id }}">
        {% csrf_token %}
        <button type="submit" class="fa fa-star my-btn" id="first"></button>
        <button type="submit" class="fa fa-star my-btn" id="second"></button>
        <button type="submit" class="fa fa-star my-btn" id="third"></button>
        <button type="submit" class="fa fa-star my-btn" id="fourth"></button>
        <button type="submit" class="fa fa-star my-btn" id="fifth"></button>
    </form>
    <br>
    <div id="confirm-box"></div>
</div>

JavaScript:

// Stars
const one = document.getElementById('first')
const two = document.getElementById('second')
const three = document.getElementById('third')
const four = document.getElementById('fourth')
const five = document.getElementById('fifth')

const form = document.querySelector('.rate-form')
const confirmBox = document.getElementById('confirm-box')
const csrf = document.getElementsByName('csrfmiddlewaretoken')

const handleStarSelect = (size) => {
    const children = form.children
    console.log(children[0])
    for (let i=0; i < children.length; i++) {
        if(i <= size) {
            children[i].classList.add('checked')
        } else {
            children[i].classList.remove('checked')
        }
    }
}

const handleSelect = (selection) => {
    switch(selection){
        case 'first':{
            handleStarSelect(1)
            return
        }
        case 'second':{
            handleStarSelect(2)
            return
        }
        case 'third':{
            handleStarSelect(3)
            return
        }
        case 'fourth':{
            handleStarSelect(4)
            return
        }
        case 'fifth':{
            handleStarSelect(5)
            return
        }
    }
}

const getNumericValue = (stringValue) =>{
    let numericValue;
    if (stringValue === 'first') {
        numericValue = 1
    } 
    else if (stringValue === 'second') {
        numericValue = 2
    }
    else if (stringValue === 'third') {
        numericValue = 3
    }
    else if (stringValue === 'fourth') {
        numericValue = 4
    }
    else if (stringValue === 'fifth') {
        numericValue = 5
    }
    else {
        numericValue = 0
    }
    return numericValue
}

if (one) {
    const arr = [one, two, three, four, five]

    arr.forEach(item=> item.addEventListener('mouseover', event=>{
        handleSelect(event.target.id)
    }))

    arr.forEach(item=> item.addEventListener('click', (event)=>{
        const val = event.target.id
        console.log(val)

        form.addEventListener('submit', e=>{
            e.preventDefault()
            const id = e.target.id
            console.log(id)
            const val_num = getNumericValue(val)


            $.ajax({
                type: 'POST',
                url: '/rate/',
                data: {
                    'csrfmiddlewaretoken': csrf[0].value,
                    'element_id': id,
                    'val': val_num,
                },
                success: function(response){
                    console.log(response)
                    confirmBox.innerHTML = `<p>Successfully rated with ${response.score}</p>`
                },
                error: function(error){
                    console.log(error)
                    confirmBox.innerHTML = '<p>Oops... Something went wrong...</p>'
                }
            })
        })
    }))
}

And regarding the error message:

4
Internal Server Error: /rate/
Traceback (most recent call last):
  File "/home/kali/Django/personal_blog/venv/lib/python3.9/site-packages/django/core/handlers/exception.py", line 47, in inner
    response = get_response(request)
  File "/home/kali/Django/personal_blog/venv/lib/python3.9/site-packages/django/core/handlers/base.py", line 181, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/home/kali/Django/personal_blog/src/blog/views.py", line 91, in RateView
    obj = Rating.objects.get(id=element_id)
  File "/home/kali/Django/personal_blog/venv/lib/python3.9/site-packages/django/db/models/manager.py", line 85, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/home/kali/Django/personal_blog/venv/lib/python3.9/site-packages/django/db/models/query.py", line 435, in get
    raise self.model.DoesNotExist(
blog.models.Rating.DoesNotExist: Rating matching query does not exist.
[29/Nov/2021 00:18:19] "POST /rate/ HTTP/1.1" 500 86956

I suspect the issue lies in the URL configuration. Any suggestions on how to resolve this problem?

screenshot

Answer №1

The problem does not seem to be with the URL but rather with the query

obj = Rating.objects.get(id=element_id)
. It appears that there is no rating object corresponding to the id of element_id.

To troubleshoot this issue, you should verify if the Rating id is being passed correctly from RatingView all the way to RateView through the Template and JS.

One possibility is that obj is empty in RatingView initially, so start by checking that.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Is there a way to integrate Prettify with Blogger/BlogSpot?

I am currently utilizing blogger.com as a platform to showcase programming texts and I am interested in incorporating Prettify (similar to Stack Overflow) to enhance the appearance of my code samples. What is the best method for installing the Prettify sc ...

What specific files from the Kendo core are required for utilizing Mobile and Angular functionalities?

After browsing through similar questions, I couldn't find a solution. Currently, I am experimenting with Kendo (open source core for now) in a Visual Studio Cordova project. Initially, disregarding Cordova, I am focusing on setting up a basic view wit ...

Launch the sidebar window using jQuery

I've been attempting to create something similar to this. However, I'm having trouble replicating it exactly. What I've attempted I've managed to create a replica, but the issue is that the buttons are fixed. Could setting the left ...

Troubleshooting problem with Zscaler and Ajax communication

When making an AJAX call on my website, everything runs smoothly except for when it is accessed behind a Zscaler proxy. In that case, the browser throws a CORS error: "No 'Access-Control-Allow-Origin' header is present on the requested resource. ...

AngularJS: Utilizing services to make API requests and retrieve JSON data

I am struggling to pass a value from an input field on the view using a service. The service is supposed to call my WebAPI2 and then receive a valid JSON as a response. Unfortunately, I keep getting a promise object that I cannot resolve (even with ".then ...

Is there a way to stop the execution of myFunc after it has been performed 5 times using clearInterval?

This code is designed to notify online shoppers that they need to choose a color from a dropdown menu before adding an item to their shopping cart. If no color is selected, the text will blink to alert them. How can I modify this code so that the blinking ...

Leveraging $this in conjunction with a jQuery plugin

I'm experimenting with a code snippet to reverse the even text in an unordered list: $(document).ready(function () { $.fn.reverseText = function () { var x = this.text(); var y = ""; for (var i = x.length - 1; i >= 0; ...

Updating div constantly with onclick using jQuery Ajax

I've been attempting to refresh the content of a div after clicking a button, but it only happens once. I have to refresh the page in order to click the button again and update the content. Since I'm new to AJAX, I need some help resolving this i ...

Preventing AttributeError 'object has no attribute' error when accessing a model field without using try/except

I have a query: (I am developing using Django 1.8 and Python 2.7.15) I fetch an object from the database: shop_users = ShopUsers.objects.get(pk=_id) If the object exists, I prepare data for the View: if shop_users: data = { 'full_name&a ...

The recurring loop issue persists when trying to edit the save() function in a Django

I am currently working on creating a model that utilizes the Google Map API. The goal is to collect and store specific data if an object does not already exist. This includes the name, address, longitude, latitude, and Google place ID. Unfortunately, I h ...

Trouble with firing the click event using document.createElement('a') in Firefox

I wrote a function that fetches arraybuffer data from my API, generates a temporary anchor element on the webpage, and then triggers a click event to download the file. Interestingly, this function performs as expected in Chrome. @action async loadVouc ...

What is the equivalent of Buffer.from(<string>, 'hex') in Python?

I am currently facing the challenge of translating a Typescript library into Python. The specific library I am working with is bs58 in Typescript and its counterpart base58 in Python. My issue arises when attempting to replicate the following code: const ...

Display PDF in Forge Viewer using PDF Extension - warning generated by pdf.worker.js

Whenever we attempt to display a PDF file using our own API, the pdf.worker.js generates a warning message and the PDF always appears completely white. https://i.stack.imgur.com/IqGML.png All I can see is this (it's a wide PDF that renders fine in t ...

The sequence of execution in React hooks with Typescript

I'm having difficulty implementing a language switching feature. On the home page of my app located at /, it should retrieve a previously set preference from localStorage called 'preferredLanguage'. If no preference is found, it should defau ...

Using setInterval in pugjs

Trying to implement a time creator using mixins in PugJS. I am getting special names from other pages as "type" but encountering an unexpected text error on the second to last line. I have been unable to resolve it, could you please assist? mixin createT ...

Encountering an Issue in Angular 5: Trouble Retrieving Information from Local JSON Source [object Object]

Trying to fetch data from a file named sampledata.json Issues: {{sampledata}} is showing [object Object] {{sampleDataModel.Title}} is throwing an error: TypeError: Cannot read property 'Title' of undefined Contents of sampledata.json: { ...

Discover the process for finding a Youtube Channel Name with querySelectorAll

OUTPUT : Console URL : https://www.youtube.com/feed/trending?gl=IN document.querySelectorAll('a[class="yt-simple-endpoint style-scope yt-formatted-string"]')[0].innerText; document.querySelectorAll('a[class="yt-simple-endpoi ...

Whenever I try to relocate my HTML file that references three.js, the three.js library seems to malfunction and stop

Something strange is happening... I recently downloaded three.js into a directory named 'brick': git clone https://github.com/mrdoob/three.js.git which created a subdirectory: brick/three.js/ After navigating to brick/three.js/examples ...

When I attempt to send a PUT request, the req.body object appears to be empty. This issue is occurring even though I have implemented the method override middleware

I am currently facing an issue with updating a form using the put method. To ensure that my form utilizes a PUT request instead of a POST, I have implemented the method override middleware. However, upon checking the req.body through console log, it appear ...

I am experiencing an issue where the button I place inside a material-ui table is unresponsive to clicks

Here is the structure of my table: <TableContainer component={Paper} style={{height: "40vh", width: "90vh"}}> <Table size="small" sx={{ minWidth: 200 }}> <TableHea ...