I have a sample Django 2.2 project that has a search bar in the top right corner of the nav bar (taken from the Bootstrapers):
navbar.html:
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<a class="navbar-brand" href="/">Navbar</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav mr-auto">
<li class="nav-item active">
<a class="nav-link" href="/">Home <span class="sr-only">(current)</span></a>
</li>
{% if user.is_authenticated %}
<li class="nav-item">
<a class="nav-link" href="/search/">Search</a>
</li>
...
{% endif %}
<li class="nav-item">
<a class="nav-link" href="/a/">A</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/b/">B</a>
</li>
</ul>
<form class="form-inline my-2 my-lg-0" action = '/search/'>
<input class="form-control mr-sm-2" type="search" name="q" placeholder="Search" aria-label="Search">
<button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button>
</form>
</div>
</nav>
It returns "You searched for [search argument]" to the url '/search/' and works fine. I would like to bring it from the nav bar under the 'Search' menu in the nav bar. I have the following:
searches/models.py
from django.db import models
from django.conf import settings
# Create your models here.
class SearchQuery(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, blank = True, null=True, on_delete=models.SET_NULL)
query = models.CharField(max_length=220)
timestamp = models.DateTimeField(auto_now_add=True)
searches/views.py:
from django.shortcuts import render
from django.contrib.auth.decorators import login_required
from django.contrib.admin.views.decorators import staff_member_required
from .models import SearchQuery
# Create your views here.
#login_required
# staff_member_required
def search_view(request):
query = request.GET.get('q', None)
user = None
if request.user.is_authenticated:
user = request.user
SearchQuery.objects.create(user=user, query=query)
context = {"query": query}
return render(request, 'searches/view.html',context)
searches/templates/searches/view.html:
{% extends "base.html" %}
{% block content %}
{% if user.is_authenticated %}
<form action = '/search/'>
<input type="search" name="q" aria-label="Search">
<button type="submit">Search</button>
</form>
<div class='row'>
<div class='col-12 col-8 mx-auto'>
<p class='lead'>You searched for {{ query }}</p>
</div>
</div>
{% endif %}
{% endblock %}
When I search from the search bar in the navigational pane, it returns the argument. But when I want to run the search from the search bar and click on the Search tab, I get this:
IntegrityError at /search/
NOT NULL constraint failed: searches_searchquery.query
...
...searches\views.py in search_view
SearchQuery.objects.create(user=user, query=query)
Why am I getting this ?
EDIT:
After making this change in searches/views.py:
query = request.POST.get('q', None)
I get this error in the runtime:
django.db.utils.IntegrityError: NOT NULL constraint failed: searches_searchquery.query
and in the browser:
Related
This is dashboard page with django login
This is analyse page after i login but the user didn#t show up
I click the analyse page when i am anonumoususer, the user didn't change after i login
I don't get the reason why i am logged in but the user did not show up.
Besides when i click logout it doesn't work either.Below is my logout code. I really appreciate it if anyone could help me!!
from django.shortcuts import render,redirect
import hashlib
from django.contrib.auth.forms import UserCreationForm, AuthenticationForm
from django.contrib.auth.models import AnonymousUser
from django.contrib.auth import authenticate,get_user_model,login,logout,get_user
from .forms import UserLoginForm,UserRegisterForm
from django.views.decorators.csrf import csrf_exempt
from django.http import HttpResponse
from django.template import Template,Context
from .decorators import unauthenticated_user,allowed_users, admin_only
from django.contrib.auth.decorators import login_required
#csrf_exempt
#unauthenticated_user
def login_view(request):
next = request.GET.get('next')
form =UserLoginForm(request.POST or None)
if form.is_valid():
username = form.cleaned_data.get('username')
password = form.cleaned_data.get('password')
user = authenticate(username=username,password=password)
login(request,user)
if next:
return redirect(next)
else:
return redirect('/home')
context = {
'form': form,
}
return render(request,'users/login.html',context)
def index(request):
return render(request,'users/home.html')
#csrf_exempt
def register_view(request):
next = request.GET.get('next')
register_form = UserRegisterForm(request.POST or None)
if register_form.is_valid():
user = register_form.save(commit=False)
password = register_form.cleaned_data.get('password1')
user.set_password(password)
user.save()
new_user = authenticate(username=user.username,password=password)
login(request, new_user)
if next:
return redirect(next)
return redirect('/userlist')
context = {
'form': register_form,
}
return render(request,'register.html',context)
def logout_view(request):
user = get_user(request)
logout(request)
request.session.flush()
print('you are log out from cms!')
request.user = AnonymousUser
return render(request,'logout.html')
def userlist(request):
User = get_user_model()
result = User.objects.all()
#template = Template('userlist.html')
#html = template.render(Context({'content': result}))
return render(request,'userlist.html',{'content':result})
def adduser(request):
return render(request,'todo.html')
#login_required(login_url='accounts/login/')
def notpermitted(request):
return render(request,'NotPermitted.html')
This is the side bar in template. The sidebar will change based on user roll.
{% load static %}
<ul class="navbar-nav bg-gradient-primary sidebar sidebar-dark accordion" id="accordionSidebar">
<!-- Sidebar - Brand -->
<a class="sidebar-brand d-flex align-items-center justify-content-center" href="/home">
<div class="sidebar-brand-icon">
<img class="img-responsive center-block" src="{% static 'img/cms.png'%}" alt="" width="72" height="57">
</div>
</a>
<!-- Divider -->
<hr class="sidebar-divider my-0">
<!-- Nav Item - Dashboard -->
<li class="nav-item active">
<a class="nav-link" href="/dashboard">
<i class="fas fa-fw fa-tachometer-alt"></i>
<span>Dashboard</span></a>
</li>
<!-- Divider -->
<hr class="sidebar-divider">
<!-- Heading -->
<div class="sidebar-heading">
Function
</div>
<!-- Nav Item - Pages Collapse Menu -->
{% if request.user.is_staff %}
<li class="nav-item">
<a class="nav-link collapsed" href="#" data-toggle="collapse" data-target="#collapseFive"
aria-expanded="true" aria-controls="collapseFive">
<i class="fas fa-fw fa-chart-area"></i>
<span>Dataset</span>
</a>
<div id="collapseFive" class="collapse" aria-labelledby="headingFive" data-parent="#accordionSidebar">
<div class="bg-white py-2 collapse-inner rounded">
<h6 class="collapse-header">Dataset:</h6>
<a class="collapse-item" href="/adddata">Add Dataset</a>
<a class="collapse-item" href="/datasetlist">Datasets</a>
</div>
</div>
</li>
<li class="nav-item">
<a class="nav-link collapsed" href="#" data-toggle="collapse" data-target="#collapseThree"
aria-expanded="true" aria-controls="collapseThree">
<i class="fas fa-fw fa-cog"></i>
<span>historical Data</span>
</a>
<div id="collapseThree" class="collapse" aria-labelledby="headingThree" data-parent="#accordionSidebar">
<div class="bg-white py-2 collapse-inner rounded">
<h6 class="collapse-header">Dataset:</h6>
<a class="collapse-item" href="/upload">upload</a>
<a class="collapse-item" href="/home">Rest</a>
</div>
</div>
</li>
{% endif %}
<li class="nav-item">
<a class="nav-link collapsed" href="/processed" data-toggle="collapse" data-target="#collapseTwo"
aria-expanded="true" aria-controls="collapseTwo">
<i class="fas fa-fw fa-cog"></i>
<span>ProcessedData</span>
</a>
<div id="collapseTwo" class="collapse" aria-labelledby="headingTwo" data-parent="#accordionSidebar">
<div class="bg-white py-2 collapse-inner rounded">
<h6 class="collapse-header">Dataset:</h6>
<a class="collapse-item" href="/processed">list</a>
<a class="collapse-item" href="/processed/opc">opc</a>
<a class="collapse-item" href="/processed/mqtt">mqtt</a>
</div>
</div>
</li>
<!-- Nav Item - Utilities Collapse Menu -->
<li class="nav-item">
<a class="nav-link collapsed" href="/analyse" data-toggle="collapse" data-target="#collapseUtilities"
aria-expanded="true" aria-controls="collapseUtilities">
<i class="fas fa-fw fa-wrench"></i>
<span>Analyse</span>
</a>
<div id="collapseUtilities" class="collapse" aria-labelledby="headingUtilities"
data-parent="#accordionSidebar">
<div class="bg-white py-2 collapse-inner rounded">
<h6 class="collapse-header">Methode:</h6>
<a class="collapse-item" href="/analyse/fft">Fast Fourier Methode</a>
<a class="collapse-item" href="/analyse/limit_monitoring">Limit Monitoring</a>
</div>
</div>
</li>
<!-- Divider -->
<hr class="sidebar-divider">
{% if request.user.is_superuser %}
<!-- Heading -->
<div class="sidebar-heading">
Usermanagement
</div>
<li class="nav-item">
<a class="nav-link collapsed" href="#" data-toggle="collapse" data-target="#collapseFour"
aria-expanded="true" aria-controls="collapseFour">
<i class="fas fa-fw fa-cog"></i>
<span>Users</span>
</a>
<div id="collapseFour" class="collapse" aria-labelledby="headingFour" data-parent="#accordionSidebar">
<div class="bg-white py-2 collapse-inner rounded">
<h6 class="collapse-header">User:</h6>
<a class="collapse-item" href="/userlist">List</a>
<a class="collapse-item" href="/adduser">add User</a>
</div>
</div>
</li>
{% endif %}
</ul>
This is topbar! the current user will be listed here.
``
<!-- Sidebar Toggle (Topbar) -->
<button id="sidebarToggleTop" class="btn btn-link d-md-none rounded-circle mr-3">
<i class="fa fa-bars"></i>
</button>
<!-- Topbar Search -->
<form
class="d-none d-sm-inline-block form-inline mr-auto ml-md-3 my-2 my-md-0 mw-100 navbar-search">
<div class="input-group">
<input type="text" class="form-control bg-light border-0 small" placeholder="Search for..."
aria-label="Search" aria-describedby="basic-addon2">
<div class="input-group-append">
<button class="btn btn-primary" type="button">
<i class="fas fa-search fa-sm"></i>
</button>
</div>
</div>
</form>
<!-- Topbar Navbar -->
<ul class="navbar-nav ml-auto">
<!-- Nav Item - Search Dropdown (Visible Only XS) -->
<li class="nav-item dropdown no-arrow d-sm-none">
<a class="nav-link dropdown-toggle" href="#" id="searchDropdown" role="button"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="fas fa-search fa-fw"></i>
</a>
<!-- Dropdown - Messages -->
<div class="dropdown-menu dropdown-menu-right p-3 shadow animated--grow-in"
aria-labelledby="searchDropdown">
<form class="form-inline mr-auto w-100 navbar-search">
<div class="input-group">
<input type="text" class="form-control bg-light border-0 small"
placeholder="Search for..." aria-label="Search"
aria-describedby="basic-addon2">
<div class="input-group-append">
<button class="btn btn-primary" type="button">
<i class="fas fa-search fa-sm"></i>
</button>
</div>
</div>
</form>
</div>
</li>
<!-- Nav Item - Alerts -->
<li class="nav-item dropdown no-arrow mx-1">
<li class="nav-item">Login</li>
<li class="nav-item">Logout</li>
</li>
<div class="topbar-divider d-none d-sm-block"></div>
<!-- Nav Item - User Information -->
<li class="nav-item dropdown no-arrow">
<a class="nav-link dropdown-toggle" href="#" id="userDropdown" role="button"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="mr-2 d-none d-lg-inline text-gray-600 small">Hello, {{ request.user }}</span>
</a>
</li>
</ul>
````
I use request.user to decide the user roll. it seems to be that the page is stored in the browser when i first load this page. So when i update the page after i login in, the page i loaded before didn't change the user in sidebar and topbar. i disabled cookies and cache in my browser but it still doesn't work, hope anyone hat a answer!
I'm currently working on To-Do App using Django.
I have two models Todo and Task. I want to create a Todo and under the todo items I want to create a task items.
As I was able to add todo items and task items.
But the problem is If I want to add task item for Maths by default all the task Items are getting added to the first todo items. I think It's becaude In Task modal(pop up) form I have linked function url to retrieve the todo objects id when the add button clicked and also added bootstrap modal(pop up) form to the a-tag in html. It's not retrieving the corresponding todo item id instead It takes the 1st todo item id.(refer below images)
models.py
class Todo(models.Model):
date_created = models.DateTimeField(auto_now_add=True)
completed = models.BooleanField(default=False)
title = models.CharField(max_length=200)
user_id = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
def __str__(self):
return self.title
class Task(models.Model):
heading = models.CharField(max_length=100)
todo = models.ForeignKey(Todo, on_delete=models.CASCADE, related_name='tasks')
date_created = models.DateTimeField(auto_now_add=True)
completed = models.BooleanField(default=False)
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
def __str__(self):
return self.heading
views.py
from django.shortcuts import render, redirect, get_object_or_404
from django.http import HttpResponse, Http404, HttpResponseNotFound, JsonResponse, HttpResponseRedirect
from .models import Todo, Task
from .forms import *
from django.utils import timezone
from django.contrib.auth.forms import UserCreationForm
from django.views.decorators.csrf import csrf_protect
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.decorators import login_required
from django.views.generic import View
from django.contrib.auth.models import User
from django.core.paginator import Paginator
def register(request):
form = userRegisterForm()
if request.method == 'POST':
form = userRegisterForm(request.POST)
if form.is_valid():
form.save()
username = form.cleaned_data.get('username')
password = form.cleaned_data.get('password2')
return redirect('login')
else:
form = userRegisterForm()
context = {'form': form}
return render(request, 'todo/register.html', context)
def logoutUser(request):
logout(request)
return redirect('login')
#login_required(login_url='login')
def home(request):
todo_form = TodoForm()
task_form = TaskForm()
current = timezone.now()
todo_items_upcoming = Todo.objects.filter(user_id=request.user, completed=False).order_by('-date_created')
todo_items_completed = Todo.objects.filter(user_id=request.user, completed=True).order_by('-date_created')
pagi1 = Paginator(todo_items_upcoming, 4)
pagi2 = Paginator(todo_items_completed, 4)
page_num = request.GET.get('upcoming', 1)
page_num2 = request.GET.get('completed', 1)
page_obj = pagi1.get_page(page_num)
page_obj2 = pagi2.get_page(page_num2)
if request.method == "POST":
todo_form1 = TodoForm(request.POST)
if todo_form1.is_valid():
data = todo_form1.cleaned_data.get('title')
obj = Todo.objects.create(
date_created=current, title=data, user_id=request.user)
context = {'todo_form': todo_form, 'page_obj': page_obj, 'page_obj2': page_obj2,
'pagi1': pagi1, 'pagi2': pagi2, 'page_num2': int(page_num2), 'page_num': int(page_num), 'task_form': task_form}
return render(request, 'todo/main.html', context)
#login_required(login_url='login')
def update_todo(request, pk):
try:
obj = Todo.objects.get(id=pk, user_id=request.user)
print(obj)
except Exception as err:
raise Http404(err)
if request.method == 'POST':
upform = TodoForm(request.POST, instance=obj)
if upform.is_valid():
upform.save()
return redirect('/')
#login_required(login_url='login')
def add_task(request, pk):
try:
obj = Todo.objects.get(id=pk, user_id=request.user)
print(obj)
except Exception as err:
raise Http404(err)
if request.method == 'POST':
Task.objects.create(heading=request.POST.get('heading'), date_created=timezone.now(),
todo=obj, user=request.user)
return HttpResponseRedirect(request.META.get('HTTP_REFERER'))
#login_required(login_url='login')
def delete_todo(request, pk):
try:
obj = Todo.objects.get(id=pk, user_id=request.user)
except Exception as err:
try:
obj = Task.objects.get(id=pk, user=request.user)
except Exception as err:
raise Http404(err)
obj.delete()
return HttpResponseRedirect(request.META.get('HTTP_REFERER'))
#login_required(login_url='login')
def completed_todo(request, pk):
try:
obj = Todo.objects.get(id=pk, user_id=request.user)
except Exception as err:
try:
obj = Task.objects.get(id=pk, user=request.user)
except Exception as err:
raise Http404(err)
obj.completed = True
obj.save()
# return redirect('/')
return HttpResponseRedirect(request.META.get('HTTP_REFERER'))
main.html
{% extends 'todo/index.html' %}
{% load crispy_forms_tags %}
{% block content %}
<div class="center-column">
<h5 class="card-title">Create your List</h5>
<form action="" method="POST" id="addTodo">
{% csrf_token %}
<div class="input-group-append">
{{ todo_form.title }}
<button type="submit" class="form-control btn btn-primary mb-3 mr-sm-2" id="addItem">
Add Items
</button>
</div>
</form>
</div>
<div class="row">
<div class="col-sm-6">
<div class="card">
<div class="card-body">
<h4 class="card-title">Upcoming Items</h4>
<hr/>
{% for i in page_obj %}
<ul class="list-group" id="upcomingItems">
<li class="list-group-item list-group-item-primary mb-1" id="upcomingItem">
{{ i.title }}
<div class="float-right">
<button type="submit" class="btn btn-sm btn-dark ml-1 mt-1 mr-1 mb-1" id="completed_btn">
Completed
</button>
<button type="submit" class="btn btn-sm btn-danger ml-1 mt-1 mr-1 mb-1">
❌
</button>
</div>
<div class="float-right">
<!-- Button trigger modal for Update Todo Modal-->
<button type="submit" class="btn btn-sm btn-success ml-1 mt-1 mr-1 mb-1" id="update_btn">
<a href="{% url 'update_todo' i.id %}" data-toggle="modal" data-target="#updateTodoModal_{{i.id}}">Update
</a>
</button>
</div>
<div class="float-right">
<!-- Button trigger modal for Adding TaskModal-->
<button type="submit" class="btn btn-sm btn-primary ml-1 mt-1 mr-1 mb-1" id="addBtn">
<a href="{% url 'addTask' i.id %}" data-toggle="modal" data-target="#taskModal_{{i.id}}" name="todoObj">
Add
</a>
</button>
</div>
<!-- Task Modal for adding tasks under todo items -->
<div class="modal fade" id="taskModal_{{ i.id }}" data-backdrop="static" tabindex="-1" role="dialog"
aria-labelledby="staticBackdropLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="staticBackdropLabel">Add New Task</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<form action="{% url 'addTask' i.id %}" method="POST" id="addTask">
{% csrf_token %}
<div class="card card-body">
{{ task_form.heading }}
</div>
<div class="modal-footer">
<button class="btn btn-success" type="submit">Submit</button>
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
</div>
</form>
</div>
</div>
</div>
</div>
<!-- Update Todo Modal for updating Todo Items -->
<div class="modal fade" id="updateTodoModal_{{i.id}}" data-backdrop="static" tabindex="-1" role="dialog" aria-labelledby="staticBackdropLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="staticBackdropLabel">Update ToDo</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<form action="{% url 'update_todo' i.id %}" method="POST">
{% csrf_token %}
<div class="card card-body">
{{ todo_form|crispy }}
</div>
</form>
</div>
<div class="modal-footer">
<button class="btn btn-success" type="submit">Submit</button>
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
{% for j in i.tasks.all %}
{% if j.completed == False %}
<div class="card mt-4">
<ul class="list-group">
<li class="list-group-item list-group-item-danger" id="upcomingItem">
{{ j.heading }}
<div class="float-right">
<button type="submit" class="btn btn-sm btn-dark ml-1 mt-1 mr-1 mb-1" id="completed_btn">
Completed
</button>
<button type="submit" class="btn btn-sm btn-danger ml-1 mt-1 mr-1 mb-1">
❌
</button>
</div>
</li>
</ul>
</div>
{% endif %}
{% endfor %}
</li>
</ul>
{% endfor %}
<hr/>
<ul class="pagination justify-content-center">
{% if page_obj.has_previous %}
<li class="page-item {% if page_obj.page_number == page_num %} active {% endif %}">
<a class="page-link" href="?upcoming={{ page_obj.previous_page_number }}&completed={{ page_num2 }}">«</a>
</li>
{% endif %}
{% for i in pagi1.page_range %}
<li class="page-item {% if i == page_num %} active {% endif %}">
<a class="page-link" href="?upcoming={{ i }}&completed={{ page_num2 }}">{{ i }}</a>
</li>
{% endfor %}
{% if page_obj.has_next %}
<li class="page-item {% if page_obj.page_number == page_num %} active {% endif %}">
<a class="page-link" href="?upcoming={{ page_obj.next_page_number }}&completed={{ page_num2 }}">»</a>
</li>
{% endif %}
</ul>
</div>
</div>
</div>
<div class="col-sm-6">
<div class="card">
<div class="card-body">
<h4 class="card-title">Completed Items</h4>
<hr/>
<ul class="list-group" id="upcomingItems">
{% for i in page_obj2 %}
<li class="list-group-item list-group-item-primary mb-1" id="upcomingItem">
{{ i.title }}
<div class="float-right">
<button type="submit" class="btn btn-sm btn-success ml-1 mt-1 mr-1 mb-1" id="update_btn">
Update
</button>
<button type="submit" class="btn btn-sm btn-danger ml-1 mt-1 mr-1 mb-1">
❌
</button>
</div>
{% for j in i.tasks.all %}
<div class="card mt-4">
<ul class="list-group">
<li class="list-group-item list-group-item-danger" id="upcomingItem">
{{ j.heading }}
<div class="float-right">
<button type="submit" class="btn btn-sm btn-dark ml-1 mt-1 mr-1 mb-1" id="completed_btn">
Completed
</button>
<button type="submit" class="btn btn-sm btn-danger ml-1 mt-1 mr-1 mb-1">
❌
</button>
</div>
</li>
</ul>
</div>
{% endfor %}
</li>
{% endfor %}
</ul>
<hr/>
<ul class="pagination justify-content-center">
{% if page_obj2.has_previous %}
<li class="page-item {% if page_obj2.page_number == page_num %} active {% endif %}">
<a class="page-link" href="?completed={{ page_obj2.previous_page_number }}&upcoming={{ page_num }}">«</a>
</li>
{% endif %}
{% for i in pagi2.page_range %}
<li class="page-item {% if i == page_num2 %} active {% endif %}">
<a class="page-link" href="?completed={{ i }}&upcoming={{ page_num }}">{{ i }}</a>
</li>
{% endfor %}
{% if page_obj2.has_next %}
<li class="page-item {% if page_obj2.page_number == page_num %} active {% endif %}">
<a class="page-link" href="?completed={{ page_obj2.next_page_number }}&upcoming={{ page_num }}">»</a>
</li>
{% endif %}
</ul>
</div>
</div>
</div>
</div>
{% endblock %}
forms.py
class TodoForm(forms.ModelForm):
class Meta:
model = Todo
fields = ['title', 'completed']
class TaskForm(forms.ModelForm):
class Meta:
model = Task
fields = ['heading', 'todo', 'completed']
class userRegisterForm(UserCreationForm):
email = forms.EmailField()
class Meta:
model = User
fields = ['username','email','password1','password2']
urls.py
urlpatterns = [
path('', views.home, name='home'),
path('update_todo/<int:pk>/', views.update_todo, name='update_todo'),
path('completed/<int:pk>/', views.completed_todo, name="completed_todo"),
path('delete_todo/<int:pk>/', views.delete_todo, name='delete_todo'),
path('add_task/<int:pk>/', views.add_task, name='addTask'),
path('register/', views.register, name='register'),
path('login/', auth_views.LoginView.as_view(template_name='todo/login.html'), name='login'),
path('logout/', auth_views.LogoutView.as_view(template_name='todo/logout.html'), name='logout'),
]
Image-1
Task form Popup modal using bootstrap for adding task items under a todo.
Image-2
Whenever I add task items for other todo items, those task items are getting stored to 1st todo items not to their corresponding todo items. I have added two task items on Maths Todo item but those Maths-1 and Maths-2 was created under 1st todo item.
You are creating n taskModal modals with the same id, which is wrong and is causing the error of opening only the first modal with id taskModal for all add operations. You need to have unique id for every element in your html. I would like to do a lot of changes to your code but for now let's get your code working.
Change the data-target for add button from data-target="#taskModal" to data-target="#taskModal_{{ i.id }}" , similarly change the id of taskModal from taskModal to taskModal_{{ i.id }}
You need to do the similar changes for update todo.
<button
id={{i.id}}
type="button"
class="btn btn-primary"
data-toggle="modal"
data-target="#taskModal">
Add
</button>
<script>
// This event is fired when the modal has been made visible to the user
$('#taskModal').on('shown.bs.modal', function (e) {
let id = e.relatedTarget.id // get the id from the button
$('#addTask').attr('action', `/add_todo/${id}/`); // update the action with the id
});
</script>
Also you must improve the variables and functions names, we code for other devs!
I'm currently working on To-Do App using Django.
I got stucked in handling two different forms in single html file and each form has separate function in views. I have two models Todo and Task.
The task items should be placed under to-do item. In short To-Do is a Category and the task's are its sub-category. The data is not getting saved and displayed in the Web.
I have two forms in main.html one is for to-do item and other one is for task item. Each have two different function in views.py which are home and add_todo function respectively.
In form-2 which is for task item built using bootstrap Modal. The form action provided to add_todo function in views.py.
models.py
class Todo(models.Model):
date_created = models.DateTimeField(auto_now_add=True)
completed = models.BooleanField(default=False)
title = models.CharField(max_length=200)
user_id = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
def __str__(self):
return self.title
class Task(models.Model):
heading = models.CharField(max_length=100)
todo = models.ForeignKey(Todo, on_delete=models.CASCADE, related_name='tasks')
date_created = models.DateTimeField(auto_now_add=True)
completed = models.BooleanField(default=False)
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
def __str__(self):
return self.heading
views.py
from django.shortcuts import render, redirect, get_object_or_404
from django.http import HttpResponse, Http404, HttpResponseNotFound, JsonResponse, HttpResponseRedirect
from .models import Todo, Task
from .forms import *
from django.utils import timezone
from django.contrib.auth.forms import UserCreationForm
from django.views.decorators.csrf import csrf_protect
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.decorators import login_required
from django.views.generic import View
from django.contrib.auth.models import User
from django.core.paginator import Paginator
def register(request):
form = userRegisterForm()
if request.method == 'POST':
form = userRegisterForm(request.POST)
if form.is_valid():
form.save()
username = form.cleaned_data.get('username')
password = form.cleaned_data.get('password2')
return redirect('login')
else:
form = userRegisterForm()
context = {'form': form}
return render(request, 'todo/register.html', context)
def logoutUser(request):
logout(request)
return redirect('login')
#login_required(login_url='login')
def home(request):
todo_form = TodoForm()
task_form = TaskForm()
current = timezone.now()
todo_items_upcoming = Todo.objects.filter(user_id=request.user, completed=False).order_by('-date_created')
todo_items_completed = Todo.objects.filter(user_id=request.user, completed=True).order_by('-date_created')
pagi1 = Paginator(todo_items_upcoming, 4)
pagi2 = Paginator(todo_items_completed, 4)
page_num = request.GET.get('upcoming', 1)
page_num2 = request.GET.get('completed', 1)
page_obj = pagi1.get_page(page_num)
page_obj2 = pagi2.get_page(page_num2)
if request.method == "POST":
todo_form1 = TodoForm(request.POST)
if todo_form1.is_valid():
data = todo_form1.cleaned_data.get('title')
obj = Todo.objects.create(date_created=current, title=data, user_id=request.user)
return redirect('/')
context = {'todo_form': todo_form, 'page_obj': page_obj, 'page_obj2': page_obj2,
'pagi1': pagi1, 'pagi2': pagi2, 'page_num2': int(page_num2), 'page_num': int(page_num), 'task_form':task_form}
return render(request, 'todo/main.html', context)
#login_required(login_url='login')
def update_todo(request, pk):
try:
obj = Todo.objects.get(id=pk, user_id=request.user)
upform = TodoForm(instance=obj)
if request.method == 'POST':
upform = TodoForm(request.POST, instance=obj)
if upform.is_valid():
upform.save()
return redirect('/')
except Exception as err:
try:
obj = Task.objects.get(id=pk, user=request.user)
upform = TaskForm(instance=obj)
if request.method == 'POST':
upform = TaskForm(request.POST, instance=obj)
if upform.is_valid():
upform.save()
return redirect('/')
except Exception as err:
raise Http404(err)
context = {'upform': upform}
return render(request, 'todo/update_task.html', context)
#login_required(login_url='login')
def add_todo(request, pk):
try:
obj = Todo.objects.get(id=pk, user_id=request.user)
except Exception as e:
raise Http404(e)
if request.method == 'POST':
t_form = TaskForm(request.POST)
if t_form.is_valid():
data = t_form.cleaned_data.get('heading')
Task.objects.create(user=request.user, heading=data, todo=obj, date_created=timezone.now())
return redirect('/')
else:
t_form = TaskForm()
context = {'t_form':t_form}
return render(request, 'todo/main.html', context)
#login_required(login_url='login')
def delete_todo(request, pk):
try:
obj = Todo.objects.get(id=pk, user_id=request.user)
except Exception as err:
try:
obj = Task.objects.get(id=pk, user=request.user)
except Exception as err:
raise Http404(err)
obj.delete()
return HttpResponseRedirect(request.META.get('HTTP_REFERER'))
#login_required(login_url='login')
def completed_todo(request, pk):
try:
obj = Todo.objects.get(id=pk, user_id=request.user)
except Exception as err:
try:
obj = Task.objects.get(id=pk, user=request.user)
except Exception as err:
raise Http404(err)
obj.completed = True
obj.save()
# return redirect('/')
return HttpResponseRedirect(request.META.get('HTTP_REFERER'))
main.html
{% extends 'todo/index.html' %}
{% load crispy_forms_tags %}
{% block content %}
<div class="center-column">
<h5 class="card-title">Create your List</h5>
#form-1
<form action="" method="POST">
{% csrf_token %}
<div class="input-group-append">
{{ todo_form.title }}
<button type="submit" class="form-control btn btn-primary mb-3 mr-sm-2" id="addItem">
Add Items
</button>
</div>
</form>
</div>
<div class="row">
<div class="col-sm-6">
<div class="card">
<div class="card-body">
<h4 class="card-title">Upcoming Items</h4>
<hr/>
<ul class="list-group" id="upcomingItems">
{% for i in page_obj %}
<li class="list-group-item list-group-item-primary mb-1" id="upcomingItem">
{{ i.title }}
<div class="float-right">
<button type="submit" class="btn btn-sm btn-danger ml-1 mt-1 mr-1 mb-1">
❌
</button>
</div>
<div class="float-right">
<button type="submit" class="btn btn-sm btn-success ml-1 mt-1 mr-1 mb-1" id="update_btn">
Update
</button>
</div>
<div class="float-right">
<button type="submit" class="btn btn-sm btn-dark ml-1 mt-1 mr-1 mb-1" id="completed_btn">
Completed
</button>
</div>
<div class="float-right">
<!-- Button trigger modal -->
<button type="button" class="btn btn-sm btn-primary ml-1 mt-1 mr-1 mb-1" data-toggle="modal" data-target="#staticBackdrop">
Add
</button>
<!-- Modal -->
<div class="modal fade" id="staticBackdrop" data-backdrop="static" tabindex="-1" role="dialog" aria-labelledby="staticBackdropLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="staticBackdropLabel">Add New Task</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
#form-2
<form action="{% url 'home' %}" method="POST">
{% csrf_token %}
<div class="card">
{{ task_form.heading }}
</div>
<div class="modal-footer">
<button class="btn btn-success" type="submit">Submit</button>
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
{% for j in i.tasks.all %}
{% if i.tasks.all %}
<div class="card mt-4">
<ul class="list-group">
<li class="list-group-item list-group-item-danger" id="upcomingItem">
{{ j.heading }}
<div class="float-right">
<button type="submit" class="btn btn-sm btn-danger ml-1 mt-1 mr-1 mb-1">
❌
</button>
</div>
<div class="float-right">
<button type="submit" class="btn btn-sm btn-dark ml-1 mt-1 mr-1 mb-1" id="completed_btn">
Completed
</button>
</div>
</li>
</ul>
</div>
{% endif %}
{% endfor %}
</li>
{% endfor %}
</ul>
<hr/>
<ul class="pagination justify-content-center">
{% if page_obj.has_previous %}
<li class="page-item {% if page_obj.page_number == page_num %} active {% endif %}">
<a class="page-link" href="?upcoming={{ page_obj.previous_page_number }}&completed={{ page_num2 }}">«</a>
</li>
{% endif %}
{% for i in pagi1.page_range %}
<li class="page-item {% if i == page_num %} active {% endif %}">
<a class="page-link" href="?upcoming={{ i }}&completed={{ page_num2 }}">{{ i }}</a>
</li>
{% endfor %}
{% if page_obj.has_next %}
<li class="page-item {% if page_obj.page_number == page_num %} active {% endif %}">
<a class="page-link" href="?upcoming={{ page_obj.next_page_number }}&completed={{ page_num2 }}">»</a>
</li>
{% endif %}
</ul>
</div>
</div>
</div>
<div class="col-sm-6">
<div class="card">
<div class="card-body">
<h4 class="card-title">Completed Items</h4>
<hr/>
<ul class="list-group">
{% for i in page_obj2 %}
{% if not i.tasks.all %}
<li class="list-group-item list-group-item-primary mb-1" id="upcomingItem">
{{ i.title }}
<div class="float-right">
<button type="submit" class="btn btn-sm btn-danger mt-1 mb-1">
❌
</button>
</div>
</li>
{% else %}
{% for j in i.tasks.all %}
<li class="list-group-item list-group-item-primary mb-1" id="upcomingItem">
{{ i.title }}
<div class="float-right">
<button type="submit" class="btn btn-sm btn-danger mt-1 mb-1">
❌
</button>
</div>
<div class="card mt-4">
<ul class="list-group">
<li class="list-group-item list-group-item-danger">
{{ j.heading }}
<div class="float-right">
<button type="submit" class="btn btn-sm btn-danger">
❌
</button>
</div>
</li>
</ul>
</div>
</li>
{% endfor %}
{% endif %}
{% endfor %}
</ul>
<hr/>
<ul class="pagination justify-content-center">
{% if page_obj2.has_previous %}
<li class="page-item {% if page_obj2.page_number == page_num %} active {% endif %}">
<a class="page-link" href="?completed={{ page_obj2.previous_page_number }}&upcoming={{ page_num }}">«</a>
</li>
{% endif %}
{% for i in pagi2.page_range %}
<li class="page-item {% if i == page_num2 %} active {% endif %}">
<a class="page-link" href="?completed={{ i }}&upcoming={{ page_num }}">{{ i }}</a>
</li>
{% endfor %}
{% if page_obj2.has_next %}
<li class="page-item {% if page_obj2.page_number == page_num %} active {% endif %}">
<a class="page-link" href="?completed={{ page_obj2.next_page_number }}&upcoming={{ page_num }}">»</a>
</li>
{% endif %}
</ul>
</div>
</div>
</div>
</div>
{% endblock %}
forms.py
class TodoForm(forms.ModelForm):
class Meta:
model = Todo
fields = ['title', 'completed']
class TaskForm(forms.ModelForm):
class Meta:
model = Task
fields = ['heading', 'todo', 'completed']
class userRegisterForm(UserCreationForm):
email = forms.EmailField()
class Meta:
model = User
fields = ['username','email','password1','password2']
urls.py
urlpatterns = [
path('', views.home, name='home'),
path('update_todo/<int:pk>/', views.update_todo, name='update_todo'),
path('completed/<int:pk>/', views.completed_todo, name="completed_todo"),
path('delete_todo/<int:pk>/', views.delete_todo, name='delete_todo'),
path('add_todo/<int:pk>/', views.add_todo, name='addTodo'),
path('register/', views.register, name='register'),
path('login/', auth_views.LoginView.as_view(template_name='todo/login.html'), name='login'),
path('logout/', auth_views.LogoutView.as_view(template_name='todo/logout.html'), name='logout'),
]
When I click Add button and type something and click enter, the data was not saved in the DB so that I'm unable to see the tasks data.
Image-1
Task form Popup modal using bootstrap for adding task items under a todo.
Image-2
Whenever I add task items for other todo items, those task items are getting dtored to 1t todo items not to their corresponding todo items. I have added two task items on Maths Todo items but those Maths-1 and Maths-2 was created under 1st todo items.
Simple way is
action = "{%url 'link_name' %}"
You can specify the function path name in the form Action.
The changes I have made are in add_todo function and bootstrap modal form.
views.py ad_todo function
def add_todo(request, pk):
obj = Todo.objects.get(id=pk, user_id=request.user)
if request.method == 'POST':
if request.POST.get('heading'):
data = Task()
data.heading = request.POST.get('heading')
data.todo = obj
data.user = request.user
data.save()
return redirect('/')
In main.html file - form-2 which is a bootstrap Modal form for adding task items.
<div class="float-right">
<!-- Button trigger modal -->
<button type="button" class="btn btn-sm btn-primary ml-1 mt-1 mr-1 mb-1">
<a href="{% url 'addTodo' i.id %}" data-toggle="modal" data-target="#staticBackdrop">
Add
</a>
</button>
<!--Modal -->
<div class="modal fade" id="staticBackdrop" data-backdrop="static" tabindex="-1" role="dialog" aria-labelledby="staticBackdropLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="staticBackdropLabel">Add New Task</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<form action="{% url 'addTodo' i.id %}" method="POST">
{% csrf_token %}
<div class="card">
{{ task_form.heading }}
</div>
<div class="modal-footer">
<button class="btn btn-success" type="submit">Submit</button>
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
I am learning Django 2.2 and using a little bit of Bootstrap 4 to help with the front end. I have a Model created which stores some user information like first name and last name. I have created a DeleteView class which is supposed to delete entries from the database using the ID. Everything works fine as is. But if I try to implement the DeleteView class using a Bootstrap modal window, nothing seems to happen even if I click the submit button. I am not sure what I am doing wrong. I read in another thread here in Stackoverflow that we need to include the button inside a form which I have done too. But it still doesn't delete the entry. Below is all the code required.
Note - I have placed the Delete button inside the contacts_view.html file. The contacts_delete.html file is exactly the same. My idea is to provide the user to not just view the details but also update or even delete the specific entry. When I click on the Delete button, the modal pop up window appears. But when I click on the 'Confirm' button, the entry does not get deleted as required.
Please let me know how to proceed with this.
contacts_view.html / contacts_delete.html
{% extends 'base.html' %}
{% block content %}
<div class="container" style="width: 500px">
<div>
<div class="list-group" style="color: black">
<a class="list-group-item list-group-item-action my-1" style="background-color: wheat">
<div class="row">
<div class="col-4">
First Name
</div>
<div class="col-8">
{{ object.first_name }}
</div>
</div>
</a>
<a class="list-group-item list-group-item-action my-1" style="background-color: wheat">
<div class="row">
<div class="col-4">
last Name
</div>
<div class="col-8">
{{ object.last_name }}
</div>
</div>
</a>
</div>
</div>
<div class="border-top text-center my-4 pt-3">
<a class="btn btn-outline-danger ml-2" href="{% url 'contacts-delete' object.id %}" type="submit" data-toggle="modal" data-target="#myModal">Delete</a>
<!-- Modal -->
<div class="modal fade" id="myModal" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content" style="background-color: whitesmoke; color: dimgray">
<div class="modal-header">
<h4 class="modal-title">Delete Contact</h4>
<button type="button" class="close" data-dismiss="modal">×</button>
</div>
<div class="modal-body text-left">
form
<p>Do you really want to delete {{ object.first_name }} {{ object.last_name }}?</p>
</div>
<div class="modal-footer">
<form method="POST" action="{% url 'contacts-delete' object.id %}">
{% csrf_token %}
<button class="btn btn-outline-warning ml-2" type="submit">Update</button>
<button type="button" class="btn btn-outline-danger" href="{% url 'contacts-delete' object.id %}" data-dismiss="modal">Delete</button>
</form>
<a type="button" class="btn btn-outline-secondary" href="{% url 'contacts-view' object.id %}" data-dismiss="modal">Cancel</a>
</div>
</div>
</div>
</div>
</div>
</div>
{% endblock content %}
views.py
from .models import Contact
from django.urls import reverse_lazy
from django.shortcuts import reverse
from django.views.generic import DetailView, DeleteView
class ContactDetailView(DetailView):
model = Contact
template_name = 'contacts/contacts_view.html'
class ContactDeleteView(DeleteView):
model = Contact
template_name = 'contacts_update.html'
success_url = reverse_lazy('contacts-browse')
models.py
from django.db import models
from django.contrib.auth.models import User
class Contact(models.Model):
added_by = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True)
first_name = models.CharField(max_length=35)
last_name = models.CharField(max_length=35, blank=True, default='')
def __str__(self):
return f"{self.first_name} {self.last_name}"
urls.py
from django.urls import path
from .views import ContactDetailView, ContactDeleteView
urlpatterns = [
path('view/<int:pk>/', ContactDetailView.as_view(), name='contacts-view'),
path('view/<int:pk>/delete/', ContactDeleteView.as_view(), name='contacts-delete'),
]
I'm new to Django, I basically have a homepage which has a search bar that is being implement using a Django Form. Additionally, in the homepage I have bootstrap card whichis being used to display data from my model.
I'm using the def_get to render the form (since it's being used to query the DB). The form is very basic, it's just a CharField. However, when I use the def_get to render the Form in my class based view it now doesn't retrieve any of the data that goes into the bootstrap card which is causing the card to not display.
I've tried to render both the form and data in the card by using ModelFormMixin but it seems like this hasn't solved my issue yet, not sure whether this is the way to achieve this?
Forms.py
from django import forms
class SearchBarForm(forms.Form):
q = forms.CharField(label="", max_length=150, required=True)
Views.py
from django.views.generic import TemplateView
from django.views.generic.list import ListView
from property.models import Property
from pages.forms import SearchBarForm
from django.shortcuts import render
class HomePageView(ListView):
model = Property
template_name = 'home.html'
def get(self, request):
form = SearchBarForm()
return render(request, self.template_name, {'form': form})
Home.html
{% extends 'base.html' %}
{% block title %}Home{% endblock %}
{% block content %}
<div class="container">
<!-- search bar -->
<div class="row">
<div class="col-xs-12 col-sm-6 col-md-8 custom-search-bar">
<form action="{% url 'property_for_rent' %}" method="get" id="search-form">
{{ form.as_p }}
</form>
</div>
<div class="col-xs-6-md-4 custom-search-bar-button">
<button type="submit" form="search-form" class="btn btn-light" value="For sale">For rent</button>
<button form="rent" type="submit" class="btn btn-light" value="For sale">For Sale</button>
</div>
</div>
<!-- search bar -->
<!-- property card -->
<div class="row">
{% for property in object_list|slice:"3" %}
<div class="col-lg-4 d-flex align-items-stretch custom-cards">
<div class="card" style="width: auto;">
<div class="card-img">
{% if property.image %}
<img class="card-img-top" src="{{property.image.url}}" alt="Card image cap"> {% endif %}
</div>
<div class="card-body">
<h5 class="card-title"> {{ property.location }} </h5>
<p class="card-text">{{ property.description }} </p>
<button type="button" class="btn btn-primary waves-effect waves-light" data-toggle="modal" data-target="#modal-{{ property.id }}">View</button>
</div>
<div class="card-footer">
<small class="text-muted">Last updated</small>
</div>
</div>
<!-- property card -->
<!-- Full Height Modal Right -->
<div class="modal fade right" id="modal-{{ property.id }}" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<!-- Add class .modal-full-height and then add class .modal-right (or other classes from list above) to set a position to the modal -->
<div class="modal-dialog modal-full-height modal-right" role="document">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title w-100" id="myModalLabel">{{ property.location }}</h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<p>{{ property.description }}</p>
<ul class="list-group z-depth-0">
<li class="list-group-item justify-content-between">
Bedrooms
<span class="badge badge-primary badge-pill">14</span>
</li>
<li class="list-group-item justify-content-between">
Price
<span class="badge badge-primary badge-pill">2</span>
</li>
<li class="list-group-item justify-content-between">
Location
<span class="badge badge-primary badge-pill">1</span>
</li>
<li class="list-group-item justify-content-between">
Property Type
<span class="badge badge-primary badge-pill">14</span>
</li>
</ul>
</div>
<div class="modal-footer justify-content-center">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>
<!-- Full Height Modal Right -->
</div>
{% endfor %}
</div>
</div>
{% endblock %}
What I want to achieve is to both display the search bar and the cards which are using data from my models.
Any hints on how to achieve this is much appreciated as i'm just a beginner :) Thanks!
You can just pass your form in the get_context_data method [Django-doc]:
class HomePageView(ListView):
model = Property
template_name = 'home.html'
def get_context_data(self, *args, *kwargs):
context = super().get_context_data(*args, **kwargs)
context['form'] = SearchBarForm()
return context
or you can make this more declarative, by making use of the FormMixin mxin [Django-doc]:
from django.views.generic.edit import FormMixin
class HomePageView(FormMixin, ListView):
model = Property
template_name = 'home.html'
form_class = SearchBarForm