Related
I am trying to create a edit form to update the database using Django model Forms but the problem is that edit form part of the sizeProductMap.html page is not rendering when edit form (sizeProductMap_edit) request is made.
My models are as shown below.
models.py
class Product(models.Model):
prod_ID = models.AutoField("Product ID", primary_key=True)
prod_Name = models.CharField("Product Name", max_length=30, null=False)
prod_Desc = models.CharField("Product Description", max_length=2000, null=False)
prod_Price = models.IntegerField("Product Price/Piece", default=0.00)
prod_img = models.ImageField("Product Image", null=True)
def __str__(self):
return "{}-->{}".format(self.prod_ID,
self.prod_Name)
class Size(models.Model):
size_id = models.AutoField("Size ID", primary_key=True, auto_created=True)
prod_size = models.CharField("Product Size", max_length=20, null=False)
def __str__(self):
return "{size_id}-->{prod_size}".format(size_id=self.size_id,
prod_size=self.prod_size)
class SizeProductMapping(models.Model):
size_p_map_id = models.AutoField("Size & Product Map ID", primary_key=True, auto_created=True)
size_id = models.ForeignKey(Size, null=False, on_delete=models.CASCADE, verbose_name="Size ID")
prod_id = models.ForeignKey(Product, null=False, on_delete=models.CASCADE, verbose_name="Product Id")
def __str__(self):
return ".`. {}_____{}".format(self.size_id,
self.prod_id)
This is the form I used to add and edit the model.
forms.py
from django import forms
from user.models import SizeProductMapping
class SizeProductMapForm(forms.ModelForm):
class Meta:
model = SizeProductMapping
fields = ['size_id', 'prod_id']
Here is the view I created to add ,update and delete the record.
views.py
def sizeProductMap(request):
form = SizeProductMapForm(request.POST, request.FILES)
if request.method == 'POST':
if form.is_valid():
form.save()
return redirect("/admin1/sizeProductMap/")
else:
sizeProductMap_show = SizeProductMapping.objects.all()
# start paginator logic
paginator = Paginator(sizeProductMap_show, 3)
page = request.GET.get('page')
try:
sizeProductMap_show = paginator.page(page)
except PageNotAnInteger:
sizeProductMap_show = paginator.page(1)
except EmptyPage:
sizeProductMap_show = paginator.page(paginator.num_pages)
# end paginator logic
return render(request, 'admin1/sizeProductMap.html', {'sizeProductMap_show': sizeProductMap_show, 'form': form})
def sizeProductMap_delete(request, id):
sizeProductMap_delete = SizeProductMapping.objects.filter(size_p_map_id=id)
sizeProductMap_delete.delete()
return redirect('/admin1/productSizeMap')
def sizeProductMap_edit(request, id):
instance = SizeProductMapping.objects.get(size_p_map_id=id)
form = SizeProductMapForm(instance=instance)
if request.method == 'POST':
form = SizeProductMapForm(request.POST, instance=instance)
if form.is_valid():
form.save()
return redirect('/admin1/sizeProductMap')
return render(request, 'admin1/sizeProductMap.html', {'form': form})
This is my urls.
urls.py
from django.urls import path
from admin1 import views
urlpatterns = [
path('sizeProductMap/', views.sizeProductMap, name="admin-size-product-map"),
path('sizeProductMap_delete/<int:id>', views.sizeProductMap_delete, name="admin-size-product-map-delete"),
path('sizeProductMap_edit/<int:id>', views.sizeProductMap_edit, name="admin-size-product-map-edit"),
]
This is the Html page where I want to display the form according to the page request.
sizeProductMap.html
{% extends 'admin1/layout/master.html' %}
{% block title %}Size Product Map{% endblock %}
{% block main %}
<h1>
<center>Size Product Map</center>
</h1>
<div class="container">
<div class="row">
<div class="col-lg-2"></div>
<div class="col-lg-10">
{% if sizeProductMap_show %}
<button type="button" class="btn btn-primary mt-2" data-toggle="modal" data-target="#modal-primary">Add
Size Product Mapping
</button>
<div class="modal fade" id="modal-primary">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Add Size Product Mapping</h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span></button>
</div>
<div class="modal-body mt-2">
<form action="{% url 'admin-size-product-map'%}" method="POST"
enctype="multipart/form-data">
{% csrf_token %}
<table border="1" class="table table-bordered border border-info">
<tr>
<th>
{{form.size_id.label_tag}}
</th>
<td>{{form.size_id}}</td>
</tr>
<tr>
<th>
{{form.prod_id.label_tag}}
</th>
<td>
{{form.prod_id}}
</td>
</tr>
</table>
<input type="Submit" name="Submit" value="Submit" class="btn btn-success w-50"><br>
<div class="modal-footer justify-content-between">
<button type="button" class="btn btn-outline-light" data-dismiss="modal">Close
</button>
</div>
</form>
</div>
</div>
<!-- /.modal-content -->
</div>
<!-- /.modal-dialog -->
</div>
<!-- /.modal -->
<div class="container-fluid ">
<div class="row">
<div class="card mt-2 border border-secondary">
<div class="card-header">
<h3 class="card-title ">Size Product Map Table</h3>
</div>
<!-- /.card-header -->
<div class="card-body">
<table class="table table-bordered border border-info">
<thead>
<tr>
<th>Size Product Mapping Id</th>
<th>Product ID</th>
<th>Size ID</th>
<th>Action</th>
</tr>
</thead>
<tbody class="justify-content-center">
{% for x in sizeProductMap_show %}
<tr>
<td>{{x.size_p_map_id}}</td>
<td>{{x.prod_id}}</td>
<td>{{x.size_id}}</td>
<td><a href="{% url 'admin-size-product-map-edit' x.size_p_map_id %}"
class="btn btn-outline-primary mt-2"><i
class="fa fa-pencil-square-o" aria-hidden="true"></i></a>
<a href="{% url 'admin-size-product-map-delete' x.size_p_map_id %}"
class="btn btn-outline-danger mt-2"><i
class="fa fa-trash" aria-hidden="true"></i></a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<!-- /.card-body -->
<div class="card-footer clearfix ">
<ul class="pagination pagination-sm m-0 justify-content-center">
{% if sizeProductMap_show.has_previous %}
<li class="page-item"><a class="page-link"
href="?page={{sizeProductMap_show.previous_page_number}}">
Previous </a>
</li>
{% endif%}
{% for x in sizeProductMap_show.paginator.page_range %}
{% if sizeProductMap_show.number == x %}
<li class="page-item active"><a class="page-link" href="?page={{x}}">{{x}}</a></li>
{% else%}
<li class="page-item"><a class="page-link" href="?page={{x}}">{{x}}</a></li>
{% endif %}
{% endfor %}
{% if sizeProductMap_show.has_next %}
<li class="page-item"><a class="page-link"
href="?page={{sizeProductMap_show.next_page_number}}">
Next </a>
</li>
{% endif %}
</ul>
</div>
</div>
<!-- /.card -->
</div>
</div>
{% endif %}
{% if sizeProductMap_edit %}
<form action="{% url 'admin-size-product-map-edit' x.size_p_map_id %}" method="POST">
{% csrf_token %}
{{form.size_id}}
{{form.prod_id}}
</form>
{% endif %}
</div>
</div>
</div>
{% endblock %}
And if it is possible to reduce the number of line of code please also help. Thanks in advance.
I've found out the answer. There was a really a silly mistake by me.
In the sizeProductMap.html there is a mistake let me point out that:
sizeProductMap.html
{% if sizeProductMap_edit %}
<form action="{% url 'admin-size-product-map-edit' x.size_p_map_id %}" method="POST">
{% csrf_token %}
{{form.size_id}}
{{form.prod_id}}
</form>
{% endif %}
Here I am checking for instance {% if sizeProductMap_edit %} this is the wrong thing.
I have to check {% if instance %} according to my views.py.
I am a newbie, and I am working on a website. On this website I have created admin panel to manage different products and attributes .
I have a page named size.html and and I am supposed to change it name and make it productAtributes.html and on this single page I want to do all add, update, delete operations for different Product attributes.
My code is as:
models.py
class Product(models.Model):
prod_ID = models.AutoField("Product ID", primary_key=True)
prod_Name = models.CharField("Product Name", max_length=30, null=False)
prod_Desc = models.CharField("Product Description", max_length=2000, null=False)
prod_Price = models.IntegerField("Product Price/Piece", default=0.00)
prod_img = models.ImageField("Product Image", null=True)
def __str__(self):
return "{}-->{}".format(self.prod_ID,
self.prod_Name)
class Size(models.Model):
size_id = models.AutoField("Size ID", primary_key=True, auto_created=True)
prod_size = models.CharField("Product Size", max_length=20, null=False)
def __str__(self):
return "{size_id}-->{prod_size}".format(size_id=self.size_id,
prod_size=self.prod_size)
class Color(models.Model):
color_id = models.AutoField("Color ID", primary_key=True, auto_created=True)
prod_color = models.CharField("Product Color", max_length=50, null=False)
def __str__(self):
return "{color_id}-->{prod_color}".format(color_id=self.color_id,
prod_color=self.prod_color)
class PaperChoice(models.Model):
paper_id = models.AutoField("Paper Choice ID", primary_key=True, auto_created=True)
paper_choices_name = models.CharField("Paper Choices", max_length=50, null=False)
def __str__(self):
return "{}-->{}".format(self.paper_id,
self.paper_choices_name)
views.py
from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage
from django.shortcuts import render, redirect
from user.models import *
def size(request):
if request.method == 'POST':
size_store = request.POST['prod_size']
size_update = Size(prod_size=size_store)
size_update.save()
return redirect('/admin1/productSize')
else:
size_show = Size.objects.all()
# start paginator logic
paginator = Paginator(size_show, 3)
page = request.GET.get('page')
try:
size_show = paginator.page(page)
except PageNotAnInteger:
size_show = paginator.page(1)
except EmptyPage:
size_show = paginator.page(paginator.num_pages)
# end paginator logic
return render(request, 'admin1/size.html', {'size_show': size_show})
def size_edit(request, id):
size_edit = Size.objects.filter(size_id=id)
return render(request, 'admin1/size.html', {'size_edit': size_edit})
def size_edit_update(request, id):
if request.method == 'POST':
size_store = request.POST['prod_size']
size_update = Size(size_id=id, prod_size=size_store)
size_update.save()
return redirect('/admin1/productSize')
def size_delete(request, id):
size_deletee = Size.objects.filter(size_id=id)
size_deletee.delete()
return redirect('/admin1/productSize')
As I created add, update, delete functionality for Size I am going to do it same with color and Papaer choice.
size.html
{% extends 'admin1/layout/master.html' %}
{% block title %}Size{% endblock %}
{% block main %}
<h1>
<center>Size</center>
</h1>
<div class="container">
<div class="row">
<div class="col-lg-2"></div>
<div class="col-lg-10">
<button type="button" class="btn btn-primary mt-2" data-toggle="modal" data-target="#modal-primary">Add
Size
</button>
<div class="modal fade" id="modal-primary">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Add Product Size</h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span></button>
</div>
<div class="modal-body mt-2">
<form action="{% url 'admin-product-size'%}" method="POST" enctype="multipart/form-data">
{% csrf_token %}
<label>Product Size:</label>
<input type="text" name="prod_size" class="form-control w-50"><br>
<br>
<input type="Submit" name="Submit" value="Submit" class="btn btn-success w-50"><br>
<div class="modal-footer justify-content-between">
<button type="button" class="btn btn-outline-light" data-dismiss="modal">Close
</button>
</div>
</form>
</div>
</div>
<!-- /.modal-content -->
</div>
<!-- /.modal-dialog -->
</div>
<!-- /.modal -->
<br>
{% if size_show %}
<div class="container-fluid ">
<div class="row">
<div class="card mt-2 border border-secondary">
<div class="card-header">
<h3 class="card-title ">Product Table</h3>
</div>
<!-- /.card-header -->
<div class="card-body">
<table class="table table-bordered border border-info">
<thead>
<tr>
<th>Product Id</th>
<th>Product Size</th>
</tr>
</thead>
<tbody class="justify-content-center">
{% for x in size_show %}
<tr>
<td>{{x.size_id}}</td>
<td>{{x.prod_size}}</td>
<td><a href="/admin1/size_edit/{{x.size_id}} "
class="btn btn-outline-primary mt-2"><i
class="fa fa-pencil-square-o" aria-hidden="true"></i></a>
<a href="/admin1/size_delete/{{x.size_id}}"
class="btn btn-outline-danger mt-2"><i
class="fa fa-trash" aria-hidden="true"></i></a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<!-- /.card-body -->
<div class="card-footer clearfix ">
<ul class="pagination pagination-sm m-0 justify-content-center">
{% if size_show.has_previous %}
<li class="page-item"><a class="page-link"
href="?page={{size_show.has_previous_page_number}}">
Previous </a>
</li>
{% endif%}
{% for x in size_show.paginator.page_range %}
{% if size_show.number == x %}
<li class="page-item active"><a class="page-link" href="?page={{x}}">{{x}}</a></li>
{% else%}
<li class="page-item"><a class="page-link" href="?page={{x}}">{{x}}</a></li>
{% endif %}
{% endfor %}
{% if size_show.has_next %}
<li class="page-item"><a class="page-link"
href="?page={{size_show.has_next_page_number}}"> Next </a>
</li>
{% endif %}
</ul>
</div>
</div>
<!-- /.card -->
</div>
</div>
{% endif %}
{% if size_edit %}
{% for x in size_edit %}
<form action="/admin1/size_data_update/{{x.size_id}}" method="POST">
{% csrf_token %}
<label>Size Name:</label>
<input type="text" name="prod_size" value="{{x.prod_size}}" class="form-control w-50"><br>
<input type="Submit" name="Submit" value="Submit" class="btn btn-success w-50"><br>
</form>
{% endfor %}
{% endif %}
</div>
</div>
</div>
{% endblock %}
For performing oertions of views.py I have created size.html .Nut there around 10 to 12 product attributes ,and for that attributes I don't want to create seprate html pages.
I want to do all the operations for all the attributes in single html page. Is it possible?
Means according to the atrribut type request the page data should change dynamically, I do not have to create seprate template pages for each attribute.
You need to make the form in your views, not the Templates, I'm not sure if this is best practise but it's the only way I see you can do this, (using Class-Based Views would simplify this process a lot) but if you want to stick to functions, this is what you do.
Let's take an input line:
<label>Product Size:</label>
<input type="text" name="prod_size" class="form-control w-50"><br>
Let's use Django's tags and turn it into this:
<label>{{form.display_name}}:</label>
<input type="text" name="{{form.name}}" class="form-control w-50">
The class will probably be the same but you could extend the same functionality to the class or type fields.
In the backend, you want to make a list of all the elements you want to show, with nested dictionaries:
forms = [ # Each form
[ # Each field within the form, this way, you can have a different amount each time
{'display_name': 'Product Size', # label Display name
'name': 'prod_size'}, # name tag value
{'display_name': "it's value", # This is a different field
'name': 'just an example'}
],
]
Then you can do a for loop in the templates:
{% for form in forms %}
{$ for field in form %}
<label>{{field.display_name}}:</label>
<input type="text" name="{{field.name}}" class="form-control w-50">
I'm not exactly sure what you're trying to do in your code, so I didn't make this example too specific, but hopefully, it will give you inspiration to get you on the right track, if you need more help, just ask
In my view, I have a model that returns all instances of a model that has a foreign key to user. This view renders a profile page where the model.user is checked against the request.user, if it matches, it prints out information on that model on the profile page.
This is what I have in my views.:
#login_required(login_url='loginpage_company')
#allowed_users_company(allowed_roles=['company'])
def profile_company(request):
print(request.user)
companies = Company.objects.all()
responses = Response.objects.all()
context = {
'companies': companies,
#'company_reviews': company_reviews,
#'total_reviews': total_reviews,
'responses': responses,
'info': "No company claimed yet",
'infor': 'Not Available',
}
return render(request, 'companyusers/profile_company.html', context)
for my models I have the following.
class Company(models.Model):
Online_Merchant = 'merch'
Education = 'edu'
Transportation = 'trans'
Hospitalism = 'hosp'
Healthcare = 'health'
Construction = 'const'
Blog = 'blog'
Finance = 'fin'
Media = 'media'
Government_Agency = 'agency'
Other = 'other'
Manufacturing = 'manufacturing'
sector = [
(Online_Merchant, 'Online Merchant'),
(Education, 'Education'),
(Transportation, 'Transportation'),
(Hospitalism, 'Hospitalism'),
(Healthcare, 'Healthcare'),
(Construction, 'Construction'),
(Blog, 'Blog'),
(Finance, 'Finance'),
(Media, 'Media'),
(Manufacturing, 'Manufacturing'),
(Government_Agency, 'Government Agency'),
(Other, 'Other')
]
Free = 'Free'
Premium = 'Premium'
package = [
(Free, 'Free'),
(Premium, 'Premium')
]
Abuja = 'Abuja'
Abia = 'Abia'
Adamawa = 'Adamawa'
Akwa_Ibom = 'Akwa Ibom'
Anambra = 'Anambra'
Bauchi = 'Bauchi'
Bayelsa = 'Bayelsa'
Benue = 'Benue'
Borno = 'Borno'
Cross_River = 'Cross River'
Delta = 'Delta'
Ebonyi = 'Ebonyi'
Edo = 'Edo'
Ekiti = 'Ekiti'
Enugu = 'Enugu'
Gombe = 'Gombe'
Imo = 'Imo'
Jigawa = 'Jigawa'
Kaduna = 'Kaduna'
Kano = 'Kano'
Katsina = 'Katsina'
Kebbi = 'Kebbi'
Kogi = 'Kogi'
Kwara = 'Kwara'
Lagos = 'Lagos'
Nasarawa = 'Nasarawa'
Niger = 'Niger'
Ogun = 'Ogun'
Ondo = 'Ondo'
Osun = 'Osun'
Oyo = 'Ibadan'
Plateau = 'Plateau'
Rivers = 'Rivers'
Sokoto = 'Sokoto'
Taraba = 'Taraba'
Yobe = 'Yobe'
Zamfara = 'Zamfara'
state = [
(Abuja, 'Abuja'),
(Abia, 'Abia'),
(Adamawa, 'Adamawa'),
(Akwa_Ibom, 'Akwa Ibom'),
(Anambra, 'Anambra'),
(Bauchi, 'Bauchi'),
(Bayelsa, 'Bayelsa'),
(Benue, 'Benue'),
(Borno, 'Borno'),
(Cross_River, 'Cross River'),
(Delta, 'Delta'),
(Ebonyi, 'Ebonyi'),
(Edo, 'Edo'),
(Ekiti, 'Ekiti'),
(Enugu, 'Enugu'),
(Gombe, 'Gombe'),
(Imo, 'Imo'),
(Jigawa, 'Jigawa'),
(Kaduna, 'Kaduna'),
(Kano, 'Kano'),
(Katsina, 'Katsina'),
(Kebbi, 'Kebbi'),
(Kogi, 'Kogi'),
(Kwara, 'Kwara'),
(Lagos, 'Lagos'),
(Nasarawa, 'Nasarawa'),
(Niger, 'Niger'),
(Ogun, 'Ogun'),
(Ondo, 'Ondo'),
(Osun, 'Osun'),
(Oyo, 'Ibadan'),
(Plateau, 'Plateau'),
(Rivers, 'Rivers'),
(Sokoto, 'Sokoto'),
(Taraba, 'Taraba'),
(Yobe, 'Yobe'),
(Zamfara, 'Zamfara')
]
user = models.ForeignKey(User, null=True, blank=True, on_delete=models.SET_NULL, verbose_name='Company User')
company_sector = models.CharField(max_length=30, choices=sector, default=Online_Merchant)
company_name = models.CharField(max_length=100)
company_description = models.TextField()
company_logo = models.ImageField(upload_to='company_logos', blank=True, null=True)
company_state = models.CharField(max_length=30, choices=state, default=Lagos)
company_address = models.TextField(max_length=2000)
average_rating = models.IntegerField(default=0)
total_views = models.IntegerField(default=0)
company_website = models.CharField(max_length=500, blank=True, null=True)
company_email = models.EmailField(max_length=500, blank=True, null=True)
company_phone = models.CharField(max_length=500)
package_chosen = models.CharField(max_length=8, choices=package, default=Free)
featured = models.BooleanField(default=False)
advert = models.BooleanField(default=False)
premium = models.BooleanField(default=False)
def __str__(self):
return self.company_name
This is what I have in the template:
{% extends 'base.html' %}
{% load static %}
{% load crispy_forms_tags %}
{% include "nav_bar.html" %}
{% block greeting %}
<li class="nav-item" >
<a class="nav-link font-weight-bold" href="{% url 'contact' %}"><i class="fas fa-envelope" style="font-size:20px; padding-right: 4px; color:#2196F3"></i>Contact Us</a>
</li>
{% endblock greeting %}
{% block section %}
<section class="mt-2 bg-white mx-2">
<div class="container-fluid border-0 text-justify">
<div class="row">
<span class="font-weight-bold px-2 py-1 mx-auto text-danger">...Created with<span class="h3"> ♥</span>... Because we understand that behind every review, there is a hearty experience...</span>
</div>
<div class="row mx-2">
<div class="col-md-5 mb-2">
<div class="card" style="width: 23rem;">
<img src="{{request.user.userprofilecompany.profile_photo.url}}" class="card-img-top" alt="profile picture">
<div class="card-body">
<h5 class="card-title">Company Name: {{request.user.userprofilecompany.company_name}}</h5>
<p class="card-text">Username: {{request.user.username}} </br><span class="font-weight-sm">this is publicly visible</span></p>
<p class="card-text">Fullname: {{request.user.last_name}}, {{request.user.first_name}}</p>
<p class="card-text">Designation: {{request.user.userprofilecompany.designation}}</p>
<p class="card-text">Email: {{request.user.email}}</p>
<p class="card-text">Phone: {{request.user.userprofilecompany.phone}}</p>
<p class="card-text">Location: {{request.user.userprofilecompany.location}}</p>
<p class="card-text">Package: {{request.user.userprofilecompany.package}} Upgrade</p>
<p class="card-text"></p>
Go to Settings</br>
<p class="card-text"></p>
Logout</br>
</div>
</div>
</div>
{% for company in companies %}
{% if company.user == request.user %}
<div class="col-md mb-2">
<div class="row">
<div class="col-md mb-2">
<div class="card text-center mb-3">
<div class="card-header text-white bg-info">
<h5 class="card-title">Total Reviews</h5>
</div>
<div class="card-body">
<h3 class="card-title"></h3>
</div>
<div class="card-body">
<h3 class="card-title"></h3>
</div>
<div class="card-body">
<h3 class="card-title">{{ company.review_set.all.count }}</h3>
</div>
<div class="card-body">
<h3 class="card-title"></h3>
</div>
<button class="btn btn-info font-weight-bold btn-sm" id="tm-reviews">View Reviews and Responses</button>
</div>
</div>
<div class="col-md mb-2">
<div class="card mb-3" >
<div class="card-header text-center text-white bg-info">
<h5 class="card-title ">Statistics</h5>
</div>
<div class="py-2 font-weight-bold px-2">
<p class="card-text">Average Rating: | <i id="tm-average_rating">{{company.average_rating}}</i><i>/5</i> </p>
<p class="card-text">Remarks: | <i id="tm-remarks" class=""></i></p>
<p class="card-text">Total Likes: | like count number</p>
<p class="card-text">Total Dislikes: | dislike count number</p>
<p class="card-text">Average Rating: | 4/5 </p>
<p class="card-text">Remarks: | Satisfactory</p>
<p class="card-text">Total Views: | 10</p>
<p class="card-text"><h6 class=" font-weight-bold">Claimed Company: <span class= "text-primary"><a class="text-decoration-none" href="{% url 'detail' company.id %}" target="_blank"> {{company.company_name}} </a> </span> </h5></p>
</div>
<button class="btn btn-info font-weight-bold btn-sm" id="tm-reviews">Click to Get Noticed</button>
</div>
</div>
</div>
<div class="row" id="tm-display-reviews">
<div class="col-md mb-2">
<div style="font-size: small;" class="card text-center mb-3">
<div class="card-header text-white bg-info">
<h5 class="card-title">Details</h5>
</div>
<div class="card-body">
{% for review in company.review_set.all %}
<div class=" py-2">
<p class="card-text ">Name: {{review.user | capfirst }} Rating: {{review.rating}}/5 | Date added: <span class="text-danger"> {{ review.date_added }}</span></p>
<p class="card-text"> Review: {{review.review_text}} </p>
<!-- check to see if there is a reponse under this review to know whether
to show the button -->
{% for response in review.response_set.all %}
{% empty %}
<p class="card-text"><button id="tm-respond" class="btn btn-outline-primary font-weight-bold btn-sm">respond to this review</button></p>
{% endfor %}
{% for response in responses%}
{% if response.review == review %}
<p class="card-text bg-light font-italic">{{response.review.company | capfirst }} responded: {{response}} on: {{response.date_added}}</p>
<hr>
{% endif %}
{% endfor %}
{% endfor %}
</div>
</div>
</div>
</div>
</div>
</div>
{% endif %}
{% endfor %}
<div class="col-md mb-2">
<!-- The problem is here. It seems to rund the code over and over again-->
{% for company in companies %}
{% if company.user != request.user%}
<div class="row">
<div class="col-md mb-2">
<div class="card text-center mb-3">
<div class="card-header text-white bg-info">
<h5 class="card-title">Total Reviews</h5>
</div>
<div class="card-body">
<p class="card-text"> You have not claimed a company yet.</p>
<p class="card-text"> You need to claim a company to view its statistis here.</p>
<p class="card-text"> You need to have your company listed to claim it.</p>
<p class="card-text"> If your company is already listed on our site, kindly email us on:</p>
<p class="card-text"> info#crediblereviews.ng</p>
</div>
</div>
</div>
<div class="col-md mb-2">
<div class="card mb-3" >
<div class="card-header text-center text-white bg-info">
<h5 class="card-title ">Statistics</h5>
</div>
<div class="py-2 font-weight-bold px-2">
<p class="card-text">Average Rating: | <i id="tm-average_rating">{{infor}}</i> </p>
<p class="card-text">Remarks: | <i id="tm-remarks" class="">{{infor}}</i></p>
<p class="card-text">Total Likes: | {{infor}}</p>
<p class="card-text">Total Dislikes: | {{infor}}</p>
<p class="card-text">Average Rating: | {{infor}} </p>
<p class="card-text">Remarks: | {{infor}}</p>
<p class="card-text">Total Views: | {{infor}}</p>
<p class="card-text"><h6 class=" text-warning font-weight-bold">{{info}}: <span style="font-size: small;" class= "text-info"> Email us to claim a company </span> </h5></p>
</div>
<button class="btn btn-info font-weight-bold btn-sm" id="tm-reviews">Click to Get Noticed</button>
</div>
</div>
</div>
{% endif %}
{% endfor %}
<!---->
</div>
</div>
</div>
</section>
{% endblock section %}
{% block article %}
{% endblock article %}
The problem is the last loop it seems to print the code as many times as there are instances of the model that doesnt match the condition. This is not what I want. I want to be able to check if request.user is not equal to company.user and print the last division. Thanks so much for the help...
It is a misuse of Django framework to do data filtering in the templates. As it is a simple filtering (or data routing) you can simply filter the unwanted campaigns out by using campaigns.filter(user=request.user) instead of campaigns while creating your context.
Thank you Ali for your help. but selecting where user=request.user would raise an exception saying: reference before assignment. I tried the try and except block for this no way.
I finally used javascript to solve the issue. In the model for my users, I inserted a boolean field. Javascript will now check for this field to know whether to hide or show the division. It works just fine the way I want it.
I find myself repeatedly cycling through the same set of data, accessing database several time for the same loops to achieve displaying the correct data on one template, here's the code:
<!-- item images and thumbnails -->
<div class="row">
<div class="col-12 col-sm-8">
<div id="item{{item.pk}}Carousel" class="carousel slide" data-ride="carousel">
<ol class="carousel-indicators">
{% for image in item.itemimage_set.all %}
<li data-target="#item{{item.pk}}Carousel" data-slide-to="{{forloop.counter0}}"
{% if forloop.first %} class="active" {% endif %}></li>
{% endfor %}
</ol>
<div class="carousel-inner shadow-lg rounded-sm">
{% for image in item.itemimage_set.all %}
<div class="carousel-item {% if forloop.first %} active {% endif %}">
<img src="{{image.image.url}}" class="d-block w-100" alt="...">
</div>
{% endfor %}
</div>
{% if item.itemimage_set.count > 1 %}
<a class="carousel-control-prev" href="#item{{item.pk}}Carousel" role="button" data-slide="prev">
<span class="carousel-control-prev-icon" aria-hidden="true"></span>
<span class="sr-only">Previous</span>
</a>
<a class="carousel-control-next" href="#item{{item.pk}}Carousel" role="button" data-slide="next">
<span class="carousel-control-next-icon" aria-hidden="true"></span>
<span class="sr-only">Next</span>
</a>
{% endif %}
</div>
</div>
<div class="pl-sm-0 col-12 col-sm-4 d-flex flex-wrap align-content-start">
{% for image in item.itemimage_set.all %}
<div class="col-4
{% if item.itemimage_set.count > 3 %}
col-sm-6
{% else %}
col-sm-8
{% endif %}
mt-2 px-1 mt-sm-0 pb-sm-2 pt-sm-0 mb-0">
<img src="{{image.image.url}}" alt="" class="col-12 p-0 rounded-sm shadow-sm"
data-target="#item{{item.pk}}Carousel" data-slide-to="{{forloop.counter0}}">
</div>
{% endfor %}
</div>
</div>
<!-- /item images and thumbnails -->
The above code renders the item's itemimage bootstrap carousel and on the same page, an extra carousel modal:
<!-- itemImageModal -->
<div class="modal fade" id="itemImageModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalCenterTitle"
aria-hidden="true">
<div class="modal-dialog modal-dialog-centered col-12 col-md-8 modal-lg" role="document">
<div class="modal-content">
<div class="col-12 px-0">
<div id="itemImage{{item.pk}}Carousel" class="carousel slide" data-ride="carousel">
<ol class="carousel-indicators">
{% for image in item.itemimage_set.all %}
<li data-target="#itemImage{{item.pk}}Carousel" data-slide-to="{{forloop.counter0}}"
{% if forloop.first %} class="active" {% endif %}></li>
{% endfor %}
</ol>
<div class="carousel-inner shadow-lg rounded-sm">
{% for image in item.itemimage_set.all %}
<div class="carousel-item {% if forloop.first %} active {% endif %}">
<img src="{{image.image.url}}" class="d-block w-100" alt="...">
</div>
{% endfor %}
</div>
{% if item.itemimage_set.count > 1 %}
<a class="carousel-control-prev" href="#itemImage{{item.pk}}Carousel" role="button" data-slide="prev">
<span class="carousel-control-prev-icon" aria-hidden="true"></span>
<span class="sr-only">Previous</span>
</a>
<a class="carousel-control-next" href="#itemImage{{item.pk}}Carousel" role="button" data-slide="next">
<span class="carousel-control-next-icon" aria-hidden="true"></span>
<span class="sr-only">Next</span>
</a>
{% endif %}
</div>
</div>
</div>
</div>
</div>
Data structure:
class Item(models.Model):
name = ... etc.
class ItemImage(models.Model):
item = models.ForeignKey(Item, on_delete=models.CASCADE)
image = models.ImageField(upload_to='itemimages', null=True, blank=True)
As you can see, there are 5 forloop cycles in the template which leads to frequent queries from the database over the same set of data.
What I've tried:
I've tried to replace {% for image in item.itemimage_set.all %} with {% for image in item.load_related_itemimage %}, and in the models.py:
class Item(models.Model):
name = ...
def load_related_itemimage(self):
return self.itemimage_set.prefetch_related('image')
and this prompt error:
'image' does not resolve to an item that supports prefetching - this is an invalid parameter to prefetch_related().
I'm actually quite new to django and am not sure how to use select_related or prefetch_related but so far I've employed them and managed to reduce database query from 150 to 30+. And I think the frequency can be further reduced due to the silly cycles above as you can see.
forward the Debug Toolbar data for the page:
SELECT "appname_itemimage"."id",
"appname_itemimage"."item_id",
"appname_itemimage"."image"
FROM "appname_itemimage"
WHERE "appname_itemimage"."item_id" = '19'
5 similar queries. Duplicated 5 times.
5 similar queries. Duplicated 5 times. is bad right?
view.py
class ItemDetailView(DetailView):
'''display an individual item'''
model = Item
template_name = 'boutique/item.html'
Thanks for #Iain Shelvington's answer, his solution for the above code works like a charm, how about this:
I think they are related so I didn't separate this to raise another question -- what if the item itself is in a forloop? how to use prefetch_related in this situation? thanks!
{% for item in subcategory.item_set.all %}
<img src="{{ item.itemimage_set.first.image.url }}">
{% endfor %}
because I need to access item.itemimage_set when looping through subcateogry.item_set, and this is a much worse problem than before, because it raises 19 repetition in loading itemimage
This template is rendered by a ListView
class CategoryListView(ListView):
'''display a list of items'''
model = Category
# paginate_by = 1
template_name = 'boutique/show_category.html'
context_object_name = 'category_shown'
def get_queryset(self):
qs = super().get_queryset().get_categories_with_item()
self.gender = self.kwargs.get('gender') # reuse in context
gender = self.gender
request = self.request
# fetch filter-form data
self.category_selected = request.GET.get('category_selected')
self.brand_selected = request.GET.get('brand_selected')
self.min_price = request.GET.get('min_price')
self.max_price = request.GET.get('max_price')
if gender == 'women':
self.gender_number = 1
elif gender == 'men':
self.gender_number = 2
else:
raise Http404
get_category_selected = Category.objects.filter(
gender=self.gender_number, name__iexact=self.category_selected).first()
category_selected_pk = get_category_selected.pk if get_category_selected else None
get_subcategory_selected = SubCategory.objects.filter(
category__gender=self.gender_number, name__iexact=self.category_selected).first()
subcategory_selected_pk = get_subcategory_selected.pk if get_subcategory_selected else None
category_pk = category_selected_pk if category_selected_pk else self.kwargs.get(
'category_pk')
subcategory_pk = subcategory_selected_pk if subcategory_selected_pk else self.kwargs.get(
'subcategory_pk')
# print('\nself.kwargs:\n', gender, category_pk, subcategory_pk)
if gender and not category_pk and not subcategory_pk:
qs = qs.get_categories_by_gender(gender)
# print('\nCategoryLV_qs_gender= ', '\n', qs, '\n', gender, '\n')
return qs
elif gender and category_pk:
qs = qs.filter(pk=category_pk)
# print('\nCategoryLV_qs_category= ', '\n', qs, '\n')
return qs
elif gender and subcategory_pk:
qs = SubCategory.objects.annotate(Count('item')).exclude(
item__count=0).filter(pk=subcategory_pk)
self.context_object_name = 'subcategory_shown'
# print('\nCategoryLV_qs_sub_category= ', '\n', qs, '\n')
return qs
def get_validated_cats(self):
categories_validated = []
subcategories_validated = []
items_validated = []
brand_selected = self.brand_selected
min_price = self.min_price
if min_price == '' or min_price is None:
min_price = 0
max_price = self.max_price
if max_price == '' or max_price is None:
max_price = 999999
for item in Item.objects.select_related('category', 'subcategory', 'tag').filter(category__gender=self.gender_number):
if int(min_price) <= item.final_price < int(max_price):
if brand_selected is None or brand_selected == 'бренд' or item.brand.name == brand_selected:
items_validated.append(item)
if item.category not in categories_validated:
categories_validated.append(item.category)
if item.subcategory not in subcategories_validated:
subcategories_validated.append(item.subcategory)
return categories_validated, subcategories_validated, items_validated
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['brands'] = Brand.objects.all()
cat_valid, subcat_valid, items_valid = self.get_validated_cats()
context['filter_context'] = {
'gender': self.gender,
'gender_number': self.gender_number,
'category_selected': self.category_selected,
'brand_selected': self.brand_selected,
'min_price': self.min_price,
'max_price': self.max_price,
'categories_validated': cat_valid,
'subcategories_validated': subcat_valid,
'items_validated': items_valid,
}
# print(context)
return context
You should use prefetch_related to prefetch "itemimage_set" so that every time you access item.itemimage_set.all you get the cached result
item = get_object_or_404(Item.objects.prefetch_related('itemimage_set'), pk=pk)
For a DetailView
class ItemDetailView(DetailView):
model = Item
queryset = Item.objects.prefetch_related('itemimage_set')
I am working on a blog project and I am getting the "Matching query does not exist "error. I have tried using try block thinking that the model class might not be returning any value. Hence, modified my views.py as below:-
from django.shortcuts import render, HttpResponseRedirect
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.models import User
from django.contrib.auth.hashers import make_password
from django.db.models import Q
from .forms import *
# Create your views here.
def home(request):
print("I am home")
try:
blog_data = BlogPost.objects.all()
print("blog_data", blog_data)
except BlogPost.DoesNotExist:
blog_data = None
print("blog_data", blog_data)
try:
last_element = BlogPost.objects.filter(id = len(blog_data))[0]
print("last_element", last_element)
except BlogPost.DoesNotExist:
last_element = None
print("last_element", last_element)
tags_list = BlogPost.objects.values_list("tags", flat = True).distinct()
#tags_list = BlogPost.objects.all().distinct()
context = {'blog_data':blog_data, "last_element":last_element, "tags_list":tags_list}
#last_element = list(BlogPost.objects.all().reverse()[0])
print("last_element",last_element, "blog_data",blog_data,"context",context)
return render(request, 'blog/home.html', context)
# def home(request):
# blog_data = BlogPost.objects.all()
# context = {'blog_data':blog_data}
# print('context', context)
# last_element = BlogPost.objects.all().reverse()[0]
# #last_element = BlogPost.objects.all().reverse()[0]
# return render(request, 'blog/home.html', context)
def new_post(request):
if request.method == 'POST':
form = BlogForm(data = request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('home')
else:
form = BlogForm()
return render(request, 'blog/blogform.html', {'form':form })
def login_user(request):
username = password = ''
state = "Please log in"
if request.POST:
username = request.POST.get('Username')
password = request.POST.get('Password')
user = authenticate(username=username, password=password)
if user is not None:
if user.is_active:
login(request, user)
state = "You're successfully logged in!"
return HttpResponseRedirect('/blog/home')
else:
state = "Your account is not active, please contact the site admin."
else:
state = "Your username and/or password were incorrect."
#return render_to_response('main/login.html',{'state':state, 'username': username})
return render(request, "blog/login.html", {'state':state, 'username': username, 'next_page':"home.html"})
#return HttpResponseRedirect("home.html")
def logout_user(request):
logout(request)
return render(request,'blog/home.html')
def register_user(request):
username = password = password_again = email = ''
state = ''
if request.method == 'POST':
username = request.POST.get('Username')
password = request.POST.get('Password')
password_again = request.POST.get('Password_again')
email = request.POST.get('Email')
print('email', email)
if password == password_again:
password = make_password(password, salt = None, hasher = 'default')
else:
state = "Password and password re-entered do not match, please try again..."
return HttpResponseRedirect('login')
print("at 63")
try:
user = User.objects.get(username = username)
print('user at 67', user)
except Exception as e:
print("Error is :", e)
user = None
print("user", user)
try:
emailID = User.objects.get(email = email)
print("emailID", emailID)
except Exception as e:
print("Error is :", e)
emailID = None
print("emailID exception", emailID)
if user is not None:
state = 'Username already exists, please try another one...'
else:
if emailID is None:
new_user = User(username = username, password = password, email = email)
##Adding new logic for securityQAs vvv
#new_SQA = SecurityQA(user_email = email, security_question = security_question, security_answer = security_answer)
##Adding new logic for securityQAs ^^^
new_user.save()
#new_SQA.save()
state = 'You are successfully registered.. Thanks'
return HttpResponseRedirect('login')
else:
state = "Email ID already registered, try a new one.."
print('state at else', state)
#return HttpResponseRedirect('login')
return render(request, "blog/register.html", {'state':state, 'username':username, 'next_page':'home.html'})
def forgot_password(request):
pass
def comment_posted(request):
return render(request, "blog/comment_posted.html")
def blog_search(request):
qset = Q()
keyword = ''
keyword = request.POST.get('keyword')
print("keyword", keyword)
for word in keyword.split():
qset |= (Q(title__contains = word)|Q(description__contains = word))
print('qset', qset)
result = BlogPost.objects.filter(qset)
context = {'result':result}
return render(request, 'blog/blog_search.html', context)
Also, find my models.py below
from django.db import models
from django.contrib.auth.models import User
#from django.core.files.storage import FileSystemStorage
#fs = FileSystemStorage(location='E:\django\myblog\\blog\uploaded images')
# Create your models here.
class BlogPost(models.Model):
title = models.CharField(max_length = 30)
posted_by = models.CharField(max_length = 30)
posted_on = models.DateTimeField(auto_now_add = True)
description = models.CharField(max_length = 200)
comment = models.CharField(max_length = 150)
tags = models.CharField(max_length=50, default = "notag")
image = models.ImageField(upload_to = 'uploaded_images', default = None, null = True, blank = True)
def __str__(self):
#return "{0} : {1}".format(self.title, self.description)
return self.title
template code as below (home.html). Here I am getting the error at line "{% get_comment_list for blog.blogpost last_element.id as comment_list %}"
{% load staticfiles %}
{%load comments%}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="author" content="">
<title>Sourav's blog</title>
<!-- Bootstrap Core CSS -->
{%block styling%}
<link href="{%static 'css/bootstrap.min.css'%}" rel="stylesheet">
<!-- Custom CSS -->
<link href="{%static 'css/blog-post.css'%}" rel="stylesheet">
{%endblock styling%}
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
<script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>
<![endif]-->
</head>
<body>
<!-- Navigation -->
<nav class="navbar navbar-inverse navbar-fixed-top" role="navigation">
<div class="container">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">Ideate</a>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav">
<li>
New idea
</li>
<!-- <li>Login</li> -->
{{user.is_authenticated}}
{% if user.is_authenticated %}
<li>
Logout
</li>
{% else %}
<li>
Login
</li>
{% endif %}
<li>
Help
</li>
{% if user.is_authenticated %}
<li>
Hi {{user.username}}
</li>
{%else%}
{% endif %}
</ul>
</div>
<!-- /.navbar-collapse -->
</div>
<!-- /.container -->
</nav>
<!-- Page Content -->
<div class="container">
<div class="row">
<!-- Blog Post Content Column -->
<div class="col-lg-8">
<!-- Blog Post -->
<!-- Title -->
<h1>Idea Blog</h1>
<!-- Author -->
<p class="lead">
by Sourav
</p>
<hr>
<!-- Date/Time -->
<p><span class="glyphicon glyphicon-time"></span>
Posted on
<!-- {%for i in blog_data%}
{{i.posted_on}}
{%endfor%}</p> -->
{{last_element.posted_on}}
<hr>
<!-- Preview Image -->
<img class="img-responsive" src="http://placehold.it/900x300" alt="">
<hr>
<!-- Post Content -->
<!-- <p>Below is the result</p> -->
<!-- <p>{{blog_data}}</p> -->
<p>
<!-- {%for i in blog_data%}
<h1>{{i.title}}</h1>
<p>{{i.description}}</p>
{%empty%}
<span>No data</span>
{%endfor%} -->
<!-- {{last_element}} -->
<h1>{{last_element.title}}</h1><span> posted by {{last_element.posted_by}}</span>
<p>Description : {{last_element.description}}</p>
{{last_element.image}}
<p>Tags : {{last_element.tags}}</p>
{% get_comment_count for blog.blogpost last_element.id as comment_count %}
<p>{{ comment_count }} comments have been posted.</p>
{% get_comment_list for blog.blogpost 1 as comment_list %}
{% for comment in comment_list %}
<p>Posted by: {{ comment.user_name }} on {{ comment.submit_date }}</p>
<p>Comment: {{ comment.comment }}</p>
{% endfor %}
{% get_comment_form for blog.blogpost last_element.id as form %}
<!-- A context variable called form is created with the necessary hidden
fields, timestamps and security hashes -->
<table>
<form action="{% comment_form_target %}" method="post">
{% csrf_token %}
{{ form }}
<tr>
<td colspan="1">
<input type="submit" name="submit" value="Post">
<input type="submit" name="preview" value="Preview">
<input type="hidden" name="next" value="{% url 'comment_posted' %}" />
</td>
</tr>
</form>
</table>
{% get_comment_list for blog.blogpost last_element.id as comment_list %}
{%for comment in comment_list%}
<li><b>{{comment.name}}</b> has posted comment on {{comment.submit_date}} </li>
<ul><li>{{comment.comment}}</li></ul>
<a name="c{{ comment.id }}"></a>
<a href="{% get_comment_permalink comment %}">
see comment details
</a>
{%endfor%}
</p>
</div>
<div class="col-md-4">
<!-- Blog Search Well -->
<form action = "{%url 'blog_search'%}" method = "POST">
<div class="well">
<h4>Blog Search</h4>
<div class="input-group">
{%csrf_token%}
<input type="text" class="form-control" name = "keyword", placeholder = "Enter search keyword">
<span class="input-group-btn">
<button class="btn btn-default" type="submit">
<span class="glyphicon glyphicon-search"></span>
</button>
</span>
</div>
<!-- /.input-group -->
</div>
</form>
<!-- Blog Categories Well -->
<div class="well">
<h4>Tags</h4>
<div class="row">
<div class="col-lg-6">
<ul class="list-unstyled">
<!-- {%for a in tags_list%}
{{a}}
{%endfor%} -->
<!-- {%for a in tags_list%}
{{a}}
{%endfor%} -->
{%for a in tags_list%}
{{a}},
{%endfor%}
<!-- <li>Category Name
</li>
<li>Category Name
</li>
<li>Category Name
</li>
<li>Category Name
</li> -->
</ul>
</div>
<div class="col-lg-6">
<ul class="list-unstyled">
<li>Category Name
</li>
<li>Category Name
</li>
<li>Category Name
</li>
<li>Category Name
</li>
</ul>
</div>
</div>
<!-- /.row -->
</div>
<!-- Side Widget Well -->
<div class="well">
<h4>Side Widget Well</h4>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Inventore, perspiciatis adipisci accusamus laudantium odit aliquam repellat tempore quos aspernatur vero.</p>
</div>
</div>
</div>
</div>
</div>
<!-- Blog Sidebar Widgets Column -->
<!-- /.row -->
<hr>
<!-- Footer -->
<footer>
<div class="row">
<div class="col-lg-12">
<p>Copyright © Your Website 2014</p>
</div>
</div>
<!-- /.row -->
</footer>
</div>
<!-- /.container -->
<!-- jQuery -->
{%block javascript%}
<script src="{%static 'js/jquery.js'%}"></script>
<!-- Bootstrap Core JavaScript -->
<script src="{%static 'js/bootstrap.min.js'%}"></script>
{%endblock javascript%}
</body>
</html>
When I am loading my homepage (home.html) I am not facing any issue, however, when I am trying to logout after logging in i am facing the error . My logout view is rendering home.html also. However, in this case it doesn't work. Please help me out of this. I am stuck.
My quick answer is that the logout view function is not providing the context variables that the home.html template needs. Try redirecting to the home view instead.