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...
Where you're trying the get an
habit object
. You haveHabit.objects.get(Habit,id=habit_id)
when it should beHabit.objects.get(id=habit_id)
.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 calledvalues
. What should be there isIndValue
according to what you've posted for yourHabit model
.After incrementing or decrementing the
IndValue
, then you can just call thesave method
on the object without passing any value to it. What you have ishabit_to_increment.save(['values'])
, just usehabit_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/')