Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Double post after refresh django

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.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

template

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

{% block page_header %}
    <div class="container header-container">
        <div class="row">
            <div class="col"></div>
        </div>
    </div>
{% endblock %}

{% block content %}
    <div class="overlay"></div>
    <div class="container-fluid">
        <div class="row">
            <div class="col-12 col-md-6 col-lg-4 offset-lg-2">
                <div class="image-container my-5">
                    {% if product.image %}
                        <a href="{{ product.image.url }}" target="_blank">
                            <img class="card-img-top img-fluid" src="{{ product.image.url }}" alt="{{ product.name }}">
                        </a>
                        {% else %}
                        <a href="">
                            <img class="card-img-top img-fluid" src="{{ MEDIA_URL }}noimage.png" alt="{{ product.name }}">
                        </a>
                    {% endif %}
                </div>
            </div>
            <div class="col-12 col-md-6 col-lg-4">
                <div class="product-details-container mb-5 mt-md-5">
                    <p class="mb-0">{{ product.name }}</p>
                    <p class="lead mb-0 text-left font-weight-bold">${{ product.price }}</p>
                    {% if product.category %}
                    <p class="small mt-1 mb-0">
                        <a class="text-muted" href="{% url 'products' %}?category={{ product.category.name }}">
                            <i class="fas fa-tag mr-1"></i>{{ product.category.friendly_name }}
                        </a>
                    </p>
                    {% endif %}
                    {% if product.get_rating > 0 %}
                        <small class="text-muted"><i class="fas fa-star mr-1"></i>{{ product.get_rating }} / 5</small>
                    {% else %}
                        <small class="text-muted">No Rating</small>
                    {% endif %}
                    {% if request.user.is_superuser %}
                        <small class="ml-3">
                            <a href="{% url 'edit_product' product.id %}">Edit</a> |
                            <a class="text-danger" href="{% url 'delete_product' product.id %}">Delete</a>
                        </small>
                    {% endif %}
                    <p class="mt-3">{{ product.description }}</p>
                    <form class="form" action="{% url 'add_to_bag' product.id %}" method="POST">
                        {% csrf_token %}
                        <div class="form-row">
                            {% with product.has_sizes as s %}
                            {% if s %}
                                <div class="col-12">
                                    <p><strong>Size:</strong></p>
                                    <select class="form-control rounded-0 w-50" 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 class="col-12">
                                <p class="mt-3"><strong>Quantity:</strong></p>
                                <div class="form-group w-50">
                                    <div class="input-group">
                                        <div class="input-group-prepend">
                                            <button class="decrement-qty btn btn-black rounded-0" 
                                                data-item_id="{{ product.id }}" id="decrement-qty_{{ product.id }}">
                                                <span class="icon">
                                                    <i class="fas fa-minus"></i>
                                                </span>
                                            </button>
                                        </div>
                                        <input class="form-control qty_input" type="number"
                                            name="quantity" value="1" min="1" max="99"
                                            data-item_id="{{ product.id }}"
                                            id="id_qty_{{ product.id }}">
                                        <div class="input-group-append">
                                            <button class="increment-qty btn btn-black rounded-0"
                                                data-item_id="{{ product.id }}" id="increment-qty_{{ product.id }}">
                                                <span class="icon">
                                                    <i class="fas fa-plus"></i>
                                                </span>
                                            </button>
                                        </div>
                                    </div>
                                </div>
                            </div>

                            <div class="col{% if s %}-12 mt-2{% endif %}">
                                <a href="{% url 'products' %}" class="btn btn-outline-black rounded-0 mt-5">
                                    <span class="icon">
                                        <i class="fas fa-chevron-left"></i>
                                    </span>
                                    <span class="text-uppercase">Keep Shopping</span>
                                </a>
                                <input type="submit" class="btn btn-black rounded-0 text-uppercase mt-5" value="Add to Bag">
                            </div>
                            <input type="hidden" name="redirect_url" value="{{ request.path }}">
                            {% endwith %}
                        </div>
                    </form>
                </div>
            </div>
        </div>

        <div class="w-full mt-6">
            <h2 class="text-xl">Reviews</h2>

            {% if request.user.is_authenticated %}
                <form method="post" action="." class="mt-6 mb-6 p-6 bg-gray-100 rounded-xl">
                    {% csrf_token %}

                    <div>
                        <label>Rating</label><br>
                        <select class="form-control" 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 class="form-group">
                        <label for="comment">Comment</label>
                        <textarea class="form-control" rows="5" id="comment" name="content"></textarea>
                      </div>
                      <button type="submit" class="btn btn-primary mb-2">Submit</button>

                </form>
            {% endif %}

            {% for review in reviews %}
            <div class="px-4 py-6 bg-gray-100 rounded-xl mb-4">
                <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'))

>Solution :

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 🖟
        return redirect('product_detail', product_id=product_id)

    reviews = Review.objects.filter(product=product)
    context = {
        'product': product,
        'reviews': reviews
    }
    return render(request, 'products/product_detail.html', context)
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading