Django Handling Multiple Forms - django

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 }}">&laquo</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 }}">&raquo</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 }}">&laquo</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 }}">&raquo</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>

Related

Django Adding Item Mismatching

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 }}">&laquo</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 }}">&raquo</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 }}">&laquo</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 }}">&raquo</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!

Getting a reverse match Django issue

I'm getting a NoReverseMatch error:
NoReverseMatch at /
Reverse for 'post-detail' with arguments '(22, '')' not found. 1 pattern(s) tried: ['post/(?P[0-9]+)/(?P[-a-zA-Z0-9_]+)/$']
not sure how to fix this, here is some of the code :
urls.py
urlpatterns=[
path('', PostListView.as_view(), name='home'),
path('post/new/<slug:slug>/', views.create_post, name='post-create'),
path('post/<int:pk>/<slug:slug>/', views.post_detail, name='post-detail'),
path('like/<slug:slug>/', views.like, name='post-like'),
path('post/<int:pk>/<slug:slug>/update/', PostUpdateView.as_view(), name='post-update'),
path('post/<int:pk>/<slug:slug>/delete/', views.post_delete, name='post-delete'),
path('search_posts/', views.search_posts, name='search_posts'),
feed models
models.py
class Post(models.Model):
description = models.TextField(max_length=255)
pic = models.ImageField(upload_to='path/to/img', blank=True)
date_posted = models.DateTimeField(default=timezone.now)
user_name = models.ForeignKey(User, on_delete=models.CASCADE)
tags = models.CharField(max_length=100, blank=True)
def __str__(self):
return self.description
def get_absolute_url(self):
return reverse('post-detail', kwargs={'pk': self.pk, 'slug': self.user_name.profile.slug})
users models
models.py
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
image = models.ImageField(default='default.png', upload_to='profile_pics')
slug = AutoSlugField(populate_from='user')
bio = models.CharField(max_length=255, blank=True)
friends = models.ManyToManyField('Profile', blank=True)
def __str__(self):
return str(self.user.username)
def get_absolute_url(self):
return "/users/{}".format(self.slug)
views.py
#login_required
def post_detail(request, pk, slug):
post = get_object_or_404(Post, pk=pk)
user = request.user
is_liked = Like.objects.filter(user=user, post=post)
if request.method == 'POST':
form = NewCommentForm(request.POST)
if form.is_valid():
data = form.save(commit=False)
data.post = post
data.username = user
data.save()
return redirect('post-detail', pk=pk, slug=slug)
else:
form = NewCommentForm()
return render(request, 'feed/post_detail.html', {'post':post, 'is_liked':is_liked, 'form':form})
home.html
{% extends "feed/layout.html" %}
{% load static %}
{% block cssfiles %}
{% endblock cssfiles %}
{% block searchform %}
<div class="container2">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.3.1/css/all.css"
integrity="sha384-mzrmE5qonljUremFsqc01SB46JvROS7bZs3IO2EmfFsd15uHvIt+Y8vEf7N7fWAU" crossorigin="anonymous">
<form class="searchbar" action="{% url 'search_posts' %}" method="get"">
<input class="postquery" name="p" type="text" autocomplete="off"/ placeholder="Search posts..">
<button id="search_btn" type="submit">
<i class="fa fa-search"></i>
</button>
</form>
</div>
{% endblock searchform %}
{% block content %}
<div class="container mt-7">
<div class="row">
<div class="col-xl-9 col-md-10 m-auto order-xl-2 mb-5 mb-xl-0">
{% for post in posts %}
<div class="card card-signin my-5">
<div class="card-body">
<img src="{{ post.user_name.profile.image.url }}" class="rounded-circle" width="30" height="30" alt="">
<a class="text-dark" href="{{ post.user_name.profile.get_absolute_url }}"><b>{{ post.user_name }}</b></a>
<br><small class="text-muted">Posted on {{ post.date_posted }}</small>
<br><br>
<p class="card-text text-dark">{{ post.description }}</p>
</div>
{% if post.pic %}
<img class="card-img-top" src="{{ post.pic.url }}" alt="">
{% endif %}
{% if post.tags %}
<br>
<p class="text-danger ml-3"><b>Tags: <i>{{ post.tags }}</i></b></p>
{% endif %}
<div class="card-footer">
<button class="btn btn-white mr-3 like" id="{{ post.id }}">
{% if post in liked_post %}
Unlike | {{post.likes.count}}
{% else %}
Like | {{post.likes.count}}
{% endif %}
</button>
<a class="btn btn-outline-info" href="{% url 'post-detail' post.id user.profile.slug %}">Comments | {{ post.details.count }}</a>
{% if post.user_name == user %}
<a class="btn btn-outline-info mr-0 float-right" href="{% url 'post-update' post.id user.profile.slug %}">Edit Post</a>
<a class="post_delete" href="{% url 'post-delete' post.id user.profile.slug %}">delete</a>
{% endif %}
</div>
</div>
{% endfor %}
</div>
</div>
</div>
{% if is_paginated %}
{% if page_obj.has_previous %}
<a class="btn btn-outline-info mb-4" href="?page=1">First</a>
<a class="btn btn-outline-info mb-4" href="?page={{ page_obj.previous_page_number }}">Previous</a>
{% endif %}
{% for num in page_obj.paginator.page_range %}
{% if page_obj.number == num %}
<a class="btn btn-info mb-4" href="?page={{ num }}">{{ num }}</a>
{% elif num > page_obj.number|add:'-3' and num < page_obj.number|add:'3' %}
<a class="btn btn-outline-info mb-4" href="?page={{ num }}">{{ num }}</a>
{% endif %}
{% endfor %}
{% if page_obj.has_next %}
<a class="btn btn-outline-info mb-4" href="?page={{ page_obj.next_page_number }}">Next</a>
<a class="btn btn-outline-info mb-4" href="?page={{ page_obj.paginator.num_pages }}">Last</a>
{% endif %}
{% endif %}
{% endblock content %}
When i click on the home page link I get the error mentioned above , not sure what in this template is causing it ? any ideas ?

Django template tags conditionals

Right, am struggling with my blog app when trying to render some logic through the template view. So the idea is to render a one time only button for the newly authenticated users that do not have a post published and after the user has published its first post the button will be rendered within a for loop so he/she'll be able to create/delete a new one from there.
views.py
#login_required(login_url='app_users:login')
#allowed_users(allowed_roles=['admin', 'staff', 'users'])
def blog(request):
posts = BlogPost.objects.all().order_by('date_posted')
context = {'title': 'Blog', 'posts': posts}
return render(request, 'app_blog/blog.html', context)
models.py
class BlogPost(models.Model):
title = models.CharField(max_length=100, null=True)
content = models.TextField(null=True)
date_posted = models.DateTimeField(default=timezone.now, null=True, blank=True)
author = models.ForeignKey(User, on_delete=models.CASCADE)
def __str__(self):
return self.title
blog.html
{% block content %}
{% if request.user not in posts|last %}
<div class="container" style="float: left;">
<a class="btn btn-primary btn-sm mt-1 mb-1" href="{% url 'app_blog:blog_create' user.id %}"><h5>C'mon {{ request.user.username }}, don't be shy! Create Your First Blog Post!</h5></a>
</div>
{% endif %}
<br>
<br>
{% for post in posts %}
<br>
<div class="container">
<article class="media content-section">
<img class="rounded-circle account-img" src="{{ post.author.profile.image.url }}" alt="Image could not be uploaded!">
<div class="card-body media-body">
<div class="article-metadata">
<a class="mr-2" href="{% url 'app_blog:blog_user_detail' post.id %}">{{ post.author }}</a>
<small class="text-muted">{{ post.date_posted|date:"d F Y" }}</small>
</div>
<div class="article-metadata">
{% if post.author == request.user %}
<div>
<a class="btn btn-primary btn-sm mt-1 mb-1" href="{% url 'app_blog:blog_create' post.id %}">Create New Post</a>
<a class="btn btn-primary btn-danger btn-sm mt-1 mb-1" href="{% url 'app_blog:blog_delete' post.id %}">Delete</a>
</div>
{% endif %}
</div>
<h2><a class="article-title" href="{% url 'app_blog:blog_detail' post.id %}">{{ post.title }}</a></h2>
<p class="article-content">{{ post.content|safe }}</p>
</div>
</article>
</div>
<br>
{% endfor %}
{% endblock %}
So, again, end question would be about what sort of conditionals to use here:
{% if request.user not in posts|last %}
Thanks.
Not quite sure I fully understand but I will suggest something. A user who was a saved post should not see that button? If so, maybe something like this would work:
{% if request.user not in posts.authors.all %}
EDIT original solution won't work. posts is a queryset object
views.py
#login_required(login_url='app_users:login')
#allowed_users(allowed_roles=['admin', 'staff', 'users'])
def blog(request):
posts = BlogPost.objects.all().order_by('date_posted')
new_user = len(posts.filter(author=request.user)) == 0
context = {'title': 'Blog', 'posts': posts, 'new_user': new_user}
return render(request, 'app_blog/blog.html', context)
blog.html (just the condition)
{% if new_user %}

How do you implement a Form in a ListView

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

NoReverseMatch Django url issue

I am trying to implement a typical url in my django project however i keep getting the error meassage. I have checked my urls, views and html code where i have passed in the KWARGS. I have no clue what went wrong here please help?
The home.html uses user_profile_detail in the template
userprofile/home.html
<div class="sidebar-fixed position-fixed side_nav_bar ">
<a class="logo-wrapper waves-effect">
<img src="/" class="img-fluid" alt="">
</a>
<div class="list-group list-group-flush">
**<a href="{% url 'userprofile:dashboard' user_profile_detail.slug %}" class="list-group-item {% if request.path == dashboard %}active{% endif %} waves-effect">
<i class="fa fa-pie-chart mr-3"></i>Dashboard
</a>**
<a href="{% url 'userprofile:profile' user_profile_detail.slug %}" class="list-group-item {% if request.path == profile %}active{% endif %} list-group-item-action waves-effect">
<i class="fa fa-user mr-3"></i>Profile</a>
<a href="{% url 'userprofile:watchlist' user_profile_detail.slug %}" class="list-group-item {% if request.path == watchlist %}active{% endif %} list-group-item-action waves-effect">
<i class="fa fa-eye mr-3" aria-hidden="true"></i>WatchList</a>
<a href="{% url 'userprofile:blog' user_profile_detail.slug %}" class="list-group-item {% if request.path == blog %}active{% endif %} list-group-item-action waves-effect">
<i class="fa fa-book mr-3" aria-hidden="true"></i>My Blogs</a>
<a href="{% url 'userprofile:history' user_profile_detail.slug %}" class="list-group-item {% if request.path == history %}active{% endif %} list-group-item-action waves-effect">
<i class="fa fa-history mr-3" aria-hidden="true"></i>My Browsing History</a>
</div>
</div>
MODELS.PY
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
slug = models.SlugField(blank=True, unique=True)
VIEWS.PY
def dashboard_view(request, slug):
userprofile = Profile.objects.get(slug=slug)
user_viewed_object = userprofile.objectviewed_set.first()
user_blog = userprofile.userblog_set.first()
user_watchlist = userprofile.watchlist_set.first()
context = {
'user_profile_detail': userprofile,
'user_blog': user_blog,
'user_watchlist': user_watchlist,
'user_viewed_object': user_viewed_object,
'page_name': "Dashboard"
}
print(userprofile.slug)
return render(request, 'userprofile/home.html', context)
def profile_view(request, slug):
user_profile_detail = Profile.objects.get(slug=slug)
if request.method == 'POST':
form = ProfileForm(request.POST or None, request.FILES, instance=user_profile_detail)
if form.is_valid():
print(form)
form.save(commit=False)
user_profile_detail = request.user
form.save()
return HttpResponseRedirect('/')
context = {
'profile': user_profile_detail,
'page_name': 'Profile',
'form': form
}
return render(request, 'userprofile/profile.html', context)
URLS.PY
app_name = 'userprofile'
urlpatterns = [
path('<slug:slug>', dashboard_view, name="dashboard"),
path('<slug:slug>/user_profile/', profile_view, name='profile'),
path('<slug:slug>/watchlist/', watchlist_view, name='watchlist'),
path('<slug:slug>/blog/', userblog_view, name="blog"),
path('<slug:slug>/history/', user_history, name="history"),
]
ERROR MESSAGE:
NoReverseMatch at /profile/jacklit/user_profile/
Reverse for 'dashboard' with arguments '('',)' not found. 1 pattern(s) tried: ['profile\\/(?P<slug>[-a-zA-Z0-9_]+)$']
profile.html
{% extends 'userprofile/dashboard.html' %}
{% load crispy_forms_tags %}
{% block content %}
<div class="container-fluid mt-5">
{% include 'userprofile/dashboard_head.html' %}
{% include 'userprofile/large_center_modal.html' %}
<div class="card">
<h2 class="my-3 mx-3"><i class="fa fa-user mr-3" aria-hidden="true"></i>My Profile</h2>
<hr >
<div class="row my-5 mx-1">
<div class="col-3 text-center pl-3">
{% if profile.profile_picture %}
<img src="{{ profile.profile_picture.url }}" alt=""
class="img-fluid z-depth-1-half rounded-circle">
{% endif %}
<div style="height: 10px"></div>
<p class="title mb-0">{{ profile.first_name }} {{ profile.last_name }}</p><br>
<p class="title mb-0" style="font-size: 13px">{{ profile.role }}</p><br>
<p class="title mb-0"><b>Joined: </b>{{ profile.joined }}</p><br><br>
{% if request.user == profile.user %}
Edit Profile
{% endif %}
</div>
<div class="col-9">
<h3><u>Biography</u></h3>
<h6>{{ profile.biography }}</h6>
<hr>
<h6><i class="fa fa-envelope mr-3" aria-hidden="true"></i>Email Address: {{ profile.email }}</h6>
<h6><i class="fa fa-phone mr-3" aria-hidden="true"></i>Office Number:{{ profile.office_number }}</h6>
<h6><i class="fa fa-mobile-phone mr-3" aria-hidden="true"></i>Phone Number: {{ profile.phone_number }}</h6>
<br><br>
<h3><u>Contact Information</u></h3>
<h6>Email: {{ profile.email }}</h6>
<h6>Office: {{ profile.office_number }}</h6>
<h6>Phone: {{ profile.phone_number }}</h6><br><br>
<h3><u>Social Medias</u></h3>
<h6><i class="fa fa-google-plus mr-3"></i>Google Plus:</h6>
<h6><i class="fa fa-facebook mr-3"></i>Facebook: </h6>
<h6><i class="fa fa-twitter mr-3"></i>Twitter: </h6>
<h6><i class="fa fa-linkedin mr-3"></i>LinkedIn: </h6>
</div>
</div>
</div>
</div>
{% endblock %}
Large_center_Modal.html
<form action="{% url 'userprofile:profile' user_profile_detail.slug %}" enctype="multipart/form-data" method="post">
{% csrf_token %}
<div class="modal fade" id="centralModalLGInfoDemo" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog modal-lg modal-notify modal-info" role="document">
<!--Content-->
<div class="modal-content">
<!--Header-->
<div class="modal-header">
<p class="heading lead">Update my Profie</p>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true" class="white-text">×</span>
</button>
</div>
<!--Body-->
<div class="modal-body">
<div class="">
<div class="col-10">{{ form | crispy }}</div>
</div>
</div>
<!--Footer-->
<div class="modal-footer">
<button type="submit" class="btn btn-outline-info waves-effect">Update</button>
</div>
</div>
<!--/.Content-->
</div>
</div>
</form>
Your context dict has profile key: 'profile': user_profile_detail,. So in template you should use profile instead of user_profile_detail:
"{% url 'userprofile:dashboard' profile.slug %}"