got an unexpected keyword argument 'id' - django

I'm trying to do a query when the object has the status = 'Opened'. And display in a table where I will have a button to give a solution for my form and change status='Pending'. But when I click in the button I get this error.
What I'd like to do for really is display was a form for each data, but when I do a for loop for each one form my data insnt show, how you can see my editable.html. I just get the buttons to do an action, and they are working fine.
url:
path('manutencao_os_status/<int:id>', views.manutencao_ordem_de_servico, name='manutencao_os_status'),
path('manutencao_ordem_de_servico/', views.manutencao_ordem_de_servico, name='manutencao_ordem_de_servico'),
views.py
def manutencao_ordem_de_servico(request):
ordem_servico = OrdemServico.objects.filter(status='Aberto').order_by('id')
form = FormOrdemServico(ordem_servico)
if request.method != 'POST':
return render(request, 'ordemservico/manutencao_ordem_de_servico.html', {
'form': form,
'ordem_servico': ordem_servico
})
form = FormOrdemServico(request.POST, ordem_servico)
if not form.is_valid():
return render(request, 'ordemservico/manutencao_ordem_de_servico.html', {
'form': form,
'ordem_servico': ordem_servico
})
ordem_servico.save()
return redirect('ordemservico:manutencao_ordem_de_servico')
def manutencao_os_status(request, id):
ordem_servico = OrdemServico.objects.get(pk=id)
ordem_servico.status = 'Em Aprovação'
ordem_servico.save()
return redirect('ordemservico:manutencao_os_status')
html:
{%extends 'base.html' %}
{%block conteudo %}
<h1>Ordens de Serviço</h1>
<section class="content">
<div class="container-fluid">
<div class="row">
<div class="card card-primary">
<div class="table table-bordered">
<table class="table table-bordered">
<thead>
<tr>
<td>Condition:</td>
<td>ID:</td>
<td>Name:</td>
<td>Status:</td>
<td>Solution:</td>
</tr>
</thead>
<tbody>
{% for os in ordem_servico %}
<tr>
<td>
<a href="{% url 'ordemservico:manutencao_os_status' os.id %}"
class="btn btn-success">Aprovar</a>
</td>
<td>{{os.id}}</td>
<td> {{os.name}}</td>
<td>{{os.status}}</td>
<td>{{os.solution}}</td>
</tr>
{%endfor%}
</tbody>
</table>
</div>
</div>
</div>
</div>
</section>
{% endblock %}
my editable.html:
{%for os in ordem_servico %}
<form action="{% url 'ordemservico:manutencao_os_status' os.id %}" method="POST" enctype="multipart/form-data">
{% csrf_token %}
<fieldset>
<legend><h2>Ordens de Serviço</h2></legend>
<table class="table">
{{ os.form }}
<tr>
<td colspan="2">
<button type="submit" class="btn btn-primary">Solucionar</button>
</td>
</tr>
</table>
</fieldset>
</form>
{%endfor%}
{% endblock %}

You routed to the wrong view, it should be:
path(
'manutencao_os_status/<int:id>',
views.manutencao_os_status,
name='manutencao_os_status'
),
In the view you should likely redirect to the manutencao_ordem_de_servico view:
def manutencao_os_status(request, id):
ordem_servico = OrdemServico.objects.filter(pk=id).update(
status='Em Aprovação'
)
return redirect('ordemservico:manutencao_ordem_de_servico')
Note: A GET request is not supposed to have side-effects, hence updating
objects when a user makes a GET request, is not compliant with the HTTP
standard. Therefore it might be better to update a OrdemServico with a POST request.

Related

HTMX form submission produces a duplicate form

{% extends "IntakeApp/base3.html" %}
{% load static %}
{% load crispy_forms_tags %}
{% block heading %}
<h2>Allergies for {{request.session.report_claimant}}</h2>
{% endblock %}
{% block content %}
<form hx-post="{% url 'allergy' %}" hx-target="#allergy_target" hx-swap="outerHTML">{% csrf_token %}
<div class="form-row">
<div class="form-group col-md-2 mb-0">
{{ form.allergen|as_crispy_field }}
</div>
</div>
<button type="submit" class="btn btn-primary">Add</button>
</form>
<div class="container-fluid">
<table class="table table-striped table-sm" id="med-table">
<thead>
<tr>
<th>Allergen</th>
</tr>
</thead>
<tbody id="allergy_target">
{% for allergy in allergy_list %}
<tr>
<td>{{allergy.allergen}}</td>
<td>
<form method="POST" action="{% url 'allergy-delete' allergy.id %}">{% csrf_token %}
<input class="btn btn-danger btn-sm" type="submit" value="Delete">
</form>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endblock %}
class AllergyCreateView(generic.CreateView):
model = Allergy
template_name = 'IntakeApp/allergy_form.html'
form_class = AllergyForm
def form_valid(self, form):
form.instance.assessment = Assessment.objects.get(id=self.request.session['assessment_id'])
return super(AllergyCreateView, self).form_valid(form)
def get_success_url(self):
return reverse_lazy("allergy")
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
assessment_id = self.request.session['assessment_id']
allergy_list = Allergy.objects.filter(assessment=assessment_id)
context["allergy_list"] = allergy_list
return context
I tried to all the different hx-swap options, but none fix it...It does post correctly and the swap does work, just not sure why I am getting another form in there. Please help
I added the View above. I think thats were my issue is...not sure if I am supposed to be doing this way or not?
Seems like you're trying to render the same html content in your view, which instead should only take a specific element.
You can try to use hx-select="#allergy_target" so htmx will only fetch the table content.

Django object update using htmx and SingleObjectMixin

I'm using htmx for the first time. I have a table where each cell is a grade object. Previous to htmx I made each cell a link to an UpdateView for the object. I am now trying to have the user modify the the object's score field directly in the table using htmx. I'm sure I'm doing several things wrong.
My page loads as expected and the table is displayed as expected. when I type in a cell, I get an error Forbidden 403. CSRF Verification Failed.
The purpose of this post/question is to figure out how to get past this 403 error. Having said that, if it turns out that I'm going down the completely wrong path with using a SingleObjectMixin, please let me know.
View
class GradeChange(SingleObjectMixin, View):
""" view to handle htmx grade change"""
model = Grade
def post(self, request, *args, **kwargs):
grade = self.get_object()
assessment = Assessment.objects.get(grade=grade.pk)
print(assessment)
classroom = Classroom.objects.get(classroom=grade.cblock)
print(classroom)
if grade.score == "EXT" or grade.score=="APP" or grade.score=="DEV" or grade.score=="BEG":
grade.save()
return HttpResponse("S")
else:
return HttpResponse("")
template
<table class="table table-bordered table-sm">
<thead>
<tr>
<th class="col-3" scope="col">Students</th>
{% for obj in objective_list %}
<th class="col-2" scope="col">{{ obj.objective_name }}</th>
{% endfor %}
<th scope="col">Comments</th>
</tr>
</thead>
<tbody>
<form action="" method="post" class="form-group">
{% csrf_token %}
{% for student in student_list %}
<tr>
<td >{{ student.student_first }} {{ student.student_last }}</td>
{% for g in grade_list %}
{% if g.student.id == student.id %}
<td>
<input type="text" hx-post="{% url 'gradebook:grade-change' g.pk %}" hx-target="" hx-trigger="keyup delay:2s" class="form-control score" title={{ g.score }} name="score" id="input-{{ forloop.counter0 }}" placeholder={{ g.score }} required>
</td>
{% endif %}
{% endfor %}
<td>
{% for comms in comment_list %}
{% if comms.student == student %}
<a class="grade-comment" href="{% url 'gradebook:addcomment' comms.pk assess_pk class_pk %}">{{ comms.comment|truncatewords:10 }}</a>
{% endif %}
{% endfor %}
</td>
</tr>
{% endfor %}
</form>
</tbody>
</table>
EDIT - a solution
I came across this, which works.
<script>
document.body.addEventListener('htmx:configRequest', (event) => {
event.detail.headers['X-CSRFToken'] = '{{ csrf_token }}';
});
</script>
The CSRF token must be included in the HTMX POST request. Currently you include it only in the regular form, but the HTMX request is initiated from a child input element where the token is not present. So just include the following hx-header attribute to a parent element like the <form> or event the <body> is a good candidate:
<body hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}'>

form doesn't submit productbacklogs to database

here is my project code .
I after posting data by form nothing happens.
#model.py
from django.db import models
from projectapp.models import Project
class Productbacklog(models.Model):
project=models.ForeignKey(Project,on_delete=models.CASCADE,default=None)
pbId=models.IntegerField(primary_key=True)
pbTitle=models.CharField(max_length=100)
pbPriority=models.IntegerField(blank=True, null=True)
class Meta:
unique_together=('project','pbId')
def __str__(self):
return self.pbTitle
#forms.py
from django import forms
from productbacklogapp.models import Productbacklog
from projectapp.models import Project
class ProductbacklogForm(forms.ModelForm):
class Meta:
model = Productbacklog
exclude=('pbId','project')
fields=['pbTitle']
#views.py
def productbacklogall(request):
if request.method == 'POST':
form = ProductbacklogForm(request.POST)
if form.is_valid():
form.instance.manage = Project.objects.get_or_create(cname=form.cleaned_data['manage_id'])
form.save()
messages.success(request, ('new productbacklog added'))
return redirect('productbacklogall')
else:
pb_all=Productbacklog.objects.all()
return render(request, 'productbacklogall.html', {'pb_all':pb_all})
I think that issue is on forms.py or views.py but I can't find it.
I'm so greatful if anyone can help me.
here is also my html code,when I submit something the method is post but I don't know why it doesn't go to data basse.
#productbacklogall.html
{%extends 'base.html'%}
{%block title%}
<title>backlog all</title>
{%endblock title%}
{%block content%}
</br>
{% if messages %}
{% for message in messages %}
<div class="alert alert-primary" role="alert">
{{ message }}
×
</div>
{% endfor %}
{% endif %}
<div class="container">
<form method="POST" class="row">
{% csrf_token %}
<label class="col-lg-4"></label>
<input type="text" class="form-control" name="Project" placeholder="project title?"/>
<input type="number" class="form-control" name="pbId" placeholder="backlog id?"/>
<input type="text" class="form-control" name="pbTitle" placeholder="pb title?"/>
<button type="submit" class="btn btn-primary col-lg-2">add project</button>
</form>
</div>
</br>
</br>
<table class="table table-bordered text-center">
<thead class="thead-dark">
<tr>
<th scope="col"> backlog-title</th>
<th scope="col">Edit</th>
<th scope="col">delivarable_task</th>
<th scope="col">related project</th>
</tr>
</thead>
<tbody>
{% load static %}
{% if pb_all %}
{% for obj in pb_all %}
<tr>
<td>{{ obj.pbTitle }}</td>
<td><a href='{% url "delete_productbacklog" obj.pbId %}'>delete</a></td>
<td> <a href=#> delivarabletask </a></td>
<td>{{ obj.project.pbTitle }}</td>
</tr>
{% endfor %}
{% endif %}
</tbody>
</table>
</div>
{%endblock content%}
Your form data are not valid, to see them, add this code to your views :
else:
messages.error(request, "Error")
like this :
def productbacklogall(request):
if request.method == 'POST':
form = ProductbacklogForm(request.POST)
if form.is_valid():
form.instance.manage = Project.objects.get_or_create(cname=form.cleaned_data['manage_id'])
form.save()
messages.success(request, ('new productbacklog added'))
else:
messages.error(request, "Error")
return redirect('productbacklogall')
else:
pb_all=Productbacklog.objects.all()
return render(request, 'productbacklogall.html', {'pb_all':pb_all})

Why is my Class-based delete view not working?

My delete view is not working and the error message is:
Page not found (404) Request Method: GET.
I am trying to delete my uploaded file based on its primary key and so far, my url is able to link me correctly based on the pk.
This is my urls.py:
path('post/<int:post_id>/lesson_delete/<int:lesson_id>', LessonDeleteView.as_view(), name='lesson_delete'),
My views.py:
class LessonDeleteView(DeleteView):
model = Lesson
success_url = '../'
template_name = 'lesson_confirm_delete.html'
This is the html template that brings user to the delete view:
{% extends "store/base.html" %}
{% block content %}
<div id="main">
<table class="table mb-0">
<thead>
<tr>
<th>Title</th>
<th>Author</th>
<th>Download</th>
<th>Delete</th>
</tr>
</thead>
<tbody>
{% for l in Lesson %}
<tr>
<td>
{% if l.file %}
{{ l.title }}
{% else %}
<h6>Not available</h6>
{% endif %}
</td>
<td>{{ l.post.author }}</td>
<td>{% if l.file %}
Download
{% else %}
<h6>Not available</h6>
{% endif %}
</td>
<td> <a class="btn btn-danger btn-sm mt-1 mb-1" href="{% url 'lesson_delete' lesson_id=l.id %}">Delete</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endblock %}
This is my html template for DeleteView:
{% extends "store/base.html" %}
{% block content %}
<div class="content-section" id="main">
<form method="POST">
{% csrf_token %}
<fieldset class="form-group">
<legend class="border-bottom mb-4">Delete Lesson</legend>
<h2>Are you sure you want to delete the post "{{object.title}}"?
</h2>
</fieldset>
<span style="display:inline;">
<button class="btn btn-outline-danger" type="submit">Yes, Delete!
</button>
<a class="btn btn-outline-secondary" href ="">Cancel</a>
</span>
</form>
</div>
{% endblock content %}
This is my Lesson Model:
class Lesson(models.Model):
title = models.CharField(max_length=100)
file = models.FileField(upload_to="lesson/pdf")
date_posted = models.DateTimeField(default=timezone.now)
post = models.ForeignKey(Post, on_delete=models.CASCADE, null=False, blank=False)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('lesson_upload', kwargs={'pk': self.pk})
Is you template called 'lesson_confirm_delete.html'?
Also, for your success url, I have feeling you don't have a path '../'. It should the specific path you want it to go to.
(Sorry, I can't comment yet.)

Django formset is not getting saved

I have a formset and I am trying to save it back. But, when I try to check if formset.is_valid() and save, validation always fails even if nothing in the formset has been changed. I am displaying already existing data using formset and trying to edit it. I don't know where I am going wrong. Can someone please help? :(
views.py
def product(request, product_id):
product = get_object_or_404(Product, pk=product_id)
productform = ProductForm(instance=product)
itemformset = modelformset_factory(Item, form = ItemForm, extra=0)
items = itemformset(queryset = Item.objects.filter(Product=product_id), prefix='items', )
if request.method == 'POST':
productform = ProductForm(request.POST, instance=product)
items = itemformset(request.POST, queryset = Item.objects.filter(Product=product_id), prefix='items', )
if productform.is_valid():
productform.save()
if items.is_valid():
items.save()
else:
print("fail")
context = {
'productform':productform,
'product_id': product_id,
'items':items,
}
return render(request, 'product.html', context )
.html
{% bootstrap_form productform %}
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">
<a data-toggle="collapse" data-parent="#accordion" href="#Items"> Items List </a>
</h4>
</div>
<div id="Items" class="panel-collapse collapse">
<table class="table table-bordered">
<thead>
<tr>
<th>Name</th>
<th>Tag</th>
</tr>
<thead>
<tbody>
{{ items.management_form }}
{% for form in items %}
<tr>
{{ form.id}}
<td> {{ form.Name }} </td>
<td> {{ form.Tag }} </td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
You are rendering the form fields individually, but not displaying the errors. First, allow Django to render the forms and get the view working. Once you've done that, you can customise the template if required.
<tbody>
{{ items.management_form }}
{% for form in items %}
{{ form }}
{% endfor %}
</tbody>
See the docs on using formsets in templates rendering form fields manually for more information.
Doing it this way should allow you to see errors in the template. Another option is to print or log productform.errors and items.errors. Your current print("fail") tells you there is a problem, but not what the problem is.