Delete model instance button - django

I have a for loop that lists all the testimony instances in my model. I'd like to have the button in the code below delete the related instance when clicked.
html
{% block content %}
{% for testimony in testimonies %}
<a href="{% url "main:update_testimony_view" slug=testimony.slug %}">
<h3>{{testimony.name}}</h3>
<button type="button" class="btn btn-danger">Delete</button>
</a>
{% endfor %}
****
{% endblock content %}
views.py
def create_testimony_view(request):
if request.method == "POST":
form = CreateTestimonyForm(request.POST)
if form.is_valid():
testimony = form.save(commit=False)
testimony.save()
return redirect('main:homepage_view')
else:
form = CreateTestimonyForm
context = {
"title": "Create - Testimony",
"form": form,
"testimonies": Testimony.objects.all(),
}
return render(request=request, template_name="main/create/create_testimony.html", context=context)
def update_testimony_view(request, slug):
instance = get_object_or_404(Testimony, slug=slug)
if request.method == 'POST':
form = CreateTestimonyForm(
request.POST, request.FILES, instance=instance)
if form.is_valid():
testimony = form.save(commit=False)
testimony.save()
return redirect('main:homepage_view')
else:
form = CreateTestimonyForm(instance=instance)
context = {
"title": "Update - Testimony",
"form": form,
"instance": instance,
}
return render(request=request, template_name="main/create/create_testimony.html", context=context)
Thanks for any help

You need to make a POST request to the server which will delete the instance.
Please have a look at Form documentation. https://docs.djangoproject.com/en/3.0/topics/forms/

You need to add simple form and view to delete testimony.
html,
{% for testimony in testimonies %}
<a href="{% url "main:update_testimony_view" slug=testimony.slug %}">
<h3>{{testimony.name}}</h3>
<form action="{% url 'main:delete_testimony' testimony.pk %}" method="POST">
<button type="button" class="btn btn-danger">Delete</button>
</form>
</a>
{% endfor %}
view,
def delete_testimony(request, pk):
deleted = False
try:
Testimony.objects.delete(pk=pk)
deleted = True
except Testimony.DoesNotExist:
pass
return JsonResponse({'deleted':deleted})

Related

Django form and formset are not valid

I'm trying to make a view containing one form and one formset but something does not work.
both form and formset after checking if .is_valid returns false. I do not really undersand why it is like that
def ProductCreateView(request):
context = {}
created_product = None
form = ProductForm()
if request.method == 'POST':
form = ProductForm(request.POST)
if form.is_valid():
created_product = form.save()
print("Successfully created new product: {}".format(created_product))
else:
print("form is not valid")
#print(request.POST) returns csrfmiddlewaretoken ...
#print(request.FILES) returns file : inmemoryuploadedfile ...
#print(list(request.POST.items()))
context['form'] = form
formset = ProductPhotoInlineFormset()
if request.method=='POST':
formset = ProductPhotoInlineFormset(request.POST or None, request.FILES or None, instance=created_product)
if formset.is_valid():
created_images = formset.save()
print("Successfully created new imagest: {}".format(created_images))
else:
print("formset is not valid")
context['formset'] = formset
return render(request, "Ecommerce/create_product_test.html", context)
my template - create_product_test.html
{% extends 'base.html' %}
{% block content %}
<div id="alert-box">
</div>
<div id="image-box" class="mb-3">
</div>
<div id="image-box"></div>
<div class="form-container">
<button class="btn btn-primary mt-3 not-visible" id="confirm-btn">confirm</button>
<form method="POST" enctype="multipart/form-data" action="" id="image-form">
{% csrf_token %}
<div>
{{form}}
{{formset.management_form}}
{{formset.as_p}}
</div>
</form>
</div>
{% endblock content %}
forms.py file
ProductPhotoInlineFormset = inlineformset_factory(
Product,
Photo,
fields=('file',),
form=PhotoForm,
extra=1,
)
where is the problem ?
You can find out what's wrong with the form with:
print(form.errors)
print(form.non_field_errors())
and for a formset:
print(formset.errors)
print(formset.non_form_errors())
This way, you can easily find out why the form is not valid.

Django booleanfield modelform

So I'm making a to-do list and I made a booleanfield modelform which has attribute "complete". I want that user to check it when it's complete and I tried wriring if task.complete == True cross out the item and it didn't work(it only worked when I checked it from the admin panel). Then I tried form.complete instead of task.complete and it doesn't do anything.
models:
class Task(models.Model):
title = models.CharField(max_length=200)
complete = models.BooleanField(default=False)
created = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.title
forms:
from .models import *
class TaskForm(forms.ModelForm):
title = forms.CharField(widget= forms.TextInput(attrs={'placeholder':'Add new task...'}))
class Meta:
model = Task
fields = '__all__'
html:
<div class="main-container">
<form method="POST" action="/">
{% csrf_token %}
<input type="submit"/>
{{ form.title }}
</form>
{% for task in tasks %}
{{ form.complete }}
{% if form.complete == True %}
<h1><strike>{{task.title}}</strike></h1>
{% else %}
<h1>{{task.title}}</h1>
{% endif %}
{% endfor %}
</div>
views:
def index(request):
tasks = Task.objects.order_by('-created')
form = TaskForm()
if request.method == 'POST':
form = TaskForm(request.POST)
if form.is_valid():
form.save()
return redirect('/')
context = {
'tasks': tasks,
'form': form,
}
return render(request, 'to-do.html', context)
There are some problems with your code I don't know how to explain. Try this. It should work.
<div class="main-container">
<form method="POST" action="/"> # create new task
{% csrf_token %}
{{ form.title }}
<input type="submit" name="new-task"/>
</form>
<form method="post"> # update task status
{% csrf_token %}
{% for task in tasks %}
{% if task.complete %}
<input type="checkbox" name="if_completed" checked value="{{ task.pk }}">
<h1><strike>{{task.title}}</strike></h1>
{% else %}
<input type="checkbox" name="if_completed" value="{{ task.pk }}">
<h1>{{task.title}}</h1>
{% endif %}
{% endfor %}
<input type="submit" name="update-task"/>
</form>
</div>
view.py (Only for form, add your other code with it)
from django.http import HttpResponseRedirect
from django.urls import reverse
def index(request):
tasks = Task.objects.order_by('-created')
form = TaskForm()
if request.method == 'POST':
if 'new-task' in request.POST:
form = TaskForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect(reverse('home')) # replace home with url name where you want to redirect
elif 'update-task' in request.POST:
task_pk = request.POST.getlist("if_completed")
for i in task_pk:
Task.objects.filter(pk=i).update(complete=True) # I have replace pk with i here
return HttpResponseRedirect(reverse('home')) # replace home with url name where you want to redirect
context = {
'tasks': tasks,
'form': form,
}
return render(request, 'to-do.html', context)
in forms.py
class TaskForm(forms.ModelForm):
class Meta:
model = Task
fields = ('title',)
widgets = {
'title': forms.TextInput(attrs={'placeholder':'Add new task...'})
}
This should work. There may be be some error because of typos or indentation. Let me know if you get any issue
def index(request):
tasks = Task.objects.order_by('-created')
form = TaskForm()
context = {
'tasks': tasks,
'form': form,
}
if request.method == 'POST':
if 'new-task' in request.POST:
form = TaskForm(request.POST)
if form.is_valid():
form.save()
elif 'update-task' in request.POST:
task_pk = request.POST.getlist("if_completed")
for i in task_pk:
Task.objects.filter(pk=pk).update(complete=True)
return render(request, 'to-do.html', context)

Django not able to submit form using ModelForm

The form is always sending a Get request instead of a Post which has been explicitly added using method = "POST". So, not able to persist the data to db. I have just started with Django so, any help will be appreciated.
Below are the code snippets:
create_order.html
<form method="POST" action="{% url 'home' %}">
{% csrf_token %}
{{form}}
<input class="btn btn-primary btn-sm" type="submit" name="Submit">
</form>
urls.py
urlpatterns = [
path('', views.dashboard, name='home'),
path('products/', views.product, name='products'),
path('customer/<str:cust_id>/', views.customer, name='customer'),
path('create_order/', views.create_order, name='create_order'),
]
views.py
def create_order(request):
form = OrderForm()
if request.method == 'POST':
print("In Post", request.method)
form = OrderForm(request.POST)
if form.is_valid():
form.save()
return redirect('/')
else:
print("In else", request.method)
print(form.is_valid())
if form.is_valid():
form.save()
return redirect('/')
context = {'form' : form}
return render(request, 'accounts/create_order.html', context)
terminal output
In else GET False
You are making a POST request to the wrong view. It should be the create_order view, so:
<form method="POST" action="{% url 'create_order' %}">
{% csrf_token %}
{{ form }}
<input class="btn btn-primary btn-sm" type="submit" name="Submit">
</form>
Note that you should not validate the form in case of a GET request, since then you only render the form. So the view logic should be:
def create_order(request):
if request.method == 'POST':
print("In Post", request.method)
form = OrderForm(request.POST)
if form.is_valid():
form.save()
return redirect('home')
else:
form = OrderForm()
context = {'form' : form}
return render(request, 'accounts/create_order.html', context)
Try to add form action method in your HTML file
<form action="" method="post">{% csrf_token %}
{{ form}}
<input type="submit" value="Submit Feedback" />
</form>
</div>

Django template variable does not show up

for some reason im unable to display the comments of a category_request and i have now idea why, is smb. maybe able to have an eye on that, praticaly i should work but i dont see the mistake here.
as far as i see I'm using category_request_comment from the view to get a releated comment objects from a category_request... any idea?
Template Snippet:
{% for category_request_comment in category_request_comments %}
<div class="comment">
<p>{{ category_request_comment.content|readmore:15 }}</p>
{% if category_request_comment.content.published_date %}
<div class="date">
<a>Comment by: {{ category_request_comment.author }}</a><br>
<a>Commented at: {{ category_request_comment.published_date }}</a>
</div>
{% endif %}
{% if request.user == category_request_comment.author %}
<a class="commentoption" href="{% url 'comment_edit' pk=category_request_comment.pk %}">Edit</a><a> | </a>
<a class="commentoption" href="{% url 'comment_delete' pk=category_request_comment.pk %}">Delete</a>
{% endif %}
</div>
{% endfor %}
views.py
def category_request_detail(request, pk):
category_request = get_object_or_404(CategoryRequests, pk=pk)
list_category_request = CategoryRequests.objects.get_queryset().filter(id=pk).order_by('-pk')
paginator = Paginator(list_category_request, 20)
page = request.GET.get('page')
category_request_comment = paginator.get_page(page)
return render(request, 'myproject/category_request_detail.html', {'category_request': category_request, 'category_request_comment': category_request_comment})
views.py (only for Reference)
def category_request_comment_new(request, pk):
if request.method == "POST":
form = CategoryRequestsCommentForm(request.POST)
if form.is_valid():
category_request = get_object_or_404(CategoryRequests, pk=pk)
requests_comment = form.save(commit=False)
requests_comment.author = request.user
requests_comment.published_date = timezone.now()
requests_comment.category_request = category_request
requests_comment.save()
return redirect('category_request_detail', pk=requests_comment.category_request.pk)
else:
form = CategoryRequestsCommentForm()
return render(request, 'myproject/comment_new.html', {'form': form})
urls.py
url(r'^categories/requests/$', myproject_views.category_request_list, name='category_request_list'),
Thanks in advance
Your template is looking for an object called category_request_comments, but you have not sent anything with that name to the template.
def category_request_detail(request, pk):
category_request = get_object_or_404(CategoryRequests, pk=pk)
list_comments = CategoryRequests_Comment.objects.get_queryset().filter(category_request_id=pk).order_by('-pk')
paginator = Paginator(list_comments, 10)
page = request.GET.get('page')
comments = paginator.get_page(page)
return render(request, 'myproject/category_request_detail.html', {'category_request': category_request, 'comments': comments})

How to delete exactly element from database?

TOday I am trying to make some kind of to-do list. I know how to add tasks(comments) and now I want to delete them with a button. I don't know how to delete exact task (comment). Code:
#views.py
def add_comment(request):
comments = Comment.objects.all()
if request.method == 'POST':
form = CommentForm(request.POST)
if "delete" in request.POST:
#HERE MAGIC HAPPENS
if form.is_valid():
save_it = form.save()
return render(request, 'task-result.html', {
'form': form, 'comments': comments,
})
else:
form = CommentForm()
return render(request, 'Task-form.html', {
'form': form,
})
#HTML
<form action="">
{% for a in comments %}
<h3>{{ a.body}}</h3>
<input type="submit" name="delete" value="delete" />
{% endfor %}
{% csrf_token %}
</form>
So how to make "magic" happen?
Addition
Now I'm facing new problems. Delete button does nothing or i get eroor: invalid literal for int() with base 10: ''. Code:
#Template:
<html>
<head>
<title>Name</title>
</head>
<body>
<h1>Tasks</h1>
<form action="" method="post">
{{ form.as_p }}
<input type="submit" value="Create task">
{% for a in comments %}
<h3>{{ a.body}}</h3>
<input type="submit" name="delete" value="delete" />
<input type="hidden" name="idcomment" id="{{comments.id}}" />
{% csrf_token %}
</form>
{% endfor %}
</body>
</html>
#Views
def add_comment(request):
comments = Comment.objects.all()
if request.method == 'POST':
form = CommentForm(request.POST)
if "delete" in request.POST:
comments_id = request.POST['idcomment']
comments_object = Comment.objects.get(id=comments_id)
comments_object.delete()
if form.is_valid():
save_it = form.save()
return render(request, 'task-form.html', {
'form': form, 'comments': comments,
})
else:
form = CommentForm()
return render(request, 'Task-form.html', {
'form': form, 'comments': comments,
})
Can you help me solve this one?
My solution will be to add a function delete in your views that will take for argument the comment number.
def del_comment(request, commentsid):
comments = Comment.objects.get(id=commentsid)
comments.delete()
and your url:
url(r'^yoururl/del/(?P<commentsid>\d+)/', del_comment),
in your template link your comment button delete to this url
yoururl/del/{{yourvalue of the comment that will give the id of the current comment}}
example in templates:
{% for a in comments %}
<h3>{{ a.body}}</h3>
Delete ME
{% endfor %}
There is another solution that may work:
if request.method == 'POST':
form = CommentForm(request.POST)
if "delete" in request.POST:
comments_id = request.POST['idcomment'] #the name of the hidden field and get the id of the comment.
comments_object = Comment.objects.get(id=comments_id)
comments_object.delete()
if form.is_valid():
save_it = form.save()
return render(request, 'task-result.html', {
'form': form, 'comments': comments,
})
the hidden field should look like this in your template:
<input type="hidden" name="idcomment" id="{{comments.id}}" /> #or value="{{comments.id}} sorry i do not have my own example on hand.