Bruno
Bruno

Reputation: 651

Create and save django object on click

I have a shoppinglist app. I want that when the user clicks on "add to shopping list" the item is saved to the shopping list.

How can I do that?

in the template I wrote:

<a href="javascript:{document.getElementById('add_item').submit()}" class="btn btn-primary btn-block">Add to
shopping list
</a>
<form action="{% url 'add_to_shopping_list' product.id %}" id="add_item" method="POST">
    {% csrf_token %}
    <input type="hidden">
</form>

in urls.py I dispaced the urls like this:

urlpatterns = [
    path('add_to_shopping_list/<int:pk>', views.add_to_shopping_list, name='add_to_shopping_list'),
]

this calls the view add_to_shopping_list where I want create a ShoppingItem object and to link this to the Product object. The problem is that I don't want to redirect the user anywhere, but just stay on the same page without refreshing. But the view wants me to return an HtmlResponse, or I get this error:

The view shoppinglist.views.add_to_shopping_list didn't return an HttpResponse object. It returned None instead.

Is the idea correct? If yes how can I solve this problem? Thanks

EDIT

here is the view.py, this is just the idea, I could not debug it

from . models import ShoppingItem
from products.models import Product

def add_to_shopping_list(request, pk):
    item = Product.objects.get(pk=pk)
    shopping_list = request.user.shopping_lists.all()[0]
    product = ShoppingItem(name=item.name, list=shopping_list, price=item.price)
    product.save()
    return ???

The Product object already exists, but I need to create a ShoppingItem object that is associated to that shopping list that belongs to that user.

Upvotes: 0

Views: 1533

Answers (2)

Bruno
Bruno

Reputation: 651

So I solved it in this way:

view.py

def add_to_shopping_list(request):
    if request.method == 'GET':
        product_id = request.GET.get('product_id')
        product = Product.objects.get(pk=product_id)
        if ShoppingItem.objects.filter(product__id=product_id).exists():
            item = ShoppingItem.objects.filter(product__id=product_id)[0]
            item.quantity +=1
            item.save()
        else:
            shopping_list = request.user.shopping_lists.all()[0]
            product = ShoppingItem(name=product.name, list=shopping_list, price=product.price, product=product)
            product.save()
        return HttpResponse('updated')

    else:
        return HttpResponse('unsuccessful')

main.js uses jQuery

$('.add-to-list').click(function () {
    var id;
    var url;
    id = $(this).attr("data-catid");
    url = $(this).attr("to_java");
    console.log(id);
    $.ajax(
        {
            type: "GET",
            url: url,
            data: {
                product_id: id
            },
            success: function (data) {
                $('#add-to-list' + id).removeClass('btn btn-primary btn-block');
                $('#add-to-list' + id).addClass('btn btn-success btn-block');
                $('#add-to-list' + id).text('Added to the shopping list');
            }
        })
});

template.html

<a to_java="{% url 'add_to_shopping_list' %}" id="add-to-list{{ product.id }}" class="add-to-list btn btn-primary btn-block" data-catid="{{ product.id }}">
 Add to shopping list
</a>

Upvotes: 0

Matej
Matej

Reputation: 820

In template use:

<button id="add-item-btn">Add item</button>
<form action="{% url 'add_to_shopping_list' product.id %}" id="add-item" method="POST">
    {% csrf_token %}
</form>

<script>
    function getCookie(name) {   //function for getting cookie
        var r = document.cookie.match("\\b" + name + "=([^;]*)\\b");
        return r ? r[1] : undefined;
    }


    function ajax(method, url, data, callback){   //function for ajax request
        let xhttp = new XMLHttpRequest();
        xhttp.onreadystatechange = function(){
            if (this.readyState == 4){
                if(callback != null) callback(this.status, this.responseText);
            }
        };
        xhttp.open(method, url, true);
        xhttp.setRequestHeader("X-CSRFToken", getCookie("csrftoken"));   //set CSRF header
        xhttp.send(data);

    }

    document.getElementById("add-item-btn").onclick = function(){   //create onclick event for button
        let url = document.getElementById("add-item").getAttribute("action");   //get action attribute from form
        ajax("POST", url, null, null);   //send request
    };
</script>

The form tag is here just to store data and you can replace it with something else.

In view.py return for example updated text, you can use this response to display Added! message to user:

from django.http import HttpResponse
from . models import ShoppingItem
from products.models import Product

def add_to_shopping_list(request, pk):
    item = Product.objects.get(pk=pk)
    shopping_list = request.user.shopping_lists
    product = ShoppingItem(name=item.name, shopping_list=shopping_list)
    product.save()
    return HttpResponse('updated')

Upvotes: 1

Related Questions