Django reverse match error for keyword arguments - django

I am a newbie in python and I' training to make an app in Django to keep track of my clients problems in a personal training center.
I'm stuck in resolving a reverse match error for keyword arguments that is not passed. Honestly I am trying to understand how django manage this keyword arguments with no success.
The error that django throws me is:
NoReverseMatch at /persone/1/post
Reverse for 'cliente_detail' with keyword arguments '{'pk': ''}' not found. 1 pattern(s) tried: ['persone\\/(?P<pk>[0-9]+)\\/$']
Request Method: GET
Request URL: http://localhost:8000/persone/1/post
Django Version: 2.0.7
Exception Type: NoReverseMatch
Exception Value:
Reverse for 'cliente_detail' with keyword arguments '{'pk': ''}' not found. 1 pattern(s) tried: ['persone\\/(?P<pk>[0-9]+)\\/$']
Exception Location: C:\Users\perso\Envs\djangodev\lib\site-packages\django\urls\resolvers.py in _reverse_with_prefix, line 636
Python Executable: C:\Users\perso\Envs\djangodev\Scripts\python.exe
Python Version: 3.6.4
Python Path:
['C:\\Users\\perso\\Dropbox\\Django\\Frame\\filo_project',
'C:\\Users\\perso\\Envs\\djangodev\\Scripts\\python36.zip',
'C:\\Users\\perso\\Envs\\djangodev\\DLLs',
'C:\\Users\\perso\\Envs\\djangodev\\lib',
'C:\\Users\\perso\\Envs\\djangodev\\Scripts',
'c:\\users\\perso\\appdata\\local\\programs\\python\\python36-32\\Lib',
'c:\\users\\perso\\appdata\\local\\programs\\python\\python36-32\\DLLs',
'C:\\Users\\perso\\Envs\\djangodev',
'C:\\Users\\perso\\Envs\\djangodev\\lib\\site-packages']
Server time: Mar, 31 Lug 2018 11:58:32 +0200
My views.py:
import json
from django.http import HttpResponse
from django.shortcuts import get_object_or_404, redirect, render
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic.detail import DetailView
from django.views.generic.list import ListView
from django.views.generic.edit import UpdateView, CreateView, DeleteView, FormView
#Qui importo la classe per essere sicuro che se l'user non è loggato lo deve far loggare
from django.contrib.auth.decorators import login_required
#Ricordarsi di importare anche i modelli:
from .models import Cliente, FitCheck, Post
#login_required(login_url='/accounts/login/')
def home(request):
return render(request, "filogest/home.html")
class ClienteListView(LoginRequiredMixin, ListView):
#questa vista mi permette di visualizzare tutto l'elenco dei clienti
model = Cliente
template_name= "filogest/elenco_clienti.html"
#quetso per richiamare nel html il nome dell'elenco
context_object_name = 'elenco_clienti'
class ClienteDetailView(LoginRequiredMixin, DetailView):
model=Cliente
template_name="filogest/cliente_detail.html"
context_object_name = 'cliente_detail'
###############################
#Vai di editing di fitcheck
###############################
class FitcheckDetailView(LoginRequiredMixin, DetailView):
model=FitCheck
template_name="filogest/fitcheck_detail.html"
context_object_name = 'fitcheck_detail'
class FitcheckUpdateView(LoginRequiredMixin, UpdateView):
model = FitCheck
fields = ['idfitcheck','colazioneregolare']
template_name="filogest/fitcheck_update.html"
###############################
#Vai di editing di post
###############################
class PostDetailView(LoginRequiredMixin, DetailView):
model = Post
template_name="filogest/post_detail.html"
context_object_name = 'post_detail'
# def myPostListView(request, pk):
# idcli = get_object_or_404(Post, idclientepost=pk)
# posts_fisio = Post.objects.filter(tipologia="FI",idclientepost=idcli)
# posts_pale = Post.objects.filter(tipologia="PA",idclientepost=idcli)
# post = {"posts_fisio": posts_fisio, "posts_pale": posts_pale}
# return render(request, 'filogest/post_list.html', post)
class PostListView(LoginRequiredMixin, ListView):
model = Post
template_name = 'filogest/post_list.html'
context_object_name = 'post_list'
def get_context_data(self, *args, **kwargs):
context = super(PostListView, self).get_context_data(*args, **kwargs)
context['FisioPost'] = Post.objects.filter(tipologia="FI",idclientepost=self.kwargs['idclientepost'])
context['PalePost'] = Post.objects.filter(tipologia="PA",idclientepost=self.kwargs['idclientepost'])
context['fkPost'] = Post.objects.filter(idclientepost=self.kwargs['idclientepost'])
return context
class PostDetailCreate(LoginRequiredMixin, CreateView):
model = Post
template_name = 'post_create'
fields = '__all__'
###############################
#Vai di editing di post
###############################
#da controllare di brutto
def CercaPersona(request):
return render(request, "filogest/seleziona_cliente.html")
def AutocompleteCliente(request):
q = request.GET.get("term", "")
clienti = Cliente.objects.filter(nome__icontains=q)
results = []
for cliente in clienti:
place_json = {}
place_json = cliente.nome + " " + cliente.cognome
results.append(place_json)
data = json.dumps(results)
return HttpResponse(data, 'application/json')
models.py
from django.db import models
from django.contrib.auth.models import User
#importo timezone perchè così posso usare la funzione per capire quando è stato inserito
#un cliente oppure un fitcheck
from django.utils import timezone
from datetime import datetime
# Create your models here.
#questa funzione permette di far fare al sistema django i link per
#gli articoli referenziati
from django.urls import reverse
class Cliente(models.Model):
SESSO = (
('M','Maschio'),
('F','Femmina'),
)
idcliente = models.AutoField(primary_key=True)
nome = models.CharField(max_length=50)
cognome = models.CharField(max_length=50)
datadinascita = models.DateField()
sesso = models.CharField(max_length=1,choices=SESSO)
datainsert = models.DateTimeField(auto_now=True)
def __str__(self):
return self.cognome + " " + self.nome
def age(self):
return int((datetime.now().date() - self.datadinascita).days / 365.25)
#Qui uso questa funzione per far gestire al sistema i link che andro poi a richiamare
#con la classe.get_absolute_url
def get_absolute_url(self):
return reverse("filogest:cliente_detail", kwargs={"pk":self.idcliente})
class Meta:
# link utile : https://docs.djangoproject.com/en/2.0/ref/models/options/
verbose_name = "Cliente"
verbose_name_plural = "Clienti"
class FitCheck(models.Model):
STILE_PROFESSIONE = (
('PA','Poco attiva'),
('MA','Mediamente attiva'),
('A', 'Attiva'),
('MM','Molto Attiva'),
('US','Usurante'),
)
SI_NO = (
('S','Si'),
('N','No'),
)
ALIMENTAZIONE_TIPO = (
('D','Dietologo'),
('F', 'Fai da te'),
('N', 'Nutrizionista'),
('O', 'Nulla'),
)
STILE_DI_VITA = (
('PA','Poco Attivo'),
('MA', 'Mediamente Attivo'),
('AA', 'Attivo'),
('AM', 'Molto Attivo'),
('US', 'Usurante'),
)
OBIETTIVO_PRIMARIO = (
('DI','Dimagrimento'),
('PE', 'Performance'),
('DO', 'Dolore'),
('MU', 'Muscolazione'),
('FI', 'Fitness Generale'),
('GR', 'Gravidanza'),
('PG', 'Post Gravidanza'),
('PO', 'Postura'),
('RI', 'Rieducazione'),
('OP', 'Pre-Intervento'),
('CV', 'Cardio Vascolare'),
('PM', 'Prescrizione Medica'),
)
HA_DOLORE = (
('A','Acuto'), #dall'ultima settimana ha dolore
('S','Sub-acuto'), #dalla fase di dolore a 6 settimane
('C','Cronico'),
('N','No')
)
PROFESSIONE = (
('A','Altro'),
('C','Casalinga'),
('I','Impiegato'),
('O','Operaio'),
('S','Sportivo'),
('U','Studente'),
('P','Pensionato'),
('L','Libero Professionista'),
('T','Autista'),
)
STRESS = (
('PS','Poco Stressante'),
('ST','Stressante'),
('MS','Molto Stressante'),
)
DISP_ORARIA = (
('MA','Mattina'),
('PP','Pausa Pranzo'),
('PO','Pomeriggio'),
('SE','Sera'),
('TU','Turni'),
('LI','Libero'),
)
PROPOSTA_ACCETTATA = (
('S','Si'),
('N','No'),
('F','Fa Sapere'),
)
OSTEO = (
('F','Fatta'),
('D','Da Fare'),
('N','No'),
)
FONTE = (
('MA','Mattia'),
('PC','Paolo Cucchetti'),
('FD','Federico Dal Corso'),
('IN','Insegna'),
('IT','Internet'),
('UM','Monsellato'),
('MC','Marco'),
('PR','Paolo Roma'),
('TR','Trainer'),
('CL','Clienti'),
('MD','Medici'),
('AM','Amicizie'),
('VA','Varie'),
)
EFFETTUATO_DA = (
('MP','Marco P'),
('PR','Paolo R'),
('MA','Marco A'),
('PC','Paolo C'),
)
FUMATORE = (
('SI','Si'),
('ST','Saltuariamente'),
('NO','No'),
('EX','Ex'),
)
VAS = (
('0','0'),
('1','1'),
('2','2'),
('3','3'),
('4','4'),
('5','5'),
('6','6'),
('7','7'),
('8','8'),
('9','9'),
('10','10')
)
idfitcheck = models.OneToOneField(Cliente, on_delete=models.CASCADE, primary_key=True)
luogodinascita = models.CharField(max_length=50, verbose_name="Luogo di nascita")
email = models.EmailField(verbose_name="E-mail")
telefono = models.CharField(max_length=20, verbose_name="Numero di telefono")
indirizzo = models.CharField(max_length=100, verbose_name="Indirizzo")
citta = models.CharField(max_length=20, verbose_name="Città")
cap = models.CharField(max_length=5, verbose_name="CAP")
figli = models.CharField(max_length=50, verbose_name="Figli")
professione = models.CharField(max_length=1,choices=PROFESSIONE, verbose_name="Professione")
stileprofessione = models.CharField(max_length=2,choices=STILE_PROFESSIONE, verbose_name="Stile Professione")
stiledivita = models.CharField(max_length=2,choices=STILE_DI_VITA, verbose_name="Stile di vita")
stress = models.CharField(max_length=2,choices=STRESS, verbose_name="Come definisce il suo stile di vita?")
fumatore = models.CharField(max_length=2, choices=FUMATORE, verbose_name="Fuma?")
obiettivoprimario = models.CharField(max_length=2,choices=OBIETTIVO_PRIMARIO, verbose_name="Obiettivo Primario")
noteprimario = models.TextField(verbose_name="Note obiettivo primario")
obiettivosecondario = models.TextField(verbose_name="Obiettivo secondario")
alimentazione = models.CharField(max_length=2,choices=ALIMENTAZIONE_TIPO, verbose_name="Cura alimentazione")
alimcontrollataattiva = models.CharField(max_length=2,choices=SI_NO, verbose_name="Attualmente l'alimentazione è controllata")
pastialgiorno = models.IntegerField(verbose_name="Quanti pasti fa al giorno?")
colazioneregolare = models.CharField(max_length=2,choices=SI_NO, verbose_name="Fa colazione regolarmente?")
giabia = models.CharField(max_length=2,choices=SI_NO,verbose_name="Ha già fatto test BIA?")
attivitaattuali = models.CharField(max_length=2,choices=SI_NO,verbose_name="Attualmente svolge attività fisiche?")
attivitafisicarecente = models.CharField(max_length=500, verbose_name="Attività fisiche recenti")
attivitapassato = models.CharField(max_length=2,choices=SI_NO, verbose_name="In passato ha svolto attività?")
qualiattivita = models.CharField(max_length=500,verbose_name="Se si quali?")
assumealcool = models.CharField(max_length=2,verbose_name="Assume alcool?", choices=FUMATORE)
quantitaalcol = models.FloatField(verbose_name="Quanti bicchieri beve al giorno?")
attualmenteagonista = models.CharField(max_length=2,choices=SI_NO, verbose_name="Attualmente Agonista")
hadolore = models.CharField(max_length=2,choices=HA_DOLORE, verbose_name="Attualmente ha dolore?")
vasnrs = models.CharField(max_length=1, choices=VAS, verbose_name="Scala vas del dolore acuto e sub-acuto")
doloripassati = models.CharField(max_length=2,choices=SI_NO, verbose_name="Dolori in passato?")
notedoloripassati = models.TextField(verbose_name="Note su dolori")
traumipassati = models.CharField(max_length=2,choices=SI_NO, verbose_name="Ha subito traumi in passato")
interventichirurgici = models.CharField(max_length=2,choices=SI_NO)
notetraumiinterventi = models.TextField(verbose_name="Note traumi/interventi")
altremalattie = models.TextField(verbose_name="Altre malattie?")
altro = models.TextField(verbose_name="Altro da segnalare?")
disponibilitaoraria = models.CharField(max_length=2,choices=DISP_ORARIA)
freqsettimanale = models.FloatField(verbose_name="Quante volte riuscirebbe a venire regolarmente?")
seduteproposte = models.IntegerField(verbose_name="Sedute proposte dal trainer")
propostaaccettata = models.CharField(max_length=1,choices=PROPOSTA_ACCETTATA, verbose_name="Proposta fatta dal trainer accettata?")
fonte = models.CharField(max_length=2,choices=FONTE, verbose_name="Fonte")
sedutaprova = models.CharField(max_length=2,choices=SI_NO, verbose_name="Seduta di prova fissata?")
totaleeconomico = models.FloatField(verbose_name="Totale economico proposto?")
biaprogrammata = models.CharField(max_length=1,choices=OSTEO, verbose_name="Bia programmata?")
osteoprogrammata = models.CharField(max_length=1,choices=OSTEO, verbose_name="Valutazione osteopatica programmata?")
fisioprogrammata = models.CharField(max_length=1,choices=OSTEO, verbose_name="Valutazione fisioterapica programmata?")
stapedio = models.CharField(max_length=2,choices=SI_NO)
datainserimento= models.DateTimeField(auto_now=True)
effettuato = models.CharField(max_length=2, choices=EFFETTUATO_DA, verbose_name="Colloquio effettuato da?")
def __str__(self):
return self.idfitcheck.cognome + " "+ self.idfitcheck.nome
def nome_persona(self):
return self.idfitcheck.cognome + " "+ self.idfitcheck.nome
def fitchekpk(self):
return self.idfitcheck
def get_absolute_url(self):
return reverse("filogest:fitcheck_detail", kwargs={"pk":self.idfitcheck})
class Meta:
# link utile : https://docs.djangoproject.com/en/2.0/ref/models/options/
verbose_name = "FitCheck"
verbose_name_plural = "FitChecks"
#da qui parte lo script per il modello di balke che prendere:
#1- età
#2-SESSO
#3-Peso che va creato ad ok
#4- da qui calcolare poi la frequenza cardiaca massima
#5- permettere l'inserimento dei dati del test
#6- elaborare e salvare i risultati
class Balke(models.Model):
idbalke = models.ForeignKey(Cliente,on_delete=models.CASCADE, related_name="filogest_balke_clienti")
etasogg = models.IntegerField()
pesosogg = models.FloatField()
blocco1=models.IntegerField()
blocco2=models.IntegerField()
blocco3=models.IntegerField()
blocco4=models.IntegerField()
blocco5=models.IntegerField()
blocco6=models.IntegerField()
blocco7=models.IntegerField()
def __str__ (self):
return self.idbalke.cognome + " "+ self.idbalke.nome
def cooper(self):
return 220-Cliente.age
def tanaka(self):
return (208-(0,7*Cliente.age))
class Post(models.Model):
OBIETTIVO_PERSONA = (
('DI','Dimagrimento'),
('PE', 'Performance'),
('DO', 'Dolore'),
('MU', 'Muscolazione'),
('FI', 'Fitness Generale'),
('GR', 'Gravidanza'),
('PG', 'Post Gravidanza'),
('PO', 'Postura'),
('RI', 'Rieducazione'),
('OP', 'Pre-Intervento'),
('CV', 'Cardio Vascolare'),
('PM', 'Prescrizione Medica'),
)
TIPO = (
('FI', 'Fisio / Osteo'),
('PA', 'Palestra'),
)
idpost = models.AutoField(primary_key=True)
idclientepost = models.ForeignKey(Cliente, on_delete=models.CASCADE, related_name="cliente")
tipologia = models.CharField(max_length=2, choices=TIPO)
titolo = models.CharField(max_length=250)
obiettivo = models.CharField(max_length=2, choices=OBIETTIVO_PERSONA)
autore = models.ForeignKey(User, on_delete=models.CASCADE,related_name="filogest_post")
corpo = models.TextField()
creato = models.DateTimeField(auto_now=True)
class Meta:
ordering = ('-creato',)
def get_absolute_url(self):
return reverse("filogest:post_detail", kwargs={"idclientepost": self.idclientepost.idcliente, "pk":self.idpost})
return reverse("filogest:post_list", kwargs={"idclientepost": self.idclientepost.idcliente})
def __str__(self):
return self.titolo
Urls.py:
from django.urls import path, include, reverse
from .views import home, ClienteListView, ClienteDetailView, AutocompleteCliente, CercaPersona, FitcheckDetailView, FitcheckUpdateView
from .views import PostListView, PostDetailView, PostListView
app_name='filogest'
urlpatterns = [
path ('', home, name='homepage'),
path ('persone/', ClienteListView.as_view(), name='elenco_clienti'),
path ('persone/<int:pk>/', ClienteDetailView.as_view(), name='cliente_detail'),
path ('getperson/', AutocompleteCliente, name='autocomplete_cliente'),
path ('cercaper/', CercaPersona, name='cerca_persona'),
path ('persone/<int:pk>/fitcheck', FitcheckDetailView.as_view(), name='fitcheck_detail'),
path ('persone/<int:pk>/fitcheckupdate', FitcheckUpdateView.as_view(), name='fitcheck_update'),
#uso idcliente post perchè il modello è il post ma il riferimento è la chiave esterna
path ('persone/<int:idclientepost>/post', PostListView.as_view(), name='post_list'),
path ('persone/<int:idclientepost>/post/<int:pk>',PostDetailView.as_view(), name='post_detail'),
]
cliente_detail template
{% extends "base.html" %}
{% load crispy_forms_tags %}
{% block head_title %}{{ block.super }} - Dettagli Cliente{% endblock head_title %}
{% block content %}
<br>
<div class="">
<button type="button" class="btn btn-primary" onclick="location.href='{% url 'filogest:cliente_detail' pk=cliente_detail.idcliente %}';">Dettagli Anagrafici</button>
<button type="button" class="btn btn-primary" onclick="location.href='{% url 'filogest:fitcheck_detail' pk=cliente_detail.idcliente %}';">FitCheck</button>
<button type="button" class="btn btn-primary" onclick="location.href='{% url 'filogest:post_list' idclientepost=cliente_detail.idcliente %}';">Note operative</button>
<button type="button" class="btn btn-primary">Test Balke</button>
<button type="button" class="btn btn-primary">Test Motori</button>
</div>
<br>
<div class="alert alert-warning" role="alert">
<br>
<h1>Dettagli persona:</h1>
<hr>
<strong>Cognome:</strong> {{ cliente_detail.cognome }} <br>
<strong>Nome:</strong> {{ cliente_detail.nome }} <br>
<strong>Data di nascita:</strong> {{ cliente_detail.datadinascita }} <br>
<strong>Sesso:</strong> {{ cliente_detail.sesso }} <br>
<strong>Età:</strong> {{ cliente_detail.age }} <br>
<hr>
</div>
{% endblock content %}
post_list
{% extends "base.html" %}
{% load crispy_forms_tags %}
{% block head_title %}{{ block.super }} - Dettagli Cliente{% endblock head_title %}
{% block content %}
<br>
<div class="">
<button type="button" class="btn btn-primary" onclick="location.href='{% url 'filogest:cliente_detail' pk=post_list.idclientepost %}';">Dettagli Anagrafici</button>
<button type="button" class="btn btn-primary" onclick="location.href='{% url 'filogest:fitcheck_detail' pk=1 %}';">FitCheck</button>
<button type="button" class="btn btn-primary">Note operative</button>
<button type="button" class="btn btn-primary">Test Balke</button>
<button type="button" class="btn btn-primary">Test Motori</button>
</div>
<div>
<br>
<h1>Commenti di {% for post in fkPost %}
{% if forloop.first %}
{{ post.idclientepost.cognome }} {{ post.idclientepost.nome}}
{% endif %}
{% endfor %}</h1>
<div class="container">
<div class="row">
<div class="col">
<h2>Note Osteofisio :</h2>
<br>
{% for post in FisioPost %}
<div class="p-2 border border-primary">
<strong>Titolo:</strong> {{ post.titolo }} <br>
<strong>Obiettivo:</strong> {{post.get_obiettivo_display}} <br>
<div class="p-1 border">
<strong>Nota:</strong><br>
{{post.corpo}}<br>
</div>
<i>Creato da: <strong>{{post.autore}}</strong> in data {{post.creato}}</i>
{{post.idclientepost}}
</div>
{% endfor %}
</div>
<div class="col">
<h2>Note Trainer:</h2>
<br>
{% for post in PalePost %}
<div class="p-2 border border-success">
<strong>Titolo:</strong> {{ post.titolo }} <br>
<strong>Obiettivo:</strong> {{post.get_obiettivo_display}} <br>
<div class="p-1 border">
<strong>Nota:</strong><br>
{{post.corpo}}<br>
</div>
<i>Creato da: <strong>{{post.autore}}</strong> in data {{post.creato}}</i>
</div>
{% endfor %}
</div>
</div>
</div>
{% endblock content %}
Any help would be appreciated.

As far as I can see this exception is raised at PostListView. In your template filogest/post_list.html you have a detail button:
<button type="button" class="btn btn-primary" onclick="location.href='{% url 'filogest:cliente_detail' pk=post_list.idclientepost %}';">Dettagli Anagrafici</button>
You are creating the url with the argument pk=post_list.idclientepost. I believe the post_list.idclientepost maybe null or blank for the instance. As it's mentioned in the error pk is passed blank (with keyword arguments '{'pk': ''}').
Reverse for 'cliente_detail' with keyword arguments '{'pk': ''}' not found. 1 pattern(s) tried: ['persone\\/(?P<pk>[0-9]+)\\/$']

Related

Add products with different sizes and price to Cart | Django

I use session's to create a shopping cart. I have a product model and a model for Product-sizes, which I define the size-title(XL , etc) and price of product in it . So that I can have products with different sizes as well as different prices. But my logic has some problems
if I add product_1 with size A , it's ok ...
if I add product_1 with size B , it's ok ...
but when I'm trying to add same product with different sizes at same time the cart only shows the price of first size
#shop/models.py
class ProductSizes(models.Model):
name = models.CharField(max_length=50)
price = models.IntegerField()
picture = models.ImageField(upload_to="products/%Y/%m/%d" )
class Product(models.Model):
name = models.CharField(max_length=100)
size = models.ManyToManyField(ProductSizes , blank=True , related_name="sizes" )
price = models.IntegerField()
#cart/cart.py
from django.conf import settings
from shop.models import Product
class Cart:
def __init__(self,request):
self.session = request.session
cart = self.session.get(settings.CART_SESSION_ID)
if not cart:
cart = self.session[settings.CART_SESSION_ID] = {}
self.cart = cart
# add to cart
def add(self,product,size_,quantity=1,override_quantity=False):
product_id = str(product.id)
print(product.size.name)
if product_id not in self.cart :
if size_ != None:
if size_.off_price:
self.cart[product_id] = {'quantity':0,'price':size_.off_price}
elif size_.price:
self.cart[product_id] = {'quantity':0,'price':size_.price}
else:
if product.off_price:
self.cart[product_id] = {'quantity':0,'price':product.off_price}
else:
self.cart[product_id] = {'quantity':0,'price':product.price}
if override_quantity:
self.cart[product_id]['quantity'] = quantity
else:
self.cart[product_id]['quantity'] += quantity
self.save()
def save(self):
self.session.modified = True
#remove from cart
def remove(self,product):
product_id = str(product.id)
if product_id in self.cart:
del self.cart[product_id]
self.save()
def __iter__(self):
product_ids = self.cart.keys()
products = Product.objects.filter(id__in=product_ids)
cart = self.cart.copy()
for product in products:
cart[str(product.id)]['product'] = product
for item in cart.values():
item['total_price'] = item['price'] * item['quantity']
yield item
def __len__(self):
return sum(item['quantity'] for item in self.cart.values())
def get_total_price(self):
return sum(item['price'] * item['quantity'] for item in self.cart.values())
def clear(self):
del self.session[settings.CART_SESSION_ID]
self.save()
ــــــــــــــــــ
from django.shortcuts import get_object_or_404 , redirect , render
from django.views.decorators.http import require_POST
from .cart import Cart
from shop.models import Product, ProductSizes
from .forms import CartAddProductForm
#require_POST
def cart_add(request , product_id , size):
cart = Cart(request)
product = Product.objects.get(id=product_id)
if size != 0:
size_ = product.size.get(id=size)
else:
size_ = None
form = CartAddProductForm(request.POST)
if form.is_valid():
cd = form.cleaned_data
cart.add(product=product , quantity=cd['quantity'] ,size_=size_, override_quantity=cd['override'] )
return redirect("home")
#require_POST
def cart_remove(request , product_id):
cart = Cart(request)
product = get_object_or_404(Product,id=product_id)
cart.remove(product=product)
return redirect("cart.detail")
def cart_detail(request):
cart = Cart(request)
for item in cart:
item['update_quantity_form'] = CartAddProductForm(initial={
'quantity':item["quantity"],
"override":True,
})
return render(request , "cart.html" , {"cart":cart})
#cart/forms.py & urls
from django import forms
PRODUCT_QUANTITY_CHOICES = [(i , str(i)) for i in range(1,21)]
class CartAddProductForm(forms.Form):
quantity = forms.TypedChoiceField(choices=PRODUCT_QUANTITY_CHOICES,coerce=int)
override = forms.BooleanField(required=False, initial=False,widget=forms.HiddenInput)
---------------
urlpatterns = [
path("" , views.cart_detail , name="cart.detail"),
path("add/<int:product_id>/<int:size>/" , views.cart_add , name="cart.add"),
path("remove/<int:product_id>/" , views.cart_remove , name="cart.remove"),
]
#html
<div class="shopping-cart-wrap">
<span class="cart-total-amunt">{{cart.get_total_price}} تومان</span><i class="icon-shopping-bag2 float-left"></i><span class="cart-total">{{cart|length}}</span>
<ul class="mini-cart">
{% for item in cart %}
<li class="cart-item">
<div class="cart-image">
<img alt="" src="/media/{{item.product.picture}}" width="80" height="80">
</div>
<div class="cart-title">
<a href="single-product.html">
<h4>{{item.product.name}}</h4>
</a>
<div class="quanti-price-wrap">
<span class="quantity">{{item.quantity}} ×</span>
<div class="price-box"><span class="new-price">{{item.price}} تومان</span></div>
</div>
<a class="{% url 'cart.remove' item.product.id %}" href="#"><i class="icon-x"></i></a>
</div>
</li>
{% endfor %}
<li class="subtotal-box">
<div class="subtotal-title">
<h3>جمع کل :</h3><span>{{cart.get_total_price}} تومان</span>
</div>
</li>
<li class="mini-cart-btns">
<div class="cart-btns">
مشاهده سبد
پرداخت
</div>
</li>
</ul>
</div>
after 2 days of struggling finally I found the solution
for adding products with different sizes you have to pass the size model id to session instead of the product id
shop/models.py
class ProductSizes(models.Model):
name = models.CharField(max_length=50)
price = models.IntegerField()
off_price = models.IntegerField(blank=True , null=True)
picture = models.ImageField(upload_to="products/%Y/%m/%d" )
product = models.ForeignKey("Product" , on_delete=models.CASCADE )
class Product(models.Model):
name = models.CharField(max_length=100)
description = models.TextField(blank=True)
picture = models.ImageField(upload_to="products/%Y/%m/%d" )
picture2 = models.ImageField(upload_to="products/%Y/%m/%d" , blank=True)
picture3 = models.ImageField(upload_to="products/%Y/%m/%d" , blank=True)
picture4 = models.ImageField(upload_to="products/%Y/%m/%d" , blank=True)
price = models.IntegerField()
available = models.BooleanField(default=True)
category = models.ForeignKey(Category ,on_delete=models.CASCADE , blank=True ,null=True )
slug = models.SlugField(max_length=100 , db_index=True , unique=True)
tags = TaggableManager(blank=True)
is_amazing = models.BooleanField(default=False)
amazing_till = models.CharField(max_length=10 , null=True , blank=True)
off_price = models.IntegerField(blank=True , null=True)
brand = models.ForeignKey(Brand ,on_delete=models.CASCADE , blank=True ,null=True )
created_at = models.DateField(auto_now_add=True)
update_at = models.DateField(auto_now=True)
def get_absolute_url(self):
return reverse('get.single.product', kwargs={'slug': self.slug})
class Meta:
ordering=("name",)
index_together = (('id' , 'slug'),)
cart/cart.py
from django.conf import settings
from shop.models import Product, ProductSizes
class Cart:
def __init__(self,request):
self.session = request.session
cart = self.session.get(settings.CART_SESSION_ID)
if not cart:
cart = self.session[settings.CART_SESSION_ID] = {}
self.cart = cart
# add to cart
def add(self,product,size_,quantity=1,override_quantity=False):
size_id = str(size_.id)
if size_id not in self.cart:
if size_.price:
self.cart[size_id] = {'quantity': 0, 'price': size_.price}
elif size_.off_price:
self.cart[size_id] = {'quantity': 0, 'price': size_.off_price}
self.cart[size_id]['quantity'] += quantity
self.save()
self.save()
def save(self):
self.session.modified = True
#remove from cart
def remove(self,size_):
product_id = str(size_.id)
if product_id in self.cart:
del self.cart[product_id]
self.save()
def __iter__(self):
sizes_ids = self.cart.keys()
products = ProductSizes.objects.filter(id__in=sizes_ids)
cart = self.cart.copy()
for size in products:
cart[str(size.id)]['size'] = size
for item in cart.values():
item['total_price'] = item['price'] * item['quantity']
yield item
def __len__(self):
return sum(item['quantity'] for item in self.cart.values())
def get_total_price(self):
return sum(item['price'] * item['quantity'] for item in self.cart.values())
def clear(self):
del self.session[settings.CART_SESSION_ID]
self.save()
cart/views.py
#require_POST
def cart_add(request , product_id , size):
cart = Cart(request)
product = Product.objects.get(id=product_id)
size_ = get_object_or_404(ProductSizes , id=size)
form = CartAddProductForm(request.POST)
if form.is_valid():
cd = form.cleaned_data
cart.add(product=product , quantity=cd['quantity'] ,size_=size_, override_quantity=cd['override'] )
return redirect("home")
The template
{% block cart %}
<div class="shopping-cart-wrap">
<span class="cart-total-amunt">{{cart.get_total_price}} تومان</span><i class="icon-shopping-bag2 float-left"></i><span class="cart-total">{{cart|length}}</span>
<ul class="mini-cart">
{% for item in cart %}
<li class="cart-item">
<div class="cart-image">
<img alt="" src="/media/{{item.size.product.picture}}" width="80" height="80">
</div>
<div class="cart-title">
<a href="single-product.html">
<h4>{{item.size.name}}</h4>
</a>
<div class="quanti-price-wrap">
<span class="quantity">{{item.quantity}} ×</span>
<div class="price-box"><span class="new-price">{{item.price}} تومان</span></div>
</div>
<a class="{% url 'cart.remove' item.size.id %}" href="#"><i class="icon-x"></i></a>
</div>
</li>
{% endfor %}
<li class="subtotal-box">
<div class="subtotal-title">
<h3>جمع کل :</h3><span>{{cart.get_total_price}} تومان</span>
</div>
</li>
<li class="mini-cart-btns">
<div class="cart-btns">
مشاهده سبد
پرداخت
</div>
</li>
</ul>
</div>
{% endblock cart %}

formset function update view does not save the forms because the id is missing

I have a view to update 6 of my formset only that the click of the send button gives me the error that the id of each form is missing ... how do you fix it?
When I have to create formset there are never problems with the id...
Can anyone tell me where I'm wrong? I leave my code below
view
#login_required
def PianoSingleUpdateView(request, id):
piano = models.Piano.objects.get(single_piano__id = id)
piano_sett = models.PianoSingleDay.objects.get(id = id)
dato = models.PianoDay.objects.filter( piano_day = piano_sett)
DatiFormSet = modelformset_factory(models.PianoDay, extra = 0, fields=('id', 'kcal', 'carboidrati', 'proteine', 'grassi'))
if request.method == 'POST':
dati_formset = DatiFormSet(request.POST, request.FILES, queryset = dato)
if dati_formset.is_valid():
for dato in dati_formset:
dato.save()
return redirect('gestione-piano', id = piano.id)
else:
dati_formset = DatiFormSet(queryset = dato)
context = {'piano': piano, 'piano_sett': piano_sett, 'dati_formset': dati_formset}
return render(request, 'crud/update/update_piano_giornaliero.html', context)
models
class Piano(models.Model):
nome_piano = models.CharField(max_length=100)
data_inizio = models.DateField()
data_fine = models.DateField()
utente_piano = models.ForeignKey(
User,
on_delete = models.CASCADE,
related_name = 'utente_piano'
)
def __str__(self):
return self.nome_piano
class PianoSingleDay(models.Model):
giorni_settimana_scelta = [
("1","Lunedì"),
("2","Martedì"),
("3","Mercoledì"),
("4","Giovedì"),
("5","Venerdì"),
("6","Sabato"),
("7","Domenica")
]
giorni_settimana = models.CharField(
choices = giorni_settimana_scelta,
max_length = 300
)
single_piano = models.ForeignKey(
Piano,
on_delete = models.CASCADE,
related_name = 'single_piano'
)
def __str__(self):
return self.giorni_settimana
class PianoDay(models.Model):
scelta_pasto = [
("1","Colazione"),
("2","Spuntino mattina"),
("3","Pranzo"),
("4","Merenda"),
("5","Cena"),
("6","Spuntino sera")
]
pasto = models.CharField(
choices = scelta_pasto,
max_length = 300,
default = '-'
)
kcal = models.IntegerField(default = 0)
grassi = models.IntegerField(default = 0)
carboidrati = models.IntegerField(default = 0)
proteine = models.IntegerField(default = 0)
piano_day = models.ForeignKey(
PianoSingleDay,
on_delete = models.CASCADE,
related_name = 'piano_day'
)
file html
<form method="post" novalidate autocomplete="off" class="form-not-box">
{% csrf_token %}
<div class="box-schede">
<div class="alert alert-pop-up mt-3" role="alert">
Le colonne lasciate a 0 non verranno considerate.
</div>
{{ dati_formset.management_form }}
<div class="row mt-3">
{% for dati in dati_formset %}
<div class="col-lg-2">
<div class="info-piano">
<div class="ico">
{% if forloop.counter == 1 %}
<object type="image/svg+xml" data="{% static 'img/icone/colazione.svg' %}">
Icona colazione
</object>
{% elif forloop.counter == 3 %}
<object type="image/svg+xml" data="{% static 'img/icone/pranzo.svg' %}">
Icona pranzo
</object>
{% elif forloop.counter == 5 %}
<object type="image/svg+xml" data="{% static 'img/icone/cena.svg' %}">
Icona cena
</object>
{% elif forloop.counter == 2 or forloop.counter == 4 or forloop.counter == 6 %}
<object type="image/svg+xml" data="{% static 'img/icone/merenda.svg' %}">
Icona cena
</object>
{% endif %}
</div>
<div class="form-floating mb-3 mt-3">
{{ dati.kcal|add_class:'form-control'|append_attr:"placeholder: dati" }}
{{ dati.kcal.label_tag }}
</div>
<div class="form-floating mb-3">
{{ dati.carboidrati|add_class:'form-control'|append_attr:"placeholder: dati" }}
{{ dati.carboidrati.label_tag }}
</div>
<div class="form-floating mb-3">
{{ dati.proteine|add_class:'form-control'|append_attr:"placeholder: dati" }}
{{ dati.proteine.label_tag }}
</div>
<div class="form-floating">
{{ dati.grassi|add_class:'form-control'|append_attr:"placeholder: dati" }}
{{ dati.grassi.label_tag }}
</div>
</div>
</div>
{% endfor %}
</div>
</div>
<div class="buttons mb-3">
Indietro
<input type="submit" class="btn btn-warning" value="Aggiorna piano">
</div>
</form>
My observation tells me that your problem is the DatiFormSet fields which shouldn't contain id value and also your function view had in queryset = dato which is not needed, but in some cases you should add an instance of Piano.
#login_required
def PianoSingleUpdateView(request, id):
piano = models.Piano.objects.get(single_piano__id = id)
piano_sett = models.PianoSingleDay.objects.get(id = id)
dato = models.PianoDay.objects.filter( piano_day = piano_sett)
DatiFormSet = modelformset_factory(models.PianoDay, extra = 0, fields=('kcal', 'carboidrati', 'proteine', 'grassi'))
if request.method == 'POST':
dati_formset = DatiFormSet(request.POST, request.FILES , instance=piano)
if dati_formset.is_valid():
for dato in dati_formset:
dato.save()
return redirect('gestione-piano', id = piano.id)
else:
dati_formset = DatiFormSet(request.POST)
context = {'piano': piano, 'piano_sett': piano_sett, 'dati_formset': dati_formset}
return render(request, 'crud/update/update_piano_giornaliero.html', context)

How to display your queries using filter?

So I am trying to set up a filter for my website and it is not working; It does not give me an error and the url updates like a query is being made but when I click "submit" it still shows all of the content in the page. I can't quite figure out what is wrong.
filters.py
import django_filters
from django_filters import DateFilter
from .models import *
class UserpostFilter(django_filters.FilterSet):
start_date = DateFilter(field_name = "date_published", lookup_expr='gte')
end_date = DateFilter(field_name = "date_published", lookup_expr='lte')
class Meta:
model = Userpost
fields = '__all__'
exclude = ['image', 'user', 'date_published']
models.py
class Userpost(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True)
Year = models.CharField(max_length = 4)
Mileage = models.CharField(max_length = 8)
Make = models.CharField(max_length = 50)
Model = models.CharField(max_length = 50)
Price = models.DecimalField(max_digits=15, decimal_places=2)
email = models.EmailField()
date_published = models.DateField(default = timezone.now)
image = models.ImageField(null = True, blank = True, upload_to = r"C:\Users\gabri\Desktop\test\ecommerce\static\images")
def __str__(self):
return self.Year + " " + self.Make + " " + self.Model
#property
def imageURL(self):
try:
url = self.image.url
except:
url = ''
return url
views.py
def posts(request):
cars = Userpost.objects.all()
p = Paginator(Userpost.objects.all(), 9)
page = request.GET.get('page')
cars_list = p.get_page(page)
nums = "a" * cars_list.paginator.num_pages
myFilter = UserpostFilter(request.GET, queryset = cars)
cars = myFilter.qs
context = {'cars':cars, 'cars_list':cars_list, "nums":nums, "myFilter":myFilter}
return render(request, 'store/userposts.html', context)
userposts.html
<div class = "row">
<div class="col">
<div class = "card card-body">
<form method="get">
{{myFilter.form}}
<button class="btn btn-primary" type="submit">Search</button>
</form>
</div>
</div>
</div>
<br>
<div class="row">
{% for car in cars_list %}
<div class="col-lg-4">
<img class="thumbnail" src="{{car.imageURL|default:'/images/transparentLogo.png'}}">
<div class="box-element product">
<h6><strong>{{car.Year}} {{car.Make}} {{car.Model}}</strong></h6>
<hr>
<a class="btn btn-outline-success" href="{% url 'post_detail' car.pk %}">View</a>
<h4 style="display: inline-block; float: right"><strong>${{car.Price|floatformat:2}}</strong></h4>
</div>
</div>
{% endfor %}
</div>
I would really appreciate if you guys could help me
EDIT
So I changed the order of the views to first filter and then paginate but it still does the same thing. I get no error, but display all the content from the page rather than the filtered ones.
def posts(request):
cars = Userpost.objects.all()
myFilter = UserpostFilter(request.GET, queryset=cars)
cars = myFilter.qs
p = Paginator(Userpost.objects.all(), 9)
page = request.GET.get('page')
cars_list = p.get_page(page)
nums = "a" * cars_list.paginator.num_pages
context = {'cars':cars, "myFilter":myFilter, 'cars_list':cars_list, "nums":nums}
return render(request, 'store/userposts.html', context)
The paginator should work on the cars not on the orignal queryset, since you are paginate over the filtered results
def posts(request):
cars = Userpost.objects.all()
myFilter = UserpostFilter(request.GET, queryset=cars)
if not myFilter.is_valid():
raise ValidationError('filter is invalid')
cars = myFilter.qs
# This is the change
p = Paginator(cars, 9)
page = request.GET.get('page')
cars_list = p.get_page(page)
nums = "a" * cars_list.paginator.num_pages
context = {'cars':cars, "myFilter":myFilter, 'cars_list':cars_list, "nums":nums}
return render(request, 'store/userposts.html', context)

Django nested forms

I have trouble figuring out how to create nested forms. I have two models: Poll and Question (foreign key for Poll is inside Question model). I want it to be possible to add several questions for the poll dynamically inside one form. I've already tried making it work with inlineform_factory, but found troubles saving the form. Right now I have overcomplicated code that throws MultiValueDictError after saving the poll for the second time. I thought maybe there is some other way. Here's my code
models.py
class Question(models.Model):
type_choices = (
('text', 'Текстовый'),
('integer', 'Числовой'),
)
type = models.CharField(verbose_name=u'Тип вопроса', choices=type_choices, max_length=70)
text = models.CharField(verbose_name=u'Текст вопроса', max_length=255)
poll = models.ForeignKey('Poll', on_delete=models.CASCADE, related_name='questions')
class Poll(BaseFields):
objects = models.Manager()
published = PublishedManager()
title = models.CharField(verbose_name=u'Заголовок', max_length=70)
date_from = models.DateTimeField(u'Дата начала')
date_to = models.DateTimeField(u'Дата окончания')
status = models.IntegerField(choices=Status.choices, default=0)
def status_name(self):
return dict(Status.choices).get(self.status)
def update_url(self):
return reverse('poll_update', args=(self.id, ))
forms.py
QuestionInlineFormSet = inlineformset_factory(Poll, Question, extra=1, can_delete=False,
fields=('type', 'text', 'poll'),
widgets={
'type': w.Select(attrs={'class': 'form-control'}),
'text': w.TextInput(attrs={'class': 'form-control'}),
})
class PollForm(CommonForm):
class Meta(CommonForm.Meta):
model = Poll
views.py
class Create(BaseCreateView):
template_name = 'back/poll/poll.html'
page_title = 'Создание опроса'
model = Poll
form_class = PollForm
def form_valid(self, form):
result = super(Create, self).form_valid(form)
questions_formset = QuestionInlineFormSet(data=form.data, instance=self.object, prefix='questions_formset')
if questions_formset.is_valid():
questions_formset.save()
return result
def get_context_data(self, **kwargs):
context = super(Create, self).get_context_data(**kwargs)
context['questions_formset'] = QuestionInlineFormSet(prefix='questions_formset')
return context
class Update(BaseUpdateView):
template_name = 'back/poll/poll.html'
page_title = 'Редактирование опроса'
model = Poll
form_class = PollForm
def form_valid(self, form):
result = super(Update, self).form_valid(form)
questions_formset = QuestionInlineFormSet(data=form.data, instance=self.object, prefix='questions_formset')
if questions_formset.is_valid():
questions_formset.save()
return result
def get_context_data(self, **kwargs):
context = super(Update, self).get_context_data(**kwargs)
context['questions_formset'] = QuestionInlineFormSet(instance=self.get_object(), prefix='questions_formset')
return context
poll.html
{% extends 'back/base/form/base.html' %}
{% block form %}
{% include "back/includes/status_buttons.html" %}
<div class="row">
<div class="col-md-7">
<div class="row" style="margin-bottom: 15px;">
<div class="col-md-12">
{% include 'back/includes/status_label.html' %}
</div>
</div>
{% include "back/base/form/field.html" with field=form.title %}
{% include "back/base/form/datetime_field.html" with field=form.date_from %}
{% include "back/base/form/datetime_field.html" with field=form.date_to %}
{{ questions_formset.management_form }}
{% for question_form in questions_formset %}
{% include "back/poll/question.html" with form=question_form %}
{% endfor %}
<div style="float: right; margin-right: 45px">
<button class="btn btn-success add-form-row">Добавить вопрос</button>
</div>
</div>
</div>
{% endblock %}
question.html
<div class="questions">
<div class="row form-row">
<div class="form-group col-md-5{% if form.type.errors %} has-error{% endif %}">
<label>{{ form.type.label }}</label>
{{ form.type }}
<p class="help-block">{{ form.type.errors }}</p>
</div>
<div class="form-group col-md-5{% if form.text.errors %} has-error{% endif %}">
<label>{{ form.text.label }}</label>
{{ form.text }}
<p class="help-block">{{ form.text.errors }}</p>
</div>
<div class="col-md-2" style="margin-top: 25px">
<button type="button" class="btn btn-danger remove-form-row">✕</button>
</div>
</div>
</div>
<script>
function updateElementIndex(el, prefix, ndx) {
let id_regex = new RegExp('(' + prefix + '-\\d+)');
let replacement = prefix + '-' + ndx;
if ($(el).attr("for")) $(el).attr("for", $(el).attr("for").replace(id_regex, replacement));
if (el.id) el.id = el.id.replace(id_regex, replacement);
if (el.name) el.name = el.name.replace(id_regex, replacement);
}
function deleteForm(prefix, btn) {
let total = parseInt($('#id_' + prefix + '_formset' + '-TOTAL_FORMS').val());
if (total > 1) {
btn.closest('.form-row').remove();
let forms = $('.form-row');
$('#id_' + prefix + '_formset' + '-TOTAL_FORMS').val(forms.length);
for (let i = 0, formCount = forms.length; i < formCount; i++) {
$(forms.get(i)).find(':input').each(function () {
updateElementIndex(this, prefix, i);
});
}
}
}
function cloneMore(selector, prefix) {
let newElement = $(selector).clone(true);
let total = $('#id_' + prefix + '_formset' + '-TOTAL_FORMS').val();
newElement.find(':input:not([type=button]):not([type=submit]):not([type=reset])').each(function () {
let name = $(this).attr('name').replace('-' + (total - 1) + '-', '-' + total + '-');
let id = 'id_' + name;
$(this).attr({'name': name, 'id': id}).val('').removeAttr('checked');
});
newElement.find('label').each(function () {
let forValue = $(this).attr('for');
if (forValue) {
forValue = forValue.replace('-' + (total - 1) + '-', '-' + total + '-');
$(this).attr({'for': forValue});
}
});
total++;
$('#id_' + prefix + '_formset' + '-TOTAL_FORMS').val(total);
$(selector).after(newElement);
}
$(document).on('click', '.add-form-row', function (event) {
event.preventDefault();
cloneMore('.form-row:last', 'questions');
})
$(document).on('click', '.remove-form-row', function (event) {
event.preventDefault();
deleteForm('questions', $(this));
});
</script>
Here's a photo of what it should look like
Again, I want it to be possible to add questions, remove them, save the form. And after I click on the poll in the list of all polls and go to it's edit page I want already added questions to be there.
UPDATE
Found solution to MultiValueDictKeyError in this post
How to debug a Django MultiValueDictKeyError on Formset POST
Now the only problem I have is removing Questions from Poll. My delete button works, it removes the form from page, but after saving the document it reappears.

I cannot connect my form to my models for posting of grades

Models.py
class YearLevel(models.Model):
...
class Section(models.Model):
...
class Subject(models.Model):
...
class Student(models.Model):
first_name = models.CharField(max_length = 100, default = '')
last_name = models.CharField(max_length = 100, default = '')
year_level = models.OneToOneField(YearLevel, on_delete=models.SET_NULL, null = True)
section = models.OneToOneField(Section, on_delete=models.SET_NULL, null = True)
enrolled_subject = models.ManyToManyField(Subject)
parent = models.ForeignKey(Parent, on_delete=models.SET_NULL, null = True) #parent is from user models
class StudentGrade(models.Model):
PERIOD_CHOICES = [
...
]
student = models.ForeignKey(Student, on_delete=models.CASCADE,)
period = models.CharField(choices=PERIOD_CHOICES, max_length = 30)
subjects = models.ForeignKey(Subject, on_delete=models.CASCADE)
grade = models.DecimalField(default = 75.00, max_digits=4, decimal_places=2)
Views.py
def postgrade(request):
students = Student.objects.all().prefetch_related('enrolled_subject')
context = {
'students': students,
}
if request.method == "POST":
data = request.POST
grade_list = data.getlist('grade')
subject_list = data.getlist('subject')
student = Student.objects.get(pk= data.get('studentid')) #this is where they point my error
i=0
while i < len(grade_list):
enrolled_subject = Subject.objects.get(pk= subject_list[i])
new_grade = StudentGrade(student = student, period= data.get('period'), subjects = enrolled_subject, grade=grade_list[i])
new_grade.save()
i+= 1
Postgrade.html(template)
My queries are displaying properly, the problem is I get an error when i try to save the form
{% for students in students %}
<p>
<a class="btn btn-primary" data-bs-toggle="collapse" href="#collapse{{forloop.counter}}" role="button" aria-expanded="false" aria-controls="collapse{{forloop.counter}}">
{{students.first_name}} {{students.last_name}}
</a>
</p>
<div class="collapse" id="collapse{{forloop.counter}}">
<div class="card card-body">
<form method="POST" >
{% csrf_token %}
<input type="hidden" name="studentid" value="{{students.student.id}}">
<label for="period">Period:</label>
<select name="period" required>
<option selected>First Grading</option>
<option>Second Grading</option>
<option>Third Grading</option>
<option>Fourth Grading</option>
</select><br>
{% for subject in students.enrolled_subject.all %}
<input type="hidden" name="subject" value="{{subject.id}}">
<label for="{{subject.subject_name}}">{{subject.subject_name}}</label>
<input type="text" name="grade">
<br>
{% endfor %}
<button type="submit">upload grade</button>
</form>
</div>
</div>
{% endfor %}
My error says:
ValueError at /Information/postgrade/
invalid literal for int() with base 10: ''
and it points to my views.py:
student = Student.objects.get(pk= data.get('studentid'))
So i feel like there might be something wrong with my template or views, or maybe both
or I should drop out LOL
Thanks for the help