I am trying to build delete button and currently stuck. I am new to django and need help. Thank You
This is my models.py:-
from django.db import models
from django.contrib.auth import get_user_model
from django.db import models
from django.urls import reverse
# Create your models here.
class simpleList(models.Model):
title = models.CharField(max_length=250)
def __str__(self):
return self.title
This is my views.py:-
from django.shortcuts import render, get_object_or_404
from .models import simpleList
from django.views.generic import ListView, DeleteView
from django.urls import reverse_lazy
from django.contrib.messages.views import SuccessMessageMixin
# Create your views here.
class ListListView(ListView):
model = simpleList
template_name = 'list_list.html'
class DeleteList(SuccessMessageMixin, DeleteView):
model = simpleList
success_url = '/'
success_message = "deleted..."
def delete(self, request, *args, **kwargs):
self.object = self.get_object()
name = self.object.title
# name will be change according to your need
request.session['title'] = title
message = request.session['title'] + ' deleted successfully'
messages.success(self.request, message)
return super(DeleteView, self).delete(request, *args, **kwargs)
This is my urls.py:-
from django.urls import path
from .views import ListListView, DeleteList
from django.conf.urls import url
from . import views
urlpatterns = [
path('', ListListView.as_view(), name='list_list'),
path('<int:pk>/', DeleteList.as_view(), name='delete_view'),
]
This is my home.html:-
{% extends 'base.html' %}
{% block title %}Home{% endblock title %}
{% block content %}
<div>
{% if user.is_authenticated %}
<button type="button" class="btn btn-info"><a style="color: white;" href="{% url 'list_list' %}">Continue to
slist</a></button>
{% endif %}
</div>
{% endblock content %}
and this is my list_list.html which is currently not complete:-
{% extends 'base.html' %}
{% block title %}sList{% endblock title %}
{% block content %}
<h2>simpleList</h2>
{% for simpleList in object_list %}
<div>
<h3>{{ simpleList.title }}</h3>
<div>
<form action="{% url 'delete_view' pk=part.pk %}">{% csrf_token %}
X<input class="btn btn-default btn-danger" type="submit" value="Delete" />
</form>
</div>
</div>
{% endfor %}
{% endblock content %}
The error i am getting from django is this:-
NoReverseMatch at /list/
Reverse for 'delete_view' with keyword arguments '{'pk': ''}' not found. 1 pattern(s) tried: ['list/(?P[0-9]+)/$']
10 <body>
11 <nav class="navbar navbar-expand-lg navbar-dark bg-primary">
12 <a class="navbar-brand" href="{% url 'home' %}">simpleList</a>
13 <div class="collapse navbar-collapse" id="navbarColor01"></div>
14 {% if user.is_authenticated %}
15 <button type="button" class="btn btn-secondary">Hi, {{ user.username }}</button>
16 <button type="button" class="btn btn-info"><a style="color:white;" href="{% url 'logout' %}">Logout</a></button>
You need to make a POST request to delete the object. Furthermore the name of the object is simpleList, not part, so the form should be rewritten to:
<form method="post" action="{% url 'delete_view' pk=simpleList.pk %}">
{% csrf_token %}
<input class="btn btn-default btn-danger" type="submit" value="Delete" />
</form>
While it is not a problem to use <int:pk>/ as the path pattern. It might be better to use <int:pk>/delete, for example, since <int:pk>/ is often used to show the details of the object with that primary key:
urlpatterns = [
path('', ListListView.as_view(), name='list_list'),
path('<int:pk>/delete/', DeleteList.as_view(), name='delete_view'),
]
Related
I have this small blog post app where everything works fine apart from delete view. As soon as I hit delete button I'm moved to my delete post page but when I hit confirm from DeleteView html page I get 405 error
My views.py for delete looks like this:
class DeletePost(DetailView):
model = Articles
template_name = 'delete_article.html'
success_url = reverse_lazy('list_articles')
My html file where the link is mentioned is like this:
<!DOCTYPE html>
{% extends 'base.html' %}
{% block body %}
<div class="container">
{% for i in articles %}
<div class="jumbotron">
<h2>{{i.title}}</h2>
<p>- {{i.author}}</p>
{{i.created_on}}
{{i.updated_on}}
<p>{{i.content}}</p>
<a class="btn btn-warning" href="{% url 'update_article' i.id %}">Update</a>
<a class="btn btn-danger" href="{% url 'delete_article' i.id %}">Delete</a>
</div>
{% endfor %}
</div>
{% endblock %}
urls.py looks this way:
from django.urls import path
from mysite import views
urlpatterns = [
path('articles/', views.PostList.as_view(), name='list_articles'),
path('articles/<pk>/', views.PostDetail.as_view(), name='detail_article'),
path('create/new/', views.CreateNewPost.as_view(), name='create_new_article'),
path('update/<pk>/', views.UpdatePost.as_view(), name='update_article'),
path('delete/<pk>/', views.DeletePost.as_view(), name='delete_article'),
]
and html for DeleteView:
<!DOCTYPE html>
{% extends 'base.html' %}
{% block body %}
<form method="post">
{% csrf_token %}
<p>Are you sure you want to delete "{{ object }}"?</p>
{{ form.as_p }}
<input class='btn btn-danger' type="submit" value="Confirm">
</form>
{% endblock %}
You have mentioned DetailView for deletion which is not correct, mention DeleteView instead which is at from django.views.generic.edit import DeleteView.
Note: Class based views required actual view name as the suffix, so you should write it as PostDeleteView instead of DeletePost. Similarly, write PostListView, PostDetailView etc. Add model name as the prefix and view name as the suffix and must be in PascalCase.
405 means method not allowed, change your form POST method to DELETE method.
<form method="DELETE">
I've just started my first app with Django by following a video on YouTube.
The app is a students dashboard with 8 tools and features to help the student to make note, search for help, save books, etc.
When I follow the steps I get stuck in the creation of a new note but note from the admin side but from the actual notes template that has a crispy form and a create button.
The program is supposed for writing a title and description (the content of the note) and then press the create button. When I try to click, nothing is happening.
#This is the view.py page in the dashboard app :
from django.shortcuts import render
from . forms import *
from django.contrib import messages
# Create your views here.
def home(request):
return render(request, 'dashboard/home.html')
def notes(request):
if request.method == "POST":
form = NotesForm(request.POST)
if form.is_valid():
notes = Notes(user=request.user,title=request.POST['title'],description=request.POST['description'])
notes.save()
messages.success(request,f"Notes Added from {request.user.username} Successfully")
else:
form = NotesForm()
notes = Notes.objects.filter(user=request.user)
context = {'notes':notes,'form':form}
return render(request,'dashboard/notes.html',context)
and this is the notes.html page in the dashboard app > template folder > dashboard folder :
{% extends 'dashboard/base.html' %}
<!-- Load the static files here -->
{% load static %} {% load crispy_forms_tags %}
<!-- loading the crispy files must be here so now i write anything to
create some space and lines here we go baby lets add more -->
{% block content %}
<div class="container">
<div class="row">
{% for note in notes %}
<div class="col-md-3">
<a href="#">
<div class="card">
<div class="card-header">{{note.title}}</div>
<div class="card-body">{{note.description|slice:"0:100"}}</div>
<div class="card-footer mt-auto">
<i class="fa fa-trash fa-2x"></i>
</div>
</div>
</a>
</div>
{% endfor %}
<br /><br />
</div>
</div>
<br /><br />
<div class="container">
<form method="POST">
{% csrf_token %}
<fieldset class="form-group">
<legend class="border-bottom mb-4">Create Notes</legend>
</fieldset>
{% crispy form %}
<div class="form-group">
<button href="" class="btn btn-outline-info" type="submit">Create</button>
</div>
</form>
</div>
{% endblock content %}
so, this the models.py file too
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class Notes(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
title = models.CharField(max_length=200)
description = models.TextField()
def __str__(self):
return self.title
class Meta:
verbose_name = "notes"
verbose_name_plural = "notes"
in case the problem is not here, please take a look on the inside this forms.py
from dataclasses import fields
from django import forms
from . models import *
class NotesForm(forms.ModelForm):
class Meta:
model = Notes
fields = ['title', 'description']
and .. urls.py
from django.urls import path
from . import views
urlpatterns = [
path('',views.home, name='home'),
path('notes',views.notes, name="notes")
]
There are many minor mistakes in the code:
It is {{form|crispy}} to display the form not {% crispy form %}.
You are also not using HttpResponseRedirect[django-doc] for redirecting, after saving form from POST data, you should always return an HttpResponse, its a good practice.
Try below code:
Notes.html
{% block content %}
{% load crispy_forms_tags %}
<div class="container">
<div class="row">
{% for note in notes %}
<div class="col-md-3">
<a href="#">
<div class="card">
<div class="card-header">{{note.title}}</div>
<div class="card-body">{{note.description|slice:"0:100"}}</div>
<div class="card-footer mt-auto">
<i class="fa fa-trash fa-2x"></i>
</div>
</div>
</a>
</div>
{% endfor %}
<br /><br />
</div>
</div>
<br /><br />
<div class="container">
<form method="POST" action="{% url 'notes' %}" novalidate>
{% csrf_token %}
<fieldset class="form-group">
<legend class="border-bottom mb-4">Create Notes</legend>
</fieldset>
{{form|crispy}}
<input type="submit" value="Create">
</form>
</div>
{% endblock content %}
views.py
from django.http import HttpResponseRedirect
from django.shortcuts import render
from django.shortcuts import render
from . forms import *
from django.contrib import messages
from django.urls import reverse
def home(request):
return render(request, 'dashboard/home.html')
def notes(request):
if request.method == "POST":
form = NotesForm(request.POST)
if form.is_valid():
title = form.cleaned_data['title']
descrip = form.cleaned_data['description']
notes = Notes(
user=request.user, title=title, description=descrip)
notes.save()
messages.success(
request, f"Notes Added from {request.user.username} Successfully")
return HttpResponseRedirect(reverse('thanks'))
else:
form = NotesForm()
notes = Notes.objects.filter(user=request.user)
context = {'notes': notes, 'form': form}
return render(request, 'dashboard/notes.html', context)
def thanks(request):
return render(request, 'dashboard/thanks.html')
urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.home, name='home'),
path('notes/', views.notes, name="notes"),
path('thanks/', views.thanks, name='thanks')
]
thanks.html
<body>
<h2>The form successfully submitted</h2>
</body>
Your forms.py can be remain same as it is.
I'm trying to build a very basic messaging app where someone types into a text input, presses send then see's the message on the screen. And I want to do all of this on the same URL. Here is what I have right now:
views.py:
from django.shortcuts import render
from django.views.generic import ListView, CreateView
from message import models
# Create your views here.
class ViewMessages(ListView):
model = models.Messages
context_object_name = 'messages'
class WriteMessages(CreateView):
fields = ('message',)
model = models.Messages
models.py:
from django.db import models
from django import forms
from django.core.urlresolvers import reverse
# Create your models here.
class Messages(models.Model):
message = models.CharField(max_length=300)
def __str__(self):
return self.message
def get_absolute_url(self):
return reverse("view")
project urls.py:
from django.conf.urls import url
from django.contrib import admin
from message import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^view/', views.ViewMessages.as_view(), name="view"),
url(r'^create/', views.WriteMessages.as_view(), name="create"),
]
messages_form.html
{% extends "message/base.html" %}
{% block head_block %}
<title>Create Message</title>
{% endblock %}
{% block body_block %}
{% for message in messages %}
<h3><div class="text-center"><span class="label label-default">{{ message.message }}</span></div></h3>
{% endfor %}
<form method="POST" class="form-horizontal">
{% csrf_token %}
<div class="text-center" style="position: fixed; top: 500px;">
<span style="margin: 10px;">{{ form }}</span>
<br>
<input type="submit" value="Send" class="btn btn-primary btn-group btn-group-lg" >
</div>
</form>
{% endblock %}
messages_list.html:
<!DOCTYPE html>
{% extends "message/base.html" %}
{% block head_block %}
<title>Read Messages</title>
{% endblock %}
{% block body_block %}
<div class="">
{% for message in messages %}
<h3><div class="text-center"><span class="label label-default">{{ message.message }}</span></div></h3>
{% endfor %}
<br>
<p><div class="text-center"><a style="border: 1px solid gray;" class="btn btn-success" href="{% url 'create' %}">Write Message</a></div></p>
</div>
{% endblock %}
The basic idea is that I want to combine the "messages_form.html" and "messages_list.html" into one template file called "message.html".
Can anyone help me?
I had something similar and here was my approach
views.py
from django.views import View
class MessageView(View):
template_name = 'message.html'
queryset = Messages.objects.all()
def get_queryset(self):
return self.queryset
def get(self, request, *args, **kwargs):
form = MessageForm()
context = {
'object_list': self.get_queryset(),
"form": form
}
return render(request, self.template_name, context)
def post(self, request, *args, **kwargs):
form = MessageForm(request.POST)
if form.is_valid():
form.save()
form = MessageForm()
return redirect('/message')
context = {
'object_list': self.get_queryset(),
"form": form
}
return render(request, self.template_name, context)
message.html
{% extends "message/base.html" %}
{% block head_block %}
<title>Message</title>
{% endblock %}
{% block body_block %}
{% for message in object_list %}
<h3><div class="text-center"><span class="label label-default">{{ message.message }}</span></div></h3>
{% endfor %}
<form method="POST" class="form-horizontal">
{% csrf_token %}
<div class="text-center" style="position: fixed; top: 500px;">
<span style="margin: 10px;">{{ form }}</span>
<br>
<input type="submit" value="Send" class="btn btn-primary btn-group btn-group-lg" >
</div>
</form>
{% endblock %}
Display your view in a url
urls.py
from django.urls import path
from .views import MessageView
urlpatterns = [
path('message', MessageView.as_view(), name='messages'),
]
I am trying to figure out why it is that I am getting the following error:
NoReverseMatch at /catalog/projects/delete/1/
Reverse for 'project_detail' with keyword arguments '{'pk': ''}' not found. 1 pattern(s) tried: ['catalog/projects/(?P<pk>[0-9]+)/$']
Here's the url for the catalog app. I think the problem is from here but I don't seem to be able to figure it out
urls.py
urlpatterns = [
path('projects/', views.ProjectListView.as_view(), name='list'),
path('projects/<int:pk>/', views.ProjectDetailView.as_view(), name='project_detail'),
path('projects/new/', views.ProjectCreateView.as_view(), name='project_new'),
path('projects/edit/<int:pk>/', views.ProjectUpdateView.as_view(), name='project_edit'),
path('projects/delete/<int:pk>/', views.ProjectDeleteView.as_view(), name='project_delete')
]
views.py
class HomeView(TemplateView):
template_name = "home.html"
def get_context_data(self, **kwargs):
context = super(HomeView, self).get_context_data(**kwargs)
context = {
'projects': Project.objects.all(),
'num_projects': Project.objects.all().count(),
'num_ongoing_projects': Project.objects.filter(status__exact='OG').count(),
'num_clients': Client.objects.count(),
}
return context
class ProjectListView(ListView):
context_object_name = 'projects'
model = Project
paginate_by = 10
class ProjectDetailView(DetailView):
model = Project
context_object_name = 'project_detail'
template_name = 'catalog/project_detail.html'
class ProjectCreateView(CreateView):
# login_url = '/login/'
form_class = ProjectForm
model = Project
redirect_field_name = 'catalog/project_detail.html'
class ProjectUpdateView(UpdateView):
fields=('project_title', 'location', 'status', 'start_date', 'end_date')
# form_class = ProjectForm
model = Project
redirect_field_name = 'catalog/project_detail.html'
class ProjectDeleteView(DeleteView):
model = Project
success_url = reverse_lazy('catalog:list')
The edit button works fine but the delete button doesn't. It produces that error code
project_detail.html
{% extends "catalog/catalog_base.html" %}
{% block content %}
<h1>Welcome to Project Detail Page</h1>
<h2>Project details:</h2>
<p><strong>Project Number:</strong> {{project_detail.project_number}}</p>
<p><strong>Project Title:</strong> {{project_detail.project_title}}</p>
<p><strong>Customer:</strong> {{project_detail.client}}</p>
<p><strong>Further For:</strong> {{project_detail.further_for}}</p>
<p><strong>Location:</strong> {{project_detail.location}}</p>
<p><strong>Status:</strong> {{project_detail.status}}</p>
<p><strong>Start Date:</strong> {{project_detail.start_date}}</p>
<p><strong>End Date:</strong> {{project_detail.end_date}}</p> <br>
<p><strong>Summary:</strong> {{project_detail.summary}}</p>
<hr>
<div class="container">
<a class="btn btn-primary" href="{% url 'catalog:project_edit' pk=project_detail.pk %}">
<i class="fas fa-pen"></i>
</a>
<a class="btn btn-warning" href="{% url 'catalog:project_delete' pk=project_detail.pk %}">
<span class="fas fa-trash" aria-hidden="true"></span>
</a>
</div>
{% endblock %}
project_form.html
{% extends "catalog/catalog_base.html" %}
{% block content %}
{% load crispy_forms_tags %}
<div class="col-sm-6">
<h1>Create New Project</h1>
<h3><em>Enter project details:</em></h3><br>
<form id="create" method="POST">
{{ form|crispy }}
{% csrf_token %}
<input type="submit" class="btn btn-primary" value="Create Project">
</form>
</div>
{% endblock %}
project_confirm_delete.html
{% extends "catalog/catalog_base.html" %}
{% block content %}
<h1>Delete {{project.project_number}}?</h1>
<form method="POST">
{% csrf_token %}
<input type="submit" class="btn btn-danger" value="Delete">
Cancel
</form>
{% endblock %}
Nothing is happened when I put comment button.I wanna make a page which is shown comment&recomment.I wrote codes in views.py
class DetailView(generic.DetailView):
model = POST
template_name = 'detail.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['comment_form'] = CommentCreateForm()
context['recomment_form'] = ReCommentCreateForm()
return context
class CommentCreateView(generic.View):
def post(self, request, *args, **kwargs):
form = CommentCreateForm(request.POST)
post = POST.objects.get(pk=kwargs['post_pk'])
if form.is_valid():
obj = form.save(commit=False)
obj.target = post
obj.save()
return redirect('detail', pk=post.pk)
class ReCommentCreateView(generic.View):
def post(self, request, *args, **kwargs):
form = ReCommentCreateForm(request.POST)
comment = Comment.objects.get(pk=kwargs['comment_pk'])
if form.is_valid():
obj = form.save(commit=False)
obj.target = comment
obj.save()
return redirect('detail', pk=comment.target.pk)
in urls.py
from django.urls import path
from django.conf import settings
from . import views
urlpatterns = [
path('detail/<int:pk>/', views.DetailView.as_view(), name='detail'),
path('comment/<int:post_pk>/',views.CommentCreateView.as_view(), name='comment'),
path('recomment/<int:comment_pk>/', views.ReCommentCreateView.as_view(), name='recomment'),
]
in detail.html
{% load static %}
<html lang="en">
<head>
<meta charset="UTF-8">
<title>DETAIL</title>
</head>
<body>
<div id="comment-area">
{% for comment in post.comment.all %}
<div class="media m-3">
<div class="media-body">
<h5 class="mt-0">
<span class="badge badge-primary badge-pill">{% by_the_time comment.created_at %}</span>
{{ comment.name }}
<span class="lead text-muted">{{ comment.created_at }}</span>
Recomment
</h5>
{{ comment.text | linebreaksbr }}
{% for recomment in comment.recomment.all %}
<div class="media m-3">
<div class="media-body">
<h5 class="mt-0">
{{ recomment.name }}
<span class="lead text-muted">{{ recomment.created_at }}</span>
</h5>
{{ recomment.text | linebreaksbr }}
</div>
</div>
{% endfor %}
<form action="{% url 'recomment' comment_pk=comment.id %}" method="post">
{{recomment_form}}
{% csrf_token %}
<input class="btn btn-primary" type="submit" value="re-comment">
</form>
</div>
</div>
{% endfor %}
<form action="{% url 'comment' post_pk=post.id %}" method="post">
{{comment_form}}
{% csrf_token %}
<input class="btn btn-primary" type="submit" value="comment">
</form>
</div>
</body>
</html>
in models.py
class Comment(models.Model):
name = models.CharField(max_length=100, blank=True)
text = models.TextField()
target = models.ForeignKey(POST, on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.name
When I put comment button, no error happens but same page which is form's content is blank is shown.I wanna show {% for comment in post.comment.all %} ~ {% endfor %},so I really cannot understand why I cannot do it.I think values are not in model, so I print out print(obj) in CommentCreateView's class, and correctly value is shown in terminal.What is wrong in my code?How should I fix this?
Do you have the objects actually created in the DB? There's some info missing in the post (like the Form itself, etc), anyway:
If you didn't set the related_name argument on the foreign key, the correct access to post's comments is via post.comment_set.all(), see:
https://docs.djangoproject.com/en/2.0/topics/db/queries/#following-relationships-backward
May I point out that you're doing a lot of work, that Django's generic views can do for you (guess it's OK if you're learning, otherwise, it's just more code to maintain).
Things like CreateView, UpdateView, and DeleteView from django.views.generic.edit. For more info see:
https://docs.djangoproject.com/en/2.0/topics/class-based-views/generic-editing/#model-forms