Home > Back-end >  Double post after refresh django
Double post after refresh django

Time:06-26

After i posted my comment and deside to refresh the page it adds the same comment over and over on every refresh how can i stop this?

The code for the comment review is at the far bottom in the template.html. And the review code is under "def product_detail" in the views.py

Hope someone can give me some tips so if i refresh it dosent do another post.

template

{% extends "base.html" %}
{% load static %}

{% block page_header %}
    <div >
        <div >
            <div ></div>
        </div>
    </div>
{% endblock %}

{% block content %}
    <div ></div>
    <div >
        <div >
            <div >
                <div >
                    {% if product.image %}
                        <a href="{{ product.image.url }}" target="_blank">
                            <img  src="{{ product.image.url }}" alt="{{ product.name }}">
                        </a>
                        {% else %}
                        <a href="">
                            <img  src="{{ MEDIA_URL }}noimage.png" alt="{{ product.name }}">
                        </a>
                    {% endif %}
                </div>
            </div>
            <div >
                <div >
                    <p >{{ product.name }}</p>
                    <p >${{ product.price }}</p>
                    {% if product.category %}
                    <p >
                        <a  href="{% url 'products' %}?category={{ product.category.name }}">
                            <i ></i>{{ product.category.friendly_name }}
                        </a>
                    </p>
                    {% endif %}
                    {% if product.get_rating > 0 %}
                        <small ><i ></i>{{ product.get_rating }} / 5</small>
                    {% else %}
                        <small >No Rating</small>
                    {% endif %}
                    {% if request.user.is_superuser %}
                        <small >
                            <a href="{% url 'edit_product' product.id %}">Edit</a> |
                            <a  href="{% url 'delete_product' product.id %}">Delete</a>
                        </small>
                    {% endif %}
                    <p >{{ product.description }}</p>
                    <form  action="{% url 'add_to_bag' product.id %}" method="POST">
                        {% csrf_token %}
                        <div >
                            {% with product.has_sizes as s %}
                            {% if s %}
                                <div >
                                    <p><strong>Size:</strong></p>
                                    <select  name="product_size" id='id_product_size'>
                                        <option value="xs">XS</option>
                                        <option value="s">S</option>
                                        <option value="m" selected>M</option>
                                        <option value="l">L</option>
                                        <option value="xl">XL</option>
                                    </select>
                                </div>
                            {% endif %}
                            <div >
                                <p ><strong>Quantity:</strong></p>
                                <div >
                                    <div >
                                        <div >
                                            <button  
                                                data-item_id="{{ product.id }}" id="decrement-qty_{{ product.id }}">
                                                <span >
                                                    <i ></i>
                                                </span>
                                            </button>
                                        </div>
                                        <input  type="number"
                                            name="quantity" value="1" min="1" max="99"
                                            data-item_id="{{ product.id }}"
                                            id="id_qty_{{ product.id }}">
                                        <div >
                                            <button 
                                                data-item_id="{{ product.id }}" id="increment-qty_{{ product.id }}">
                                                <span >
                                                    <i ></i>
                                                </span>
                                            </button>
                                        </div>
                                    </div>
                                </div>
                            </div>

                            <div >
                                <a href="{% url 'products' %}" >
                                    <span >
                                        <i ></i>
                                    </span>
                                    <span >Keep Shopping</span>
                                </a>
                                <input type="submit"  value="Add to Bag">
                            </div>
                            <input type="hidden" name="redirect_url" value="{{ request.path }}">
                            {% endwith %}
                        </div>
                    </form>
                </div>
            </div>
        </div>

        <div >
            <h2 >Reviews</h2>

            {% if request.user.is_authenticated %}
                <form method="post" action="." >
                    {% csrf_token %}

                    <div>
                        <label>Rating</label><br>
                        <select  name="rating">
                            <option value="1">1</option>
                            <option value="2">2</option>
                            <option value="3" selected>3</option>
                            <option value="4">4</option>
                            <option value="5">5</option>
                        </select>
                    </div>

                    <div >
                        <label for="comment">Comment</label>
                        <textarea  rows="5" id="comment" name="content"></textarea>
                      </div>
                      <button type="submit" >Submit</button>

                </form>
            {% endif %}

            {% for review in reviews %}
            <div >
                <strong>Author:</strong> {{ review.created_by }}<br>
                <strong>Rating:</strong> {{ review.rating }}/5<br>
                <strong>Date:</strong> {{ review.created_at|date:"Y-m-d" }}<br>
                <strong>Comment:</strong><br>
                {{ review.content }}
            </div>
        {% endfor %}
    </div>
</div>
{% endblock %}

{% block postloadjs %}
{{ block.super }}
{% include 'products/includes/quantity_input_script.html' %}
{% endblock %}

views.py

from django.shortcuts import render, redirect, reverse, get_object_or_404
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.db.models import Q
from django.db.models.functions import Lower

from .models import Product, Category, Review
from .forms import ProductForm

# Create your views here.

def all_products(request):
    """ A view to show all products, including sorting and search queries """

    products = Product.objects.all()
    query = None
    categories = None
    sort = None
    direction = None

    if request.GET:
        if 'sort' in request.GET:
            sortkey = request.GET['sort']
            sort = sortkey
            if sortkey == 'name':
                sortkey = 'lower_name'
                products = products.annotate(lower_name=Lower('name'))
            if sortkey == 'category':
                sortkey = 'category__name'
            if 'direction' in request.GET:
                direction = request.GET['direction']
                if direction == 'desc':
                    sortkey = f'-{sortkey}'
            products = products.order_by(sortkey)
            
        if 'category' in request.GET:
            categories = request.GET['category'].split(',')
            products = products.filter(category__name__in=categories)
            categories = Category.objects.filter(name__in=categories)

        if 'q' in request.GET:
            query = request.GET['q']
            if not query:
                messages.error(request, "You didn't enter any search criteria!")
                return redirect(reverse('products'))
            
            queries = Q(name__icontains=query) | Q(description__icontains=query)
            products = products.filter(queries)

    current_sorting = f'{sort}_{direction}'

    context = {
        'products': products,
        'search_term': query,
        'current_categories': categories,
        'current_sorting': current_sorting,
    }

    return render(request, 'products/products.html', context)


def product_detail(request, product_id):
    """ A view to show individual product details """

    product = get_object_or_404(Product, pk=product_id)


    if request.method == 'POST':
        rating = request.POST.get('rating', 3)
        content = request.POST.get('content', '')

        review = Review.objects.create(
            product=product,
            rating=rating,
            content=content,
            created_by=request.user
        )

    reviews = Review.objects.filter(product=product)
    context = {
        'product': product,
        'reviews': reviews
    }

    return render(request, 'products/product_detail.html', context)


@login_required
def add_product(request):
    """ Add a product to the store """
    if not request.user.is_superuser:
        messages.error(request, 'Sorry, only store owners can do that.')
        return redirect(reverse('home'))

    if request.method == 'POST':
        form = ProductForm(request.POST, request.FILES)
        if form.is_valid():
            product = form.save()
            messages.success(request, 'Successfully added product!')
            return redirect(reverse('product_detail', args=[product.id]))
        else:
            messages.error(request, 'Failed to add product. Please ensure the form is valid.')
    else:
        form = ProductForm()
        
    template = 'products/add_product.html'
    context = {
        'form': form,
    }

    return render(request, template, context)


@login_required
def edit_product(request, product_id):
    """ Edit a product in the store """
    if not request.user.is_superuser:
        messages.error(request, 'Sorry, only store owners can do that.')
        return redirect(reverse('home'))

    product = get_object_or_404(Product, pk=product_id)
    if request.method == 'POST':
        form = ProductForm(request.POST, request.FILES, instance=product)
        if form.is_valid():
            form.save()
            messages.success(request, 'Successfully updated product!')
            return redirect(reverse('product_detail', args=[product.id]))
        else:
            messages.error(request, 'Failed to update product. Please ensure the form is valid.')
    else:
        form = ProductForm(instance=product)
        messages.info(request, f'You are editing {product.name}')

    template = 'products/edit_product.html'
    context = {
        'form': form,
        'product': product,
    }

    return render(request, template, context)


@login_required
def delete_product(request, product_id):
    """ Delete a product from the store """
    if not request.user.is_superuser:
        messages.error(request, 'Sorry, only store owners can do that.')
        return redirect(reverse('home'))

    product = get_object_or_404(Product, pk=product_id)
    product.delete()
    messages.success(request, 'Product deleted!')
    return redirect(reverse('products'))

CodePudding user response:

You should implement the Post/Redirect/Get architectural pattern [wiki], and thus return a redirect such that the browser will make a GET request next, and thus prevent making another POST request when refreshing the page:

def product_detail(request, product_id):
    product = get_object_or_404(Product, pk=product_id)
    if request.method == 'POST':
        rating = request.POST.get('rating', 3)
        content = request.POST.get('content', '')
        Review.objects.create(
            product=product,
            rating=rating,
            content=content,
            created_by=request.user
        )
        # redirect to the same page            
  • Related