How to get these gender choices to display as radio buttons - python-3.x

I am relatively new to Django and I have no idea how to get the gender choices in my Models to my views and then to my templates.
Below is my Models.py:
from django.db import models
from django.forms import ModelForm
from model_utils import Choices
class Country(models.Model):
''' define a table in the database called Country with several variables.'''
name = models.CharField(max_length = 50, unique = True)
officiallang = models.CharField(max_length = 50)
size = models.IntegerField()
# TODO: Find out how to defined this relationship
# representative = models.OneToOneField(UNrepresentative)
class UNrepresentative(models.Model):
GENDER_CHOICES = (
('M', 'Male'),
('F', 'Female'),
('O', 'Other'),
)
name = models.CharField(max_length = 100, unique = True)
gender = models.CharField(max_length = 1,choices = GENDER_CHOICES,)
country = models.OneToOneField(Country, on_delete = models.CASCADE, )
class CountryForm(ModelForm):
class Meta:
model = Country
fields = ['name', 'officiallang', 'size']
class UNrepresentativeForm(ModelForm):
class Meta:
model = UNrepresentative
fields = ['name', 'gender', 'country']
Below is my Forms.py:
from django import forms
from app1.models import Country, UNrepresentative
class CountryForm(forms.Form):
name = forms.CharField(max_length = 50,)
officiallang = forms.CharField(max_length = 50)
size = forms.IntegerField()
class UNrepresentativeForm(forms.Form):
name = forms.CharField(max_length = 100,)
gender = forms.ChoiceField(
choices = UNrepresentative.GENDER_CHOICES,)
Finally, here is create_representative.html which contains the templates code:
{% extends 'base.html' %}
{% block content %}
<form method = 'POST' action = "{% url 'create_representative' %}">
{% csrf_token %}
<div class="form-row">
<div class="col-4">
<input type="text" class="form-control" placeholder="name" value = "" name = 'name'>
</div>
<div class="col-4">
<div>
<label>Male</label>
<input type="radio" placeholder="gender" value="male" name='gender'>
</div>
<div>
<label>Female</label>
<input type="radio" placeholder="gender" value="female" name='gender'>
</div>
</div>
<div class = 'col-4'>
<label for="country">Choose a country:</label>
<select name="country_id">
{% for items in all_items %}
<option value="{{items.id}}">{{items.name}}</option>
{% endfor %}
</select>
</div>
<div class = 'col'>
<button type="submit" class="btn btn-outline-secondary">Create rep</button>
</div>
</div>
</form>
{% endblock content %}
I have manually added male and female in values but ideally what I want to have is a dropdown with radio buttons to choose one of the genders. Any help will be appreciated. Thank you.

Related

Django: Exception Value: The 'image' attribute has no file associated with it

Hi everyone I'm trying to create an auction system with Django.
But when I go to the item profile, Django sends me an error:
Exception Value:
The 'image' attribute has no file associated with it.
auction.html
{% extends "base.html" %}
{% block content %}
{% load static %}
<div class="page-header">
<h1>OPEN AUCTIONS</h1>
</div>
<div class="container">
<div class="row">
{% for item in auction %}
<div class="col-sm-4">
<div class="card border-secondary" style="width: 25rem;">
<div class="card-header">
Auction {{item.id}}
</div>
<img src="{{ item.image.url }}" class="card-img-top" width="250" height="180">
<div class="card-body">
<h3 class="card-title" style="text-align:center" >{{ item.object }}</h3>
<p class="card-text">{{item.description}}<br> Price: ${{ item.open_price}}<br>
End: {{ item.close_date }}</p>
<form method="POST">
{% csrf_token %}
<input type="number" name='auct_id' value={{item.id}} readonly>
<button type="submit" class="btn btn-primary btn-sm">Go</button>
</form>
</div>
</div>
</div>
{% endfor %}
</div>
</div>
{% endblock %}
If I remove item from <img src="{{ item.image.url }}" class="card-img-top" width="250" height="180"> the page work correctly but the image doesn't display. Like this:
view.py
#login_required(login_url="login")
def auction(request):
if request.user.is_superuser:
messages.error(
request, "super user can access to admin/ and new_auction page only"
)
return redirect("new_auction")
auction = Auction.objects.filter(active=True)
for data in auction:
check = check_data(data.close_date)
if check is False:
data.active = False
data.save()
check_winner(
request, data.id
)
check_prof = check_profile(
request
)
if check_prof is True:
return redirect("profile")
auctions_open = Auction.objects.filter(active=True)
if request.method == "POST":
form = request.POST
auct_ids = form["auct_id"]
auct_id = int(auct_ids)
request.session["selected_id"] = auct_id
return redirect("betting")
else:
return render(request, "auction/auction.html", {"auction": auctions_open})
models.py
from django.db import models
from django.contrib.auth.models import User
from datetime import datetime
# Create your models here.
class Auction(models.Model):
object = models.CharField(max_length=50)
description = models.CharField(max_length=256, default="")
image = models.ImageField(upload_to="media/", null=True, blank=True)
open_date = models.DateTimeField(auto_now_add=True)
close_date = models.DateTimeField()
total_bet = models.IntegerField(default=0)
open_price = models.FloatField(
default=0,
)
close_price = models.FloatField(default=0)
winner = models.CharField(max_length=256, default="")
active = models.BooleanField(default=True)
json_details_file = models.TextField(default="")
tx = models.CharField(max_length=256, default="")
def __str__(self):
return self.object
settings.py
MEDIA_ROOT = os.path.join((BASE_DIR), "media")
MEDIA_URL = "/media/"
According to your model field image, you must give different name instead of media to upload_to.
Let's give different name to upload_to:
image = models.ImageField(upload_to="images/", null=True, blank=True) #here added images instead of media
And in your template:
instead of this:
<img src="{{ item.image.url }}" class="card-img-top" width="250" height="180">
Try this way:
<img src="/media/{{ item.image }}" class="card-img-top" width="250" height="180">
And now that images will display.
Note: don't forget to migrate after modifying upload_to="images/"

django form not showing in template to add data

the goal of my code is to make a school management system where the admin can log in and add teachers to their respective classes that they are leading and be able to add students to their respective classes and then take the attendance of those students present on any given day. however, I am having an issue where the form to add the student to the class isn't rendering when I click on the add student button. I have been searching but can't seem to find the error in my code, I am new to Django so any help will be appreciated. the closest I got was to make the modal show up but the fields to select the student from to add to the class wasn't showing
models
class Teacher(models.Model):
first_name = models.CharField(max_length=60, blank=False, null=False)
last_name = models.CharField(max_length=80, blank=False, null=False)
address = models.CharField(max_length=120, blank=True, null=True)
contact = models.CharField(max_length=10, blank=True, null=True)
email = models.EmailField(blank=True, null=True)
birth = models.CharField(max_length=20, blank=True, null=True)
gender = models.CharField(max_length=100, choices=[('Male', 'Male'), ('Female', 'Female')], blank=True, null=True)
comment = models.TextField(max_length=10000, blank=True, null=True)
def __str__(self):
return f"{self.first_name + ' ' + self.last_name}"
class Student(models.Model):
student_code = models.CharField(max_length=250, blank=True, null=True)
first_name = models.CharField(max_length=20, blank=False, null=False)
last_name = models.CharField(max_length=20, blank=False, null=False)
address = models.CharField(max_length=120, blank=True, null=True)
contact = models.CharField(max_length=10, blank=True, null=True)
admission = models.CharField(max_length=20, blank=True, null=True)
birth = models.CharField(max_length=20, blank=True, null=True)
parents = models.CharField(max_length=200, blank=False)
gender = models.CharField(max_length=100, choices=[('Male', 'Male'), ('Female', 'Female')], blank=True, null=True)
comment = models.TextField(max_length=10000, null=True, blank=True)
passport = models.ImageField(null=True,blank=True, default='default.png', upload_to="profile/")
def __str__(self):
return f"{self.first_name + ' ' + self.last_name}"
def save(self, *args, **kawrgs):
super().save(*args, **kawrgs)
img = Image.open(self.passport.path)
if img.height > 300 or img.width > 300:
output_size = (300, 300)
img.thumbnail(output_size)
img.save(self.passport.path)
class Room(models.Model):
form_teacher = models.ForeignKey(Teacher, on_delete=models.CASCADE)
school_year = models.CharField(max_length=250)
level = models.CharField(max_length=250)
name = models.CharField(max_length=250)
def __str__(self):
return "[" + self.level + "] " + self.level + '-' + self.name
class ClassStudent(models.Model):
classIns = models.ForeignKey(Room, on_delete=models.CASCADE)
student = models.ForeignKey(Student, on_delete=models.CASCADE)
def __str__(self):
return self.student.student_code
def get_present(self):
student = self.student
_class = self.classIns
try:
present = Attendance.objects.filter(
classIns=_class, student=student, type=1).count()
return present
except:
return 0
def get_tardy(self):
student = self.student
_class = self.classIns
try:
present = Attendance.objects.filter(
classIns=_class, student=student, type=2).count()
return present
except:
return 0
def get_absent(self):
student = self.student
_class = self.classIns
try:
present = Attendance.objects.filter(classIns= _class, student=student, type = 3).count()
return present
except:
return 0
class Attendance(models.Model):
classIns = models.ForeignKey(Room, on_delete=models.CASCADE, default=' ')
student = models.ForeignKey(Student, on_delete=models.CASCADE, default=' ')
attendance_date = models.DateField(default=' ')
type = models.CharField(max_length=250, choices=[(
'1', 'Present'), ('2', 'Tardy'), ('1', 'Absent')], default=' ')
date_updated = models.DateTimeField(auto_now=True)
def __str__(self):
return self.classIns.name + " " + self.student.student_code
views
# create a classroom
login_required()
def class_view(request):
form = ClassRoomForm()
if request.method == 'POST':
form = ClassRoomForm(request.POST)
if form.is_valid():
form.save()
name = form.cleaned_data.get('name')
messages.success(request, f'{name} was Successfully Added')
return redirect('classroom')
classes = Room.objects.all()
return render(request, 'school/class_view.html', {"form": form, 'classes': classes})
#show all the classroom created
#login_required
def class_detail(request,pk):
_class = Room.objects.filter(id=pk).first()
students = ClassStudent.objects.filter(classIns =_class).all()
print(students)
context = {
'class': _class,
'students': students
}
return render(request, "school/class_info.html", context)
#passes the form responsible for adding student to the classroom
#login_required
def save_class_student(request):
form = SaveClassStudent()
if request.method == 'POST':
form = SaveClassStudent(request.POST)
if form.is_valid():
form.save()
messages.success(request, "Student has been added successfully.")
redirect('class_detail')
return render(request, 'school/class_info.html', {'form': form})
forms
class ClassRoomForm(forms.ModelForm):
school_year = forms.CharField(max_length=250,help_text = "School Year Field is required.")
level = forms.CharField(max_length=250,help_text = "Level Field is required.")
name = forms.CharField(max_length=250,help_text = "Class Name Field is required.")
class Meta:
model = Room
fields = ('form_teacher', 'name', 'level', 'school_year')
class SaveClassStudent(forms.ModelForm):
classIns = forms.IntegerField()
student = forms.IntegerField()
class Meta:
model = ClassStudent
fields = ('classIns', 'student')
def clean_classIns(self):
cid = self.cleaned_data['classIns']
try:
classIns = Room.objects.get(id=cid)
return classIns
except:
raise forms.ValidationError("Class ID is Invalid.")
def clean_student(self):
student_id = self.cleaned_data['student']
_class = Room.objects.get(id=self.data.get('classIns'))
student = Student.objects.get(id=student_id)
try:
cs = ClassStudent.objects.get(classIns=_class, student=student)
if len(cs) > 0:
raise forms.ValidationError(
f"Student already exists in the Class List.")
except:
return student
HTML template for the form
{% extends 'school/dashboard.html' %}
{% load static %}
{% load widget_tweaks %}
{% load humanize %}
{% block title%}
<title>Class Information</title>
{% endblock %}
{% block page%}Class Info{% endblock %}
{% block card%} {%endblock%}
{% block table %}
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
<div class="card card-default rounded-0 shadow ">
<div class="card-header">
<div class="d-flex w-100 align-items-center justify-content-between">
<h4 class="card-title fw-bold">Class Information</h4>
<div class="tools">
<button type="button" class="btn btn-secondary border rounded-0 bg-gradient btn-sm"
id='print_attendance_report'><i class="fa fa-print"></i> Print Attendance Report</button>
<a href="#addModal" data-bs-toggle="modal"> <button type="button" class="btn btn-primary rounded-0 bg-gradient btn-sm" id='add_new'><i
class="fa fa-plus"></i> Add Student</button></a>
</div>
</div>
</div>
<div class="card-body">
<div class="container-fluid">
<fieldset id="class-details">
<legend>Class Details</legend>
<div class="row">
<div class="col-md-6">
<div class="d-flex w-100">
<div class="col-auto pe-2 text-muted">School Year:</div>
<div class="col-auto flex-shrink-1 flex-grow-1">
<p class="m-0 fw-bold">{{ class.school_year }}</p>
</div>
</div>
</div>
<div class="col-md-6">
<div class="d-flex w-100">
<div class="col-auto pe-2 text-muted">Level:</div>
<div class="col-auto flex-shrink-1 flex-grow-1">
<p class="m-0 fw-bold">{{ class.level }}</p>
</div>
</div>
</div>
<div class="col-md-6">
<div class="d-flex w-100">
<div class="col-auto pe-2 text-muted">Name:</div>
<div class="col-auto flex-shrink-1 flex-grow-1">
<p class="m-0 fw-bold">{{ class.name }}</p>
</div>
</div>
</div>
<div class="col-md-6">
<div class="d-flex w-100">
<div class="col-auto pe-2 text-muted">Faculty:</div>
<div class="col-auto flex-shrink-1 flex-grow-1">
<p class="m-0 fw-bold">{{ class.form_teacher}}</p>
</div>
</div>
</div>
</div>
</fieldset>
<hr>
<fieldset>
<legend>Class Student List</legend>
<table class="table tables-bordered" id="student-list">
<colgroup>
<col width="10%">
<col width="25%">
<col width="25%">
<col width="10%">
<col width="10%">
<col width="10%">
<col width="10%">
</colgroup>
<thead>
<tr>
<th class="text-ceter">#</th>
<th class="text-ceter">Student Code</th>
<th class="text-ceter">Student Name</th>
<th class="text-ceter">Total Tardy</th>
<th class="text-ceter">Total Absent</th>
<th class="text-ceter">Total Present</th>
<th class="text-ceter">Actions</th>
</tr>
</thead>
<tbody>
{% for student in students %}
<tr class="">
<td class="text-center">{{ forloop.counter }}</td>
<td>{{ student.student.student_code }}</td>
<td>{{ student.student.first_name }} {{student.student.last_name }}</td>
<td class="text-center">{{ student.get_present|intcomma }}</td>
<td class="text-center">{{ student.get_tardy|intcomma }}</td>
<td class="text-center">{{ student.get_absent|intcomma }}</td>
<td class="text-center">
<button class="btn btn-outline-danger btn-sm delete-data" type="button"
data-id="{{ student.pk }}" title="Delete">
<i class="fa fa-trash"></i>
</button>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</fieldset>
</div>
</div>
</div>
</div>
{% endblock %}
{% block content%}
<!-- Modal -->
<div class="modal fade" id="addModal" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1"
aria-labelledby="staticBackdropLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="staticBackdropLabel">Add Student To Class</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<form class="row g-3" method="post">
{% csrf_token %}
<div class="col-md-6 form-group">
<label class="form-label">Student</label>
{% render_field form.student class+="form-control" %}
</div>
<div class="col-md-12">
<button type="submit" class="btn btn-primary">Place</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
{% endblock %}
Here are a few recommendations. Firstly, within your forms.py you're re-creating the existing fields and that's not necessary. For example:
class ClassRoomForm(forms.ModelForm):
# school_year = forms.CharField(max_length=250,help_text = "School Year Field is required.")
# level = forms.CharField(max_length=250,help_text = "Level Field is required.")
# name = forms.CharField(max_length=250,help_text = "Class Name Field is required.")
# There's no need to re-create the above since they're in the Room model already.
class Meta:
model = Room
fields = ('form_teacher', 'name', 'level', 'school_year')
# What you need to do is to use the widget attribute on the Class Meta to set the help_text and the max_length.
widgets = {
'name': forms.TextInput(attr={'class':'form-control'}, max_length=250, help_text='Class Name Field is required.'),
'level': forms.TextInput(attr={'class':'form-control'}, max_length=250, help_text='Level Field is required.'),
'school_year': forms.TextInput(attr={'class':'form-control'}, max_length=250, help_text='School Year Field is required.'),
}
You could take that approach for the other forms you have as well.
Secondly, since you mentioned that the save_class_student method is passing the form, I'd suggest using {{ form.student }} if you want to render the form field of the form you're passing to the template.
<form class="row g-3" method="post">
{% csrf_token %}
...
<label class="form-label">Student</label>
{{ form.student }}
...
</form>
However, I think you might want to pass the form from the class_detail method since you want it to be displayed with the existing class information based on what you have in your template. With this, you could have the save_class_student method to handle the post request instead of trying to pass the form from there. For example:
#login_required
def class_detail(request,pk):
_class = Room.objects.filter(id=pk).first()
students = ClassStudent.objects.filter(classIns =_class).all()
# The classroom data: Initilizer
data = {
'classIns': _class # To set the classroom on the form since you'll be displaying on the student field.
}
form = SaveClassStudent(initial=data)
context = {
'class': _class,
'students': students,
'form': form,
}
return render(request, "school/class_info.html", context)
Then within the html file, you can have the form's action calling the url for the save_class_student method.
<form class="row g-3" method="post" action="{% url 'save_class_student url here' %}">
{% csrf_token %}
...
<label class="form-label">Student</label>
{{ form.student }}
...
</form>

Django: NoReverseMatch at /home/blog/ Reverse for 'post-detail' not found. 'post-detail' is not a valid view function or pattern name

I have been getting this error, and I didn't know what I did wrong in the code, I checked everything and I still cant figure it out. I also try getting the specific post object in the database by id, i mean doing something like "post = Post.objects.get(id=id)" in post function in my views.py, but i got the same error.
Any help will be appreciated.
this is my models.py
from django.db import models
from django.contrib.auth import get_user_model
from django.urls import reverse
User = get_user_model()
class Author(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
profile_pic = models.ImageField()
def __str__(self):
return self.user.username
class Category(models.Model):
name = models.CharField(max_length=50)
def __str__(self):
return self.name
class Post(models.Model):
title = models.CharField(max_length=200)
overview = models.CharField(max_length=200)
categories = models.ManyToManyField(Category)
author = models.ForeignKey(Author, on_delete=models.CASCADE)
comment_count = models.IntegerField(default=0)
views_count = models.IntegerField(default=0)
timestamp = models.DateTimeField(auto_now_add=True)
thumbnail = models.ImageField()
featured = models.BooleanField(default=False)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('post-detail', kwargs={'id': self.id})
my urls
from django.urls import path
from blog.views import home, blog, post
app_name = 'blog'
urlpatterns = [
path('', home, name='home-page'),
path('blog/', blog, name='blogs'),
path('post/<id>/', post, name='post-detail'),
]
my blog.html template
<div class="container">
<div class="row">
{% for post in queryset %}
<div class="post col-xl-6">
<div class="post-thumbnail">
<img src="{{post.thumbnail.url}}" alt="..." class="img-fluid">
</div>
<div class="post-details">
<div class="post-meta d-flex justify-content-between">
<div class="category">
{% for cat in post.categories.all %}
{{cat}}
{% endfor %}
</div>
</div>
<a href="{{post.get_absolute_url}}">
<h3 class="h4">{{post.title}}</h3>
</a>
<p class="text-muted">{{post.overview}}</p>
<footer class="post-footer d-flex align-items-center">
<a href="#" class="author d-flex align-items-center flex-wrap">
<div class="avatar">
<img src="{{post.author.profile_pic.url}}" alt="..." class="img-fluid">
</div>
<div class="title">
<span>{{post.author.user.username}}</span>
</div>
</a>
<div class="date"><i class="icon-clock"></i>{{post.timestamp|timesince}} ago</div>
<div class="comments meta-last"><i class="icon-comment"></i>{{post.comment_count}}</div>
</footer>
</div>
</div>
{% endfor %}
</div>
<!-- Pagination -->
<nav aria-label="Page navigation example">
<ul class="pagination pagination-template d-flex justify-content-center">
{% if queryset.has_previous %}
<li class="page-item">
<a href="?page={{queryset.previous_page_number}}" class="page-link">
<i class="fa fa-angle-left"></i>
</a>
</li>
{% endif %}
<li class="page-item">{{queryset.number}}</li>
{% if queryset.has_next %}
<li class="page-item">
<a href="?page={{queryset.next_page_number}}" class="page-link">
<i class="fa fa-angle-right"></i>
</a>
</li>
{% endif %}
</ul>
</nav>
</div>
my views.py
from django.shortcuts import render, redirect
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from blog.models import Post, Category
from marketing.models import Signup
def home(request):
featured_posts = Post.objects.filter(featured=True)
latest_posts = Post.objects.order_by('-timestamp')[:3]
if request.method == 'POST':
email = request.POST['email']
new_signup = Signup()
new_signup.email = email
new_signup.save()
context = {
'featured_posts': featured_posts,
'latest_posts': latest_posts
}
return render(request, 'index.html', context)
def blog(request):
post_list = Post.objects.all()
latest_posts = Post.objects.order_by('-timestamp')[:3]
categories = Category.objects.all()
paginator = Paginator(post_list, 4)
page_number = request.GET.get('page')
try:
queryset = paginator.get_page(page_number)
except PageNotAnInteger:
queryset = paginator.get_page(1)
except EmptyPage:
queryset = paginator.get_page(paginator.num_pages)
context = {
'post_list': post_list,
'queryset': queryset,
'latest_posts': latest_posts,
'categories': categories,
}
return render(request, 'blog.html', context)
def post(request, id):
context = {}
return render(request, 'post.html', context)
In your models.py change the get_absolute_url as follow. You need to include the app name also before calling any specific url from an app.
def get_absolute_url(self):
return reverse('blog:post-detail', kwargs={'id': self.id})

Set instances of a Form without the User input

I am trying to set an instance of a Modelform that render through ListView.
Program Model:
class Program(models.Model):
patient = models.ForeignKey(User, on_delete=models.CASCADE, default=0)
program_name = models.CharField(max_length=1000, default="")
date_posted = models.DateTimeField(default=timezone.now)
def __str__(self):
return str(self.id) + " - " + self.patient.username + " - " + self.program_name + " - " + str(self.date_posted)
def get_absolute_url(self):
return reverse('program-detail', kwargs={'pk': self.pk})
Exercise Model:
class Exercise(models.Model):
program = models.ForeignKey(Program, on_delete=models.CASCADE, default=0)
date_posted = models.DateTimeField(default=timezone.now)
name = models.CharField(max_length=1000, default="")
description = models.TextField(default="")
load_share = models.TextField(default="")
breath_method = models.TextField(default="")
recovery_method = models.TextField(default="")
measure_method = models.TextField(default="")
notes = models.TextField(default="")
extra_info = models.TextField(default="")
reps = models.PositiveSmallIntegerField(default=0)
sets = models.PositiveSmallIntegerField(default=0)
def __str__(self):
return str(self.program_id) + " - " + str(self.pk) + " - " + " - " + self.name + " - " + str(self.date_posted)
Data Model:
exercise = models.ForeignKey(Exercise, on_delete=models.CASCADE, default="0")
set_number = models.PositiveSmallIntegerField(default=0)
spo2 = models.PositiveSmallIntegerField(default=0)
hr = models.PositiveSmallIntegerField(default=0)
physical_level = models.PositiveSmallIntegerField(default=0)
breath_level = models.PositiveSmallIntegerField(default=0)
sys = models.PositiveSmallIntegerField(default=0)
dia = models.PositiveSmallIntegerField(default=0)
misc_input = models.PositiveSmallIntegerField(default=0)
def __str__(self):
return self.exercise.name
My Exercise listView include the Data form that the User need to fill up, It is paginated to 1 exercise per page.
Exercise ListView:
# Exercise list inside each program + Data form
class ExerciseListView(LoginRequiredMixin, FormMixin, ListView):
model = Exercise
context_object_name = 'exercises'
form_class = DataForm
paginate_by = 1
def get_queryset(self):
program_num = get_object_or_404(Program, pk=self.kwargs.get('pk'))
return Exercise.objects.filter(program=program_num)
def form_valid(self, dataform):
program_num = get_object_or_404(Program, pk=self.kwargs.get('pk'))
exercises = Exercise.objects.filter(program=program_num)
for exe in exercises:
dataform.instance.exercise = exe.pk
print(dataform.instance.exercise)
return super(ExerciseListView, self).form_valid(dataform)
# Submit the Data form and redirect to the same page exercise
def add_data(request):
page = request.GET.get('page')
page = '?page={}'.format(page) if page else ''
if request.method == "POST":
form = DataForm(request.POST)
if form.is_valid():
data = form.save()
return redirect(reverse('program-detail', kwargs={'pk': data.exercise.program.pk}) + page)
forms.py:
class DataForm(forms.ModelForm):
class Meta:
model = Data
fields = ['set_number', 'spo2', 'hr']
I didn't add all the fields because it is too long for test stage.
template.py:
{% extends "program/base.html" %}
{% load crispy_forms_tags %}
{% block content %}
<h3> Program Exercises List </h3>
{% for exercise in exercises %}
<article class="media content-section">
<div class="media-body">
<div class="article-metadata">
{% if user.is_superuser %}
<a class="btn btn-secondary btn-sm mt-1 mb-1" href="{% url 'exercise-update' exercise.id %}">Update</a>
<a class="btn btn-danger btn-sm mt-1 mb-1" href="{% url 'exercise-delete' exercise.id %}">Delete</a>
<p class="article-content">{{ exercise.name }}</p>
{% else %}
<p class="article-content">{{ exercise.name }}</p>
{% endif %}
</div>
<div class="article-metadata">
<p class="article-content">{{ exercise.description }}</p>
<p class="article-content">{{ exercise.breath_method}}</p>
<p class="article-content">{{ exercise.recovery_method }}</p>
<p class="article-content">{{ exercise.measure_method }}</p>
<p class="article-content">{{ exercise.load_share }}</p>
<p class="article-content">{{ exercise.notes }}</p>
<p class="article-content">{{ exercise.extra_info }}</p>
<p class="article-content">{{ exercise.reps }}</p>
<p class="article-content">{{ exercise.sets }}</p>
</div>
<form action="{% url 'data-submit' %}{%if request.GET.page%}?page={{request.GET.page}}{%endif%}" method="POST" enctype="multipart/form-data">
{% csrf_token %}
<fieldset class="form-group">
<legend class="border-bottom mb-4">Exercise Measurements</legend>
{{ form|crispy }}
</fieldset>
<div class="form-group">
<button class="btn btn-outline-info" type="submit">Save</button>
</div>
</form>
</div>
</article>
{% endfor %}
{% if is_paginated %}
{% if page_obj.has_previous %}
<a class="btn btn-outline-info mb-4" href="?page={{ page_obj.previous_page_number }}">Previous Exercise</a>
{% endif %}
{% if page_obj.has_next %}
<a class="btn btn-outline-info mb-4" href="?page={{ page_obj.next_page_number }}">Next Exercise</a>
{% else %}
<a class="btn btn-outline-info mb-4" href="{% url 'web-home' %}">Exit</a>
{% endif %}
{% endif %}
{% endblock content %}
The instances I am trying to pass (in the Data form) without the user input are:
exercise - each Data form will be connect to an exercise in the database. as I mention before, the exercises are paginated 1 per page, maybe its something i can use?
I tried to solve it by that way:
def form_valid(self, dataform):
program_num = get_object_or_404(Program, pk=self.kwargs.get('pk'))
exercises = Exercise.objects.filter(program=program_num)
for exe in exercises:
dataform.instance.exercise = exe.pk
print(dataform.instance.exercise)
return super(ExerciseListView, self).form_valid(dataform)
It didn't work, I am still receiving id error for this instance.
set_number - each exercise as few sets. what I want to build is that:
the exercise as "sets" that define the number of sets the user need to perform. I want to set a "for" loop that count the number of sets and pass this instance "set_number" accordingly.
Each time the user submit the form, it will have an exercise and set_number.
Thanks!

How to show filtered items only after adding to cart on home page in django?

i am practicing django by making an ecommerce app. I also share the video so that you can also check the problem.
https://youtu.be/crYlZ7Bo8y4
Application is working perfectly but when i filter the product according to selected category and press add to cart button then it will show all products of all categories instead of showing selected products under that category.
Can you please help me out in this.
index.html page:
{% extends 'base.html' %}
{% block content %}
{% load cart %}
{% load custom_filter %}
<!-- body -->
<div class="container-fluid mt-3">
<div class="row">
<!-- filter -->
<div class="col-lg-3 mx-auto">
<div class="list-group">
All Products
{% for category in categories %}
<a href="/?category={{category.id}}"
class="list-group-item list-group-item-action">{{category.name}}</a>
{% endfor %}
</div>
</div>
<!-- all products -->
<div id='products' class="col-lg-9 mx-auto">
<div class="row mx-auto">
{% for product in products %}
<div class="card mx-auto mb-3" id={{product.id}} style="width: 18rem;">
<img class="card-img-top" src="{{product.image.url}}" alt="Card image cap">
<div class="card-body">
<p class="card-title">{{product.name}}</p>
<p class="card-text"><b>{{product.price|currency}}</b></p>
<!-- {{product | is_in_cart:request.session.cart }} -->
</div>
<div class="card-footer p-0 no-gutters">
{% if product|is_in_cart:request.session.cart %}
<div class="row no-gutters">
<form action="/#{{product.id}}" class="col-2 " method="post">
{% csrf_token %}
<input hidden type="text" name='product' value='{{product.id}}'>
<input hidden type="text" name='remove' value='True'>
<input type="submit" value=" - " class="btn btn-block btn-light border-right">
</form>
<div class="text-center col">{{product|cart_quantity:request.session.cart}} in Cart</div>
<form action="/#{{product.id}}" class="col-2 " method="post">
{% csrf_token %}
<input hidden type="text" name='product' value='{{product.id}}'>
<input type="submit" value=" + " class="btn btn-block btn-light border-left">
</form>
</div>
{% else %}
<form action="/#{{product.id}}" method="POST" class="btn-block">
{% csrf_token %}
<input hidden type="text" name='product' value='{{product.id}}'>
<input type="submit" class="float-right btn btn-light form-control"
value="Add To Cart">
</form>
{% endif %}
</div>
</div>
{% endfor %}
</div>
</div>
</div>
</div>
{% endblock %}
index.py:
from django.shortcuts import render , redirect , HttpResponseRedirect
from user.models.product import Product
from user.models.category import Category
from django.views import View
# Create your views here.
class Index(View):
def post(self , request):
product = request.POST.get('product')
remove = request.POST.get('remove')
cart = request.session.get('cart')
if cart:
quantity = cart.get(product)
if quantity:
if remove:
if quantity<=1:
cart.pop(product)
else:
cart[product] = quantity-1
else:
cart[product] = quantity+1
else:
cart[product] = 1
else:
cart = {}
cart[product] = 1
request.session['cart'] = cart
print('cart', request.session['cart'])
return redirect('user:homepage')
def get(self , request):
return HttpResponseRedirect(f'/store{request.get_full_path()[1:]}')
def store(request):
cart = request.session.get('cart')
if not cart:
request.session['cart'] = {}
products = None
categories = Category.get_all_categories()
categoryID = request.GET.get('category')
if categoryID:
products = Product.get_all_products_by_categoryid(categoryID)
else:
products = Product.get_all_products();
data = {}
data['products'] = products
data['categories'] = categories
print('you are : ', request.session.get('email'))
return render(request, 'index.html', data)
urls.py:
from django.urls import path
from .views.index import Index,store
from .views.signup import Signup
from .views.login import Login,logout
app_name = 'user'
urlpatterns = [
path('', Index.as_view(), name='homepage'),
path('store', store, name='store'),
path('signup', Signup.as_view(), name='signup'),
path('login', Login.as_view(), name='login'),
path('logout', logout, name='logout'),
]
cart.py template tag:
from django import template
register = template.Library()
#register.filter(name='is_in_cart')
def is_in_cart(product , cart):
keys = cart.keys()
for id in keys:
if int(id) == product.id:
return True
return False;
#register.filter(name='cart_quantity')
def cart_quantity(product , cart):
keys = cart.keys()
for id in keys:
if int(id) == product.id:
return cart.get(id)
return 0;
#register.filter(name='price_total')
def price_total(product , cart):
return product.price * cart_quantity(product , cart)
#register.filter(name='total_cart_price')
def total_cart_price(products , cart):
sum = 0 ;
for p in products:
sum += price_total(p , cart)
return sum
Custom_filter.py template tag:
from django import template
register = template.Library()
#register.filter(name='currency')
def currency(number):
return "₹ "+str(number)
#register.filter(name='multiply')
def multiply(number , number1):
return number * number1
referer = request.META['HTTP_REFERER']
return redirect(referer)
You can get the referring page of request instead of redirecting a constant link.You can also check META

Resources