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">
Related
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'),
]
I'm trying to create a form with dependent dropdowns so far I have been able to add the required triggers but I just noticed that the response message wasn't rendering template tags
Even other HTML files that I try to add template tags to just gets ignored
I have no clue what is even causing this kind of error
After viewing a few other posts which said that if I were to use {% load XYZ %}. That I should use this load tag in all my HTML pages but this didn't solve my problem
my views.py:
from django.shortcuts import render,redirect
from django.views.generic.base import TemplateView
from status.forms import StatusForm
from status.models import FlightStatus
from django.views.generic import ListView, CreateView, UpdateView
from postlog.models import Flight
from django.urls import reverse_lazy
# Create your views here.
class StatusPageView(CreateView):
template_name = "status/home.html"
model = FlightStatus
form_class = StatusForm
success_url = reverse_lazy('status')
def load_park_bay(request):
flightid = request.GET.get('flight1')
parks = Flight.objects.filter(fl_no='flightid').order_by('park_bay')
context = {'parks': parks}
return render(request, 'status/park_bay_dropdown_list.html', context)
my urls.py:
from django.urls import path,include
from . import views
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
urlpatterns = [
path('', views.StatusPageView.as_view(), name='status'),
path('ajax/load-park/', views.load_park_bay, name='ajax_load_park'),
]
my home page where my form is present home.html:
{% extends 'base_template1.html' %}
{% load static from staticfiles %}
{% load crispy_forms_tags %}
<!DOCTYPE html>
{% block title %} Status {% endblock %}
{% block content %}
<div class="modal fade" id="Add_Modal" tabindex="-1" role="dialog" aria-labelledby="Add_ModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="AddModalLabel">Flight Details</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<form method="post" id="statusForm" data-parks-url="{% url 'ajax_load_park' %}" novalidate>
{% csrf_token %}
{{ form|crispy }}
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Add Details</button>
</div>
</form>
</div>
</div>
</div>
</div>
<script
src="https://code.jquery.com/jquery-3.4.1.js"
integrity="sha256-WpOohJOqMqqyKL9FccASB9O0KwACQJpFTUBLTYOVvVU="
crossorigin="anonymous"></script>
<script>
$("#id_fl_no").change(function () {
var url = $("#statusForm").attr("data-parks-url");
var flightId = $(this).val();
$.ajax({
url: url,
data: {
'flight1': flightId
},
success: function (data) {
$("#id_park_bay").html(data);
}
});
});
</script>
{%endblock%}
the html response served as response to the ajax request park_bay_dropdown.html:
{% load static from staticfiles %}
{% load crispy_forms_tags %}
<option value="">---------</option>
{% for park in parks %}
<option value="{{ park.fl_no }}">{{ park.park_bay }}</option>
{% endfor %}
Response received:link
even when I tried to send the form instance as a context for displaying the complete form none of the template tags was even shown
Since you are storing the value of 'flight1' coming from ajax in variable flightid. So you need to write flightid without ' ' in Query. And also keep practice to convert the id coming form Ajax into int to avoid any error while querying through ORM. So your view would be like this.
def load_park_bay(request):
flightid = int(request.GET.get('flight1'))
parks = Flight.objects.filter(fl_no=flightid).order_by('park_bay')
context = {'parks': parks}
return render(request, 'status/park_bay_dropdown_list.html', context)
I want the user to login using three fields, username, password and OTP ONLY.
Here is my .html file
{% extends "base.html" %}
{% load static %}
{% load bootstrap4 %}
{% block head %}
<title>HomePage</title>
{% endblock %}
{% block content %}
<div class="container">
<div style='width:500px;margin:0 auto;' class="panel panel-default">
<div class="panel-body">
<h1>Login</h1>
<form method="POST" class="form">
{% csrf_token %}
{% bootstrap_form form %}
{% buttons %}
<button type="submit" class="btn btn-primary">Login</button>
{% endbuttons %}
</form>
</div>
</div>
</div>
{% endblock %}
Here is the browser view of the .html file
I want to remove Otp Device and Otp Challenge as they are unnecessary for my case.
Here is my models.py file
from django.contrib.auth.models import AbstractUser
class ProjectUser(AbstractUser):
# add additional fields in here
def __str__(self):
return self.email
Here is my urls.py file
from django_otp.forms import OTPAuthenticationForm
from django.contrib.auth.views import LoginView
urlpatterns = [
path('user_login/', LoginView.as_view(template_name="accounts_app/user_login.html",
authentication_form=OTPAuthenticationForm), name='user_login'), ]
Here is the reference I used
Solution 1:
The straight forward way is to Subclass OTPAuthenticationForm to replace the form fields used for otp_device and otp_challenge by using the HiddenInput widget. In your app folder, create a new python file called forms.py and add the following
from django_otp.forms import OTPAuthenticationForm
from django import forms
class SimpleOTPAuthenticationForm(OTPAuthenticationForm):
otp_device = forms.CharField(required=False, widget=forms.HiddenInput)
otp_challenge = forms.CharField(required=False, widget=forms.HiddenInput)
In your urls.py file inside your app, add the import and replace the LoginView with the following
from .forms import SimpleOTPAuthenticationForm
path('user_login/', LoginView.as_view(template_name="accounts_app/user_login.html",
authentication_form=SimpleOTPAuthenticationForm), name='user_login'),
Solution 2:
Alternative option but requires more styling to fit the bootstrap form warning and other features. Start with using the following
Only display the fields you want in your template: Since otp_device and otp_challenge are not required, you can just leave them out. Use {% bootstrap_field form.<field> %} for each of the fields you want to display instead of {% bootstrap_form form %}. See here for all the options to customise the rendering of each field. Errors for each field can be displayed with {{ form.errors.<field> }} but you have to style them yourself.
In your case
{% bootstrap_field form.username %}
{% bootstrap_field form.password %}
{% bootstrap_field form.otp_token %}
I have a ListView Template in Django 1.11 that renders to group_list.html. However I want the same view to show in a column in the home page
I also have screenshots below if that helps understanding what I am trying to achieve
I have tried different ways to use {% include 'some.html' %}
1) I tried to make a html page and include it in homepage. but it keeps giving errors
2) I tried to change the group_list.html page into a (insert template) that and tried to insert that, in both the index page and created another template view for groups. but that is giving errors too
Below are my views and templates
Views.py
class GroupCreate(LoginRequiredMixin, CreateView):
model = Group
fields = ('name', 'description')
class GroupList(ListView):
model = Group
class GroupDetail(DetailView):
model = Group
Below is my Index.html and group_list.html
INDEX.HTML
{% extends 'base.html' %}
{% block body %}
<div class="col-md-8" style="background-color:white; border-right:1px solid grey;">
<h4>Groups</h4>
<p>Join a group or make a new Group.</p>
<a style="float:left" class="btn btn-success" href="{% url 'groups:new' %}">Start a Group</a>
<div class="content">
<!--{ % include 'groups/some.html' % } I am trying to insert my -->
</div>
</div>
<div class="col-md-4" style=background-color:white">
<h4>Second Coloumn</h4>
</div>
{% endblock %}
Below is my group_list.html
{% extends 'groups/group_base.html' %}
{% block pre_group %}
<div class="col-md-4">
<div>
<h2>Welcome Back
{{group.user.username}}
</h2>
<h3>Groups</h3>
<p>Welcome to the groups page! Select the Group with the shared interest</p>
</div>
<div>
{% if user.is_authenticated %}
<a class="btn btn-warning" href="{% url 'groups:new' %}"><span class="glyphicon glyphicon-plus-sign"></span> Create a New Group</a>
{% endif %}
</div>
</div>
{% endblock %}
{% block content %}
<div class="col-md-8">
<div class="list-group">
{% for group in object_list %}
<a class="list-group-item" href="{% url 'groups:single' slug=group.slug %}">
<h3 class="list-group-item-heading">{{group.name}}</h3>
<div class="list-group-item-text container-fluid">
{{group.description_html|safe}}
<div class="row">
<div class="col-md-4">
<span class="badge">{{group.members.count}}</span> member{{group.members.count|pluralize}}
</div>
<div class="col-md-4">
<span class="badge">{{group.posts.count}}</span> post{{group.posts.count|pluralize}}
</div>
</div>
</div>
</a>
{% endfor %}
</div>
</div>
{% endblock %}
The HomePage View comes from the root Views they are below
View.py(root directory)
from django.views.generic import TemplateView
class Homepage(TemplateView):
template_name = 'index.html'
class LoggedIn(TemplateView):
template_name = 'test.html'
class LoggedOut(TemplateView):
template_name = 'thanks.html'
I am still learning Django while working on my 1st independent project. I did a some research but could not solve this
I want a list view like this to show on a section of the HomePage
Currently the view works perfectly well on the groups page
In your homepage view you can override get_context_data and add the groups to the context.
class Homepage(TemplateView):
template_name = 'index.html'
def get_context_data(self, **kwargs):
context = super(Homepage, self).get_context_data(**kwargs)
context['object_list'] = Group.objects.all()
return context
In the index.html, you'll have to copy the code from your group_list.html template. To prevent duplication, you could move the code from the content block into a include_groups.html template, then use {% include 'include_groups.html' %} in yourindex.htmlandgroup_list.html` templates.
In this case, since your Homepage view is just a template view, you could use a ListView instead.
class Homepage(ListView):
model = Group
template = 'index.html'
Whichever option you go for, it's useful to understand how to override get_context_data in class based views.
I'm using django 1.2.4.
I have a template for login in registration/login.html (wich action is django.contrib.auth.views.login) and I want to include it on everypage. I created a block on my base.html as I do for every template. The thing is the browser doesn't recognize this login block and I think it is because I only render a template for each view, I am not rendering this login template.
Here is my folder structure:
/templates/
base.html
/myapp/
object_list.html
...
/registration/
login.html
...and here is my login.html:
{% extends "base.html" %}
{% block mylogin %}
<div class="horizontal">
{% if form.errors %}
<p>Your username and password didn't match. Please try again.</p>
{% endif %}
<form action="{% url django.contrib.auth.views.login %}" method="post">
{% csrf_token %}
<div class="login_box">
<div class="login_text">{{ form.username.label_tag }}</div><div class="login_input">{{ form.username }}</div>
<div class="password_text">{{ form.password.label_tag }}</div><div class="password_input">{{ form.password }}</div>
<input id="button_login" type="submit" value="" />
</div>
</form>
</div>
{% endblock %}
...and in my base.html I have:
<div id="some_div">
{% block mylogin %} {% endblock %}
</div>
I have a basestyle.css included in base.html and the other templates inherit correctly too... it seems to be a block problem...
So.. how can I render this template for every view??
Thank you
I think you are looking for the include tag. This way you can include your login html snippet in your base.html :
{% include "/registration/login.html" %}
What I really need was to create a templatetag in templatetags/mytags.py, where I define a function called get_login wich looks like this:
#register.inclusion_tag('registration/login.html', takes_context=True)
def get_login(context):
...
return {'formLogin': mark_safe(AuthenticationForm())}
...and in base.html:
{% load mytags %}{% get_login %}
The problem now is that the template (registration/login.html) doesnt recognize '{{ formLogin.username }}','{{ formLogin.password }}' and so on.
What am I missing?
Update 1:
mark_safe returns an instance of django.utils.safestring.SafeString, not a form.
Use (AuthenticationForm() instead of mark_safe(AuthenticationForm()) and it works!