Why is my Class-based delete view not working? - django

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.)

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.

Custom format an inline formset

I'm create a template in Django, adding a form and formset to the template, but I don't like how it's formatting the formset by default. I've tried .as_table and .as_ul, but it's not formatting it to my liking. I'd like to see the following from the formset:
Ingredient Percentage Delete
ingredient1 .55
ingredient2 .22
ingredient3 .33
I've tried the code in "https://stackoverflow.com/questions/17492374/how-to-render-formset-in-template-django-and-create-vertical-table" but when I implement it, I'm getting two extra column, "ID" and "Recipe Name". I don't know where those columns are coming from and I don't know how to get rid of them.
Example:
models.py
class Recipe(models.Model):
name = models.CharField(max_length=200, null=True)
description = models.CharField(max_length=200, null=True, blank=True)
def __str__(self):
return self.name
class Recipe_Ingredient(models.Model):
recipe_name = models.ForeignKey(Recipe, null=True, on_delete = models.SET_NULL)
ingredient = models.ForeignKey(Product, null=True, on_delete= models.SET_NULL)
recipe_percent = models.DecimalField(max_digits=8, decimal_places=5, blank=True)
views.py
def recipeUpdate(request, recipe_id):
RecipeIngredientFormSet2 = inlineformset_factory(Recipe, Recipe_Ingredient, extra=10, fields=('ingredient', 'recipe_percent'))
recipe = Recipe.objects.get(pk=recipe_id)
formset = RecipeIngredientFormSet2(instance=recipe)
context = {'formset' : formset}
return render(request, 'accounts/recipe_form.html', context)
recipe_form.html
{% extends 'accounts/main.html' %}
{% load static %}
{% block content %}
<div class="row">
<div class="col-md-6">
<div class="card card-body">
<form action="" method="POST">
{{ form }}
<p></p>
<!--{{ formset.as_table }}-->
<p></p>
{{ formset.management_form}}
<!--{% for form in formset %}
{{ form }}
{% endfor %}-->
<table>
<thead>
{% for form in formset %}
{% if forloop.first %}
{% for field in form %}
<th>{{ field.label_tag }}</th>
{% endfor %}
{% endif %}
</thead>
<tbody>
<tr>
{% for field in form %}
<td>{{ field }}</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
<input type="submit" name="Submit">
</form>
</div>
</div>
</div>
{% endblock %}
Found the answer. You've got to add the formset with a .management_form tag, then in table, loop through each form in form set. If it's the first loop, add the headers to the tables. In all other loops, add each field from the form that you want in the table.
The updated HTML that I'm using is below.
{% extends 'accounts/main.html' %}
{% load static %}
{% block content %}
<div class="row">
<div class="col-md-6">
<div class="card card-body">
<form action="" method="POST">
{% csrf_token %}
{{ form }}
{{ formset.management_form }}
<table>
{{ form.id }}
{% for p in formset %}
<tr>
{% if forloop.first %}
<td>{{ p.DELETE.label_tag }}</td>
<td>{{ p.ingredient.label_tag }}</td>
<td>{{ p.recipe_percent.label_tag }}</td>
<p></p>
{% endif %}
</tr>
<!--{{ p.id }}
{{ p.ORDER }}-->
<tr></tr>
<td>{{ p.DELETE }}</td>
<td>{{ p.ingredient }}</td>
<td>{{ p.recipe_percent }}</td>
</tr>
{% endfor %}
</table>
<input type="submit" name="Submit">
</form>
</div>
</div>
</div>
{% endblock %}

save() prohibited to prevent data loss due to unsaved related object 'user'

i am trying to save data in a table when a user click the checkout button of add to cart but it is showing me the above mention error i am unable to understand and one more thing is happening when i logout my the cart which i saved also got erased is it shomehow related to that i don't know
here is my views.py for checkout button
class Checkout(View):
def post (self, request,):
user = request.session.get('user')
ids = (list(request.session.get('cart').keys()))
sections = Section.get_sections_by_id(ids)
for section in sections:
order = Order(user = User(id=user),
section = section,
price = section.price,
)
order.save()
my views.py for cart.html
class Cart(View):
def get (self, request):
ids = (list(request.session.get('cart').keys()))
sections = Section.get_sections_by_id(ids)
print(sections)
return render(request, 'cart.html', {'sections': sections})
my urls.py
urlpatterns = [
path('cart/', Cart.as_view(),name='cart'),
path('Check-Out/', Checkout.as_view(),name='checkout'),
]
my cart.html
{% extends 'base.html' %}
{% load static %}
{% load cart %}
{% load custom %}
{% block head %}
<link rel="stylesheet" href="{% static 'css/cart.css' %}">
{% endblock %}
{% block content %}
<div class="container jumbotron">
<section>
<h1>My cart</h1>
<table class="table">
<thead>
<tr>
<th scope="col">S.no</th>
<th scope="col">Subject</th>
<th scope="col">Section</th>
<th scope="col">Teacher</th>
<th scope="col">Duration</th>
<th scope="col">Price</th>
</tr>
</thead>
{% for section in sections%}
<tbody style="margin-bottom: 20px;">
<tr>
<th scope="row">{{forloop.counter}}</th>
<td>{{section.subject.name}}</td>
<td>{{section.title}}</td>
<td>{{section.teacher}}</td>
<td>{{section.content_duration}}</td>
<td>{{section.price|currency}}</td>
</tr>
</tbody>
{% endfor %}
<tfoot>
<tr>
<th> Total</th>
<th></th>
<th></th>
<th></th>
<th></th>
<th>{{sections|total_price:request.session.cart|currency}}</th>
</tr>
<hr>
</tfoot>
</table>
<button type="button" data-toggle="modal" data-target="#exampleModal" style="float: right; margin-left:5px" class="btn btn-outline-primary">Check Out</button>
<button type="button" style="float: right; margin-left:5px" class="btn btn-info">Back To Site</button>
</tfoot>
</section>
</div>
<!-- Modal -->
<div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Please Verify</h5>
<input type="button"class="btn-close btn-link" style="text-decoration:none; border:none; font-size:20px;" data-dismiss="modal" aria-label="Close" value="X">
</div>
<div class="modal-body">
<form action="{% url 'transactions:checkout' %}" method="Post">
{% csrf_token %}
<input type="submit" class="btn float-right btn-primary" value='Go Ahead'>
</form>
</div>
</div>
</div>
</div>
{% endblock %}
and my models.py
class Order(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE,)
section = models.ForeignKey(Section, on_delete=models.CASCADE )
price = models.FloatField(blank=False)
update_at = models.DateTimeField(auto_now=True, editable=False)
def placeorder(self):
self.save()
please help if you can an
The issue caused by this line:
order = Order(user = User(id=user)
Using User(id=user) means you want to create an unsaved User and use it in an unsaved Order and then saving the order, but this will not work because you haven't saved the User yet, as mentioned by the error.
You can just simply just use the existing user in the order like this:
order = Order(user=user, section=section, price=section.price)
order.save()

Django how to display list users with some data in template

I want to display the list of users with some objects in 2 modelapps created.
these are the models.
first model:
class UserProfile(models.Model):
user = models.OneToOneField(User,on_delete=models.CASCADE)
indirizzo = models.CharField(max_length=50)
citta = models.CharField(max_length=50)
paese = models.CharField(max_length=50)
ecap = models.CharField(max_length=4)
descrizione = models.CharField(max_length=100, default='')
image = models.ImageField(upload_to='profile_image', blank=True,null=True)
second model:
class Ore(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="ore",null=True,)
data = models.DateField(default=timezone.now)
oret = models.CharField(max_length=3,)
contrattiok = models.PositiveSmallIntegerField()
contrattiko = models.PositiveSmallIntegerField(default=0,)
nomecognome = models.CharField(max_length=100,blank=True)
my view:
def inizio(request):
users = User.objects.all()
return render (request, "base.html", {"users":users})
my template:
{% for users in users %}
<tbody>
<tr>
<td>
<img src="{{ users.userprofile.image.url }}"class="thumbnail">
<h4 class="small font-weight-bold">{{users}}</h4>
</td>
<td><h4 class="small font-weight-bold">{{users.last_name}}</h4></td>
<td class="text-center">
<h4 class="small font-weight-bold" class="btn btn-primary btn-circle">{{ users.ore.contrattiok }}</h4> <<<<<(does not work)
</td>
</tr>
{% endfor %}
I saw several problems in your templates.
1. It would be better to make different variable of users loop to increase readability code.
don't do this: {% for users in users %}
but instead: {% for user in users %}
so then you can use it with user instead of users inside loop like:
{{ user.last_name }}
2. your <tbody> inside forloop users, but theres no </tbody> right before the {% endfor %}.
But I suggest you to do not include <tbody> inside forloop.
Do this instead:
<tbody>
{% for user in users %}
<tr><td></td></tr>
{% endfor %}
</tbody>
since your foreign key is inside Ore model instead
(one to many relationship which means 1 user has many ores),
so you need to loop every ore on each user.
{% for user in users %}
{% for ore in user.ore.all %}
{{ ore.contrattiok }}
{% endfor %}
{% endfor %}
so the final result will be like this:
<tbody>
{% for user in users %}
<tr>
<td>
<img src="{{ user.userprofile.image.url }}" class="thumbnail">
<h4 class="small font-weight-bold">{{ user }}</h4>
</td>
<td><h4 class="small font-weight-bold">{{user.last_name}}</h4></td>
<td class="text-center">
{% for ore in user.ore.all %}
<h4 class="small font-weight-bold" class="btn btn-primary btn-circle">
{{ ore.contrattiok }}
</h4>
{% endfor %}
</td>
</tr>
{% endfor %}
</tbody>
EDITED
based on your comment, so you want to sum the total of contrattiok field?
if that so, you need to change your view using annotate
from django.db.models import Sum
users = User.objects.annotate(total_contrattiok=Sum('ore__contrattiok'))
then in your template:
{% for user in users %}
<td class="text-center">
<h4 class="small font-weight-bold" class="btn btn-primary btn-circle">
{{ user.total_contrattiok }}
</h4>
</td>
{% endfor %}

Django post duplicates on page refresh

I have this view which adds replies to a topic:
#login_required
def post_reply(request, topic_id):
tform = PostForm()
topic = Topic.objects.get(pk=topic_id)
args = {}
if request.method == 'POST':
post = PostForm(request.POST)
if post.is_valid():
p = post.save(commit = False)
p.topic = topic
p.title = post.cleaned_data['title']
p.body = post.cleaned_data['body']
p.creator = request.user
p.user_ip = request.META['REMOTE_ADDR']
p.save()
tid = int(topic_id)
args['topic_id'] = tid
args['topic'] = topic
args['posts'] = Post.objects.filter(topic_id= topic_id).order_by('created')
return render_to_response("myforum/topic.html",args)
else:
args.update(csrf(request))
args['form'] = tform
args['topic'] = topic
return render_to_response('myforum/reply.html', args,
context_instance=RequestContext(request))
The problem is that when user refershes the page after posting a reply her reply is being duplicated. How to avoid this?
UPDATE:Here is the related template:
{% extends "base.html"%}
{% load static %}
{% block content%}
<div class="panel">
<div class="container">
<!-- Posts -->
<div class="col-md-12">
<h3>{{ topic.title }}</h3>
<table class="table table-striped">
<tr class="col-md-9"><td>{{ topic.description }}</td></tr>
<tr class="col-md-3"><div class="userpanel"><td>{{ topic.created }}</td></div></tr>
{% for post in posts %}
<tr class="col-md-12 userpanel"><td>{{ post.title }}</td></tr>
<tr class="">
<td>
<div class="col-md-9 userpanel">{{ post.body }} <br> {{ post.created }} </div>
</td>
<td>
<div class="col-md-3 userpanel">{{ post.creator }} <br> {{ post.created }} </div>
</td>
</tr>
{% endfor %}
</table>
<hr />
<!-- Next/Prev page links -->
{% if posts.object_list and posts.paginator.num_pages > 1 %}
<div class="pagination">
<span class="step-links">
{% if posts.has_previous %}
previous <<
{% endif %}
<span class="current">
Page {{ posts.number }} of {{ topics.paginator.num_pages }}
</span>
{% if posts.has_next %}
>> next
{% endif %}
</span>
</div>
{% endif %}
<a class="button" href="/forum/reply/{{topic.id}}"> Reply </a>
</div> <!-- End col-md-12 -->
</div> <!-- End container -->
</div>
{% endblock %}
Always - I repeat, always, redirect after a POST.
So instead of doing a return render_to_response("myforum/topic.html",args) when your form is valid, do a return HttpResponseRedirect(url_of_your_view) (https://docs.djangoproject.com/en/1.7/ref/request-response/#django.http.HttpResponseRedirect)
Update after OP's comments:
You should use reverse (https://docs.djangoproject.com/en/1.7/ref/urlresolvers/#reverse) to create the url to redirect to:
return HttpResponseRedirect(reverse('myforum.views.topic', args=[topic_id]))
Also, I recommend to name your views (and drop strings for defining them since they are deprecated), so change your urls.py line like this:
from myforum.views import topic
...
url(r'^topic/(\d+)/$', topic, name='view_topic'),
...
And then just do a reverse('view_topic', args=[topic_id]) to get the url of your view.