0

i check with django document and But my problem was not solved [08/Feb/2023 15:57:18] "POST /courses/2/learning-django HTTP/1.1" 403 2506 error: Forbidden (CSRF token missing.): /courses/2/learning-django

this is my models

class Review(models.Model):
    course = models.ForeignKey(Product, on_delete=models.CASCADE, related_name='reviews')
    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)
    rating = models.IntegerField(null=True, validators=[MinValueValidator(1), MaxValueValidator(5)])
    comment = models.TextField()
    created = models.DateField(auto_now_add=True)
    active = models.BooleanField(default=False)
    
    def __str__(self):
        return f'{self.first_name} {self.last_name}

my views:

def productDetailView(request, id, slug):
    product = get_object_or_404(Product, id=id, slug=slug, available=True)
    new_comment = None
    
    if request.method == 'POST':
        form = ReviewForm(request.POST)
        if form.is_valid():
            new_comment = form.save(commit=False)
            new_comment.course = product
            new_comment.rating = request.POST['rating']
            new_comment.save()
    else:
        form = ReviewForm()
    
    return render(request, 'shop/product_detail.html', {'product': product, 'form': form})

js function:

$(document).ready(function(){
        $('.rate .rate-item').on('click', function(){
            var value = $(this).data('value');
            $.ajax({
                url: '{{ product.get_absolute_url }}',
                type: 'POST',
                data: {'rating': value},
                success: function(response){
                    alert('Rating saved successfully!');
                }
            });
        });
    });

my template

<form method="post">                                            
<div class="row">
<div class="col-md-6">
<div class="form-singel">
{{ form.first_name|attr:" placeholder:Fast name" }}
</div>
</div>
<div class="col-md-6">
<div class="form-singel">
{{ form.first_name|attr:" placeholder:Last Name"}}
</div>
</div>
<div class="col-lg-12">
<div class="form-singel">
<div class="rate-wrapper">
<div class="rate-label">Your Rating:</div>
<div class="rate">
<div data-value="1" class="rate-item"><i class="fa fa-star" aria-hidden="true"></i></div>
<div data-value="2" class="rate-item"><i class="fa fa-star" aria-hidden="true"></i></div>
<div data-value="3" class="rate-item"><i class="fa fa-star" aria-hidden="true"></i></div>
<div data-value="4" class="rate-item"><i class="fa fa-star" aria-hidden="true"></i></div>
<div data-value="5" class="rate-item"><i class="fa fa-star" aria-hidden="true"></i></div>
</div>
</div>
</div>
</div>
<div class="col-lg-12">
<div class="form-singel">
{{ form.first_name|attr:" placeholder:Comment" }}                                                                                               
</div>
</div>
{% csrf_token %} 
<div class="col-lg-12">
<div class="form-singel">
<button type="submit" class="main-btn">Post Comment</button>
</div>
</div>
</div> <!-- row -->                                 
</form>

I used csrf_token in my form but it seems that dosen't work and i searched in stackoverflow no one have same error

how do i fix it

MMEEUR
  • 57
  • 6

2 Answers2

0

If you want to make AJAX request, you need to add CSRF token to the data body.

$.ajax({
    url: '{{ product.get_absolute_url }}',
    type: 'POST',
    data: {'rating': value, csrfmiddlewaretoken: '{{ csrf_token }}'},
    success: function(response){
        alert('Rating saved successfully!');
    }
});

Original answer: https://stackoverflow.com/a/6170377/5711733

Michał
  • 438
  • 3
  • 7
  • 1
    This solution is fine until you want to use javascript in external files placed in static - you can't access context variables from `.js` files. So if author is considering that he should load csrftoken from cookies. – Patryk Szczepański Feb 08 '23 at 17:41
  • i suppose author is using JS inside a template, because he/she used `'{{ product.get_absolute_url }}'` tag. Thanks for your additional answer. – Michał Feb 08 '23 at 17:53
  • Yeah I know that, I just wanted to make he is sure what todo if he will not use Django templates but javascript files instead. – Patryk Szczepański Feb 08 '23 at 18:14
0

Basically what you miss is csrftoken in the form data.

You have two possibilities:

Either define view with @csrf_exempt:

from django.views.decorators.csrf import csrf_exempt

@csrf_exempt
def productDetailView(request, id, slug):
    product = get_object_or_404(Product, id=id, slug=slug, available=True)
    new_comment = None

Or load variable from cookie and pass it into headers (I'm using js-cookie library but you can find single functions on stack overflow that will fit your needs) - example:

$.ajax({
    url: url,
    type: 'POST',
    headers: {
        'X-CSRFTOKEN': Cookies.get('csrftoken'),
    },
    success: (data) => {
        location.reload();
    }
})

From what I know first solution should be more secure.

Patryk Szczepański
  • 731
  • 1
  • 4
  • 12
  • now when i post the the comment it doesn't save in the Database how do i fix this – MMEEUR Feb 08 '23 at 19:36
  • class ReviewForm(forms.ModelForm): | class Meta: | model = Review | fields = ('first_name', 'last_name', 'comment') – MMEEUR Feb 08 '23 at 19:37
  • Your modelform defines other fields that you handle in frontend with rating package - you need to fit fields pass logic into form validation. – Patryk Szczepański Feb 08 '23 at 20:29