Home > Software design >  I am trying to figure out how to increment and decrement the values with Django but I get this error
I am trying to figure out how to increment and decrement the values with Django but I get this error

Time:06-05

Hi there I am having an issue incrementing and decrement a value in the views.py file in my application, also I am getting the error of "cannot unpack non-iterable ModelBase object" Everything else works beside the increment and decrement function. As soon as I press the increment or the decrement button it does not work and it spits that error out. Also I will post the view.py file, the html file, and the urls just so there can be more context.

the views.py file

from django.shortcuts import get_object_or_404, redirect, render
from django.http import HttpResponse,HttpRequest
from .models import Habit
# Create your views here.

def list_habit_items(request):
    context = {'habit_list':Habit.objects.all()}
    return render(request,'habits/habit_list.html',context)

def insert_habit_item(request:HttpRequest):
    habit=Habit(IndHabit =request.POST['habit'])
    habit.save()
    return redirect('/habits/list/')

def delete_habit_item(request,habit_id):
    habit_to_delete = Habit.objects.get(id=habit_id)
    habit_to_delete.delete()
    return redirect('/habits/list/')
    
def increment_habit_value(request,habit_id):
    habit_to_increment = Habit.objects.get(Habit,id=habit_id)
    habit_to_increment.values  = 1
    habit_to_increment.save(['values'])
    return redirect('/habits/list/')

def decrement_habit_value(request,habit_id):
    habit_to_decrement = Habit.objects.get(Habit,id=habit_id)
    habit_to_decrement.values -= 1
    habit_to_decrement.save(['values'])
    return redirect('/habits/list/')

the models

class Habit(models.Model):
#this makes a attribute that describes the individual Habit
#the individual Habit and Value.
    IndHabit=models.TextField()
   
    IndValue=models.IntegerField()

the urls.py file

from django.urls import path
from . import views



urlpatterns=[
    path('list/',views.list_habit_items),
    path('insert_habit/',views.insert_habit_item,name='insert_habit_item'),
    path('delete_habit/<int:habit_id>',views.delete_habit_item,name='delete_habit_item'),
    path('increment_habit/<int:habit_id>',views.increment_habit_value,name='increment_habit_value'),
    path('decrement_habit/<int:habit_id>',views.decrement_habit_value,name='decrement_habit_value'),
    ]

the html file

{% load static %}

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <link
            href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css"
            rel="stylesheet"
            integrity="sha384-0evHe/X R7YkIZDRvuzKMRqM OrBnVFBL6DOitfPri4tjfHxaWutUpFmBp4vmVor"
            crossorigin="anonymous"
        />
        <link
            rel="stylesheet"
            href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.1/css/all.min.css"
        />
        <link rel="stylesheet" href="{% static 'habits/styles.css' %} " />
        <title>Habit</title>
    </head>
    <body >
        <!--good-->
        <div >
            <!--good-->
            <div >
                <!--good-->
                <div >
                    <!--good-->
                    <div >
                        <!--good-->
                        <div >
                            <h1 >
                                Habits <i  style="color: red"></i>
                            </h1>
                            <div >
                                <ul >
                                    <li >
                                        <form
                                            action="{% url 'insert_habit_item'%}"
                                            method="post"
                                            autocomplete="off"
                                        >
                                            {% csrf_token %}
                                            <!--  value used by server to make sure if the post or response is from 
                                        a trusted source or not -->
                                            <div >
                                                <input type="text"  name="habit" />
                                                <div >
                                                    <span 
                                                        ><button type="submit" >
                                                            <i ></i>
                                                        </button>
                                                    </span>
                                                </div>
                                            </div>
                                        </form>
                                    </li>
                                    {% for habit in habit_list %}
                                    <li >
                                        {{habit.IndHabit}}
                                        <form
                                            action="{% url 'decrement_habit_value' habit.id %}"
                                            method="post"
                                            
                                        >
                                            {% csrf_token %}

                                            <button type="submit" >
                                                <i
                                                    
                                                    aria-hidden="true"
                                                ></i>
                                            </button>
                                        </form>
                                        {{habit.IndValue}}
                                        <form
                                            action="{% url 'increment_habit_value' habit.id %}"
                                            method="post"
                                            
                                        >
                                            {% csrf_token %}

                                            <button type="submit" >
                                                <i
                                                    
                                                    aria-hidden="true"
                                                ></i>
                                            </button>
                                        </form>
                                        <form
                                            action="{% url 'delete_habit_item' habit.id %}"
                                            method="post"
                                            
                                        >
                                            {% csrf_token %}

                                            <button type="submit" >
                                                <i
                                                    
                                                ></i>
                                            </button>
                                        </form>
                                    </li>
                                    {% empty %}
                                    <li >
                                        <span>No Habits Found!</span>
                                    </li>
                                    {% endfor %}
                                </ul>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
        <script
            src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"
            integrity="sha384-pprn3073KE6tl6bjs2QrFaJGz5/SUsLqktiwsUTF55Jfv3qYSDhgCecCxMW52nD2"
            crossorigin="anonymous"
        ></script>
    </body>
</html>

CodePudding user response:

If I'm not mistaken about what I saw, there are three things here I'm seeing a problem with...

  1. Where you're trying the get an habit object. You have Habit.objects.get(Habit,id=habit_id) when it should be Habit.objects.get(id=habit_id).

  2. You're trying to increment and decrement a field that doesn't exist. You have habit_to_increment.values = 1 when the model doesn't have a field called values. What should be there is IndValue according to what you've posted for your Habit model.

  3. After incrementing or decrementing the IndValue, then you can just call the save method on the object without passing any value to it. What you have is habit_to_increment.save(['values']), just use habit_to_increment.save().

Another quick recommendation here is for you to set a default value to the Habit model IndValue field. IndValue=models.IntegerField(default=0).

Ideally, this should work for you...

def increment_habit_value(request, habit_id):
     habit_to_increment = Habit.objects.get(id=habit_id)
     habit_to_increment.IndValue  = 1
     habit_to_increment.save()

     return redirect('/habits/list/')


def decrement_habit_value(request, habit_id):
     habit_to_decrement = Habit.objects.get(id=habit_id)
     habit_to_decrement.IndValue -= 1
     habit_to_decrement.save()

     return redirect('/habits/list/')

CodePudding user response:

The way you are referencing the field you want to increment won't work (or at least I've never seen it before). My guess is you are wanting to use .values()? Using .values() can be useful to convert a recordset into a dict, but there is no need to do that here, especially if you are simply altering a field then saving back to the database. Try the following

from django.shortcuts import get_object_or_404

def increment_habit_value(request,habit_id):
    #You just need the id value in your objects.get(), as the type of model is defined by Habit as in
    #habit_to_increment = Habit.objects.get(id=habit_id)
    #However,I suspect you were wanting to use get_object_or_404
    #https://docs.djangoproject.com/en/4.0/topics/http/shortcuts/#, 
    #which conveniently handles a bad id, 
    #and does require the Model as an argument, so I used it here
    habit_to_increment = get_object_or_404(Habit, id=habit_id)
    #Because there is only one object, you can refer to the field you want to increment directly.
    habit_to_increment.IndValue  = 1
    habit_to_increment.save()
    return redirect('/habits/list/')

#similarly with the decrement view
def decrement_habit_value(request, habit_id):
    habit_to_decrement = get_object_or_404(Habit, id=habit_id)
    habit_to_decrement.IndValue -= 1
    habit_to_decrement.save()

 return redirect('/habits/list/')
  • Related