here in my code i am displaying elements from a database using a loop
at the the user click buy button, i want to pass the particular product id to another page.
how i get the product id & how it passed to another page...
HTML page
{% for product in products %}
<div class="col-md-3">
<div class="card">
<img src="{{product.product_image}}" class="card-img-top" alt="...">
<div class="card-body">
<h5 class="card-title">{{product.product_name}}</h5>
<p class="card-text">₹{{product.product_price}}</p>
<a href="{% url 'buy' %}" class="btn btn-primary">
Buy</a>
</div>
</div>
</div>
{% endfor %}
Passing id to path
{% for product in products %}
<div class="col-md-3">
<div class="card">
<img src="{{product.product_image}}" class="card-img-top" alt="...">
<div class="card-body">
<h5 class="card-title">{{product.product_name}}</h5>
<p class="card-text">₹{{product.product_price}}</p>
<a href="{% url 'buy' product.id %}" class="btn btn-primary">
Buy</a>
</div>
</div>
</div>
{% endfor %}
Problem
I want to the following things but am unable to understand that how can I do the following things.
Firstly, I want that when the page is loaded the defualt values should be displayed from using the value from the combox. For example pack of 1KG is the defualt value so it's price and other values should be updated when the page is loaded.
Secondly, I want that when the product is added to the cart the page is not reloaded or refreshed and a popup is shown that the product is added to the cart.
CODE
Script
$(document).on("change", '.tranactionID', function (event) {
event.preventDefault();
//get closest outer div..
var selector = $(this).closest(".productID")
//find to get required elements..
selector.find('.id_price').text($(this).children(":selected").attr("price"));
selector.find('.price-sale').text($(this).children(":selected").attr("sale_price"));
selector.find('.id_discount').text($(this).children(":selected").attr("discount"));
let id = $(this).find("option:selected").attr('transID');
let Url = `{% url 'cart:cart_add' 0 %}`.replace(0, id);
selector.find("form").attr('action', Url);
});
HTML
{% regroup transaction by productID as ProductList %}
{% for productID in ProductList %}
<div class="col-sm-3 productID" >
<div class="product">
<a href="{% url 'main:product-detail' productID.grouper.id %}" class="img-prod"><img class="img-fluid" src={{productID.grouper.product_image.url}} alt="" height="200px">
<span class="status id_discount">%</span>
<div class="overlay"></div>
</a>
<div class="text py-3 pb-4 px-3 text-center">
<h3>{{productID.grouper}}</h3>
<div class="d-flex">
<div class="pricing">
<p class="price"><span class="mr-2 price-dc id_price">Rs. </span><span class="price-sale">Rs. </span></p>
</div>
</div>
<select class="tranactionID" id="ItemID" style="width: 250px;">
{% for val in productID.list %}
<option transID={{val.id}} price={{val.Price}} discount={{val.discount_percentage}} sale_price={{val.get_sale}} class="price_value" >{{val.AUID}} - {{val.Description}}</option>
{% endfor %}
</select>
<form id='transactionIDValue' class="d-inline" method="post">
{{cart_product_form}}
{% csrf_token %}
<input type="submit" id="Id_submit" class="btn btn-primary shadow px-5 py-2" value="Add To Cart">
<!-- <button type="submit" class="btn btn-primary shadow px-5 py-2">Add to Cart</button> -->
</form>
</div>
</div>
</div>
{% endfor %}
This is my discover.html file
<form action="POST">
<div class="swipe-area">
<div class="swiper-container mySwiper">
<div class="swiper-wrapper">
{% for topic in topics %}
<div class="swiper-slide">
<a href="{% url 'content' %}" style="color: white; text-decoration: none;">
<h1 name="headings" data-tooltip="{{ topic.description }}" data-tooltip-location="bottom">
{{ topic.heading }}
</h1>
</a>
</div>
{% endfor %}
</div>
<div class="swiper-button-next"></div>
<div class="swiper-button-prev"></div>
</div>
<!-- <div class="swiper-button-next"></div>
<div class="swiper-button-prev"></div> -->
</div>
</form>
I want to pass the value of h1 tag that is {{ topic.heading }} when clicked on that link to the page that link takes me.
<a href="{% url 'content' %}" style="color: white; text-decoration: none;">
<h1 name="headings" data-tooltip="{{ topic.description }}" data-tooltip-location="bottom">
{{ topic.heading }}
</h1>
</a>
Below is my views.py file
def content(request):
heading = request.GET['headings']
content = Search.objects.all().filter(title__contains = heading)
context = {'content': content}
return render(request, 'search/content.html', context)
So I want that variable value in my content.html page.
Please tell me how to tackle this problem, I have been stuck here for 2 weeks.
You should add the heading in the link href.
<a href="{% url 'content' %}?heading={{topic.heading}}" style="color: white; text-decoration: none;">
<h1 name="headings" data-tooltip="{{ topic.description }}" data-tooltip-location="bottom">
{{ topic.heading }}
</h1>
</a>
This will output something like , then when user clicks on this link, the heading parameter will be added in request.GET.
You need to modify your view accordingly heading = request.GET['heading'].
I am new to programming and this is also my first question on this platform. I have tried implementing applicable solutions I could find here for similar questions raised but is still stuck. Should you believe that a previously answered question might answer mine, please share the link to such answer. Also please correct me should you find that I have broken some guidelines on how to properly ask questions on this platform.
Now, on to the actual issues.
The following are the relevant sections (please, let me know if I have missed something that might be relevant). The issues are stated on my comments on modals.js.
modals.js
$(document).ready(function(){
$('#frmAddProduct').on('submit', function aj (event) {
event.preventDefault();
$.ajax({
cache: false,
type : 'POST',
url : '/products/new',
data : $('#frmAddProduct').serialize(),
datatype: 'html'
})
.done(function process (data) {
/* The modal has to be shown unless the user clicks on 'close'*/
$('#modalAdd').modal('show');
let err = $(data).find(".invalid-feedback").html();
if (err){
/* replace the contents of the modal with section from
ajax result to show validation messages*/
let cont = $(data).find("#targetModalContent").html();
$('#targetModalContent').html(cont);
/* Once the code above executes, clicking the submit button again
terminates the whole process.
Maybe this section requires a loop or recursion? But this part
is already on the "on submit" listener, right?*/
}
else {
/* Show success flash message on the modal instead of the original
below nav location */
console.log(data);
let msg = $(data).closest("#targetFlash").html();
/* using the .find doesn't work and results in msg=undefined.
I don't understand why that is the case, I tried using .parent
but it also did not work, or maybe I was using the .parent improperly.
I also tried $($(data).closest("#targetFlash")).parent().html but
it too didn't worked.
Why is it returning only the message and not the whole node
with the enclosing div?
*/
$('#frmAddProduct fieldset>div:first').prepend(msg);
}
});
});
});
products.html
{% extends "tblayout.html" %}
<!-- Main Content -->
{% block thead %}
{% endblock %}
{% block tbody %}
{% endblock %}
{% block tfoot %}
{% endblock %}
{% block maincont %}
<!-- ModalAdd -->
<div class="modal fade" id="modalAdd" tabindex="-1" role="dialog" aria-labelledby="modalAddTitle" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered modal-lg" role="document">
<div class="modal-content" id="targetModalContent">
<div class="modal-header">
<h5 class="modal-title" id="modalAddLongTitle">Add {{ legend }}</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<form method="POST" action="" id="frmAddProduct">
{{ formAdd.csrf_token }}
<div class="modal-body">
<div class="container-fluid">
<fieldset class="form-group">
<div class="form-group row">
{{ formAdd.productSubCategory.label(class="col-form-label col-sm-5") }}
{% if formAdd.productSubCategory.errors %}
{{ formAdd.productSubCategory(class="form-control col-sm-7 is-invalid") }}
<div class="invalid-feedback">
{% for error in formAdd.productSubCategory.errors %}
<span class="col-sm-7 offset-5">{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ formAdd.productSubCategory(class="form-control col-sm-7") }}
{% endif %}
</div>
<div class="form-group row">
{{ formAdd.brand.label(class="col-form-label col-sm-5") }}
{% if formAdd.brand.errors %}
{{ formAdd.brand(class="form-control col-sm-7 is-invalid") }}
<div class="invalid-feedback">
{% for error in formAdd.brand.errors %}
<span class="col-sm-7 offset-5">{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ formAdd.brand(class="form-control col-sm-7") }}
{% endif %}
</div>
<div class="form-group row">
{{ formAdd.description.label(class="col-form-label col-sm-5") }}
{% if formAdd.description.errors %}
{{ formAdd.description(class="form-control col-sm-7 is-invalid") }}
<div class="invalid-feedback">
{% for error in formAdd.description.errors %}
<span class="col-sm-7 offset-5">{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ formAdd.description(class="form-control col-sm-7") }}
{% endif %}
</div>
</fieldset>
</div>
</div>
<div class="modal-footer">
<div>
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
</div>
<div>
{{ formAdd.submit(class="btn btn-primary") }}
</div>
</div>
</form>
</div>
</div>
</div>
{% endblock %}
<!-- Optional Body scipt loaded after the main content has loaded -->
{% block bodyscript %}
<script src="../static/js/modals.js"></script>
{% endblock %}
AJAX result on Issue #1
<!-- ModalAdd -->
<div class="modal fade" id="modalAdd" tabindex="-1" role="dialog" aria-labelledby="modalAddTitle" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered modal-lg" role="document">
<div class="modal-content" id="targetModalContent">
<div class="modal-header">
<h5 class="modal-title" id="modalAddLongTitle">Add Product</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<form method="POST" action="" id="frmAddProduct">
<input id="csrf_token" name="csrf_token" type="hidden" value="ImNlZDc1Njc0MTY4NTg5NTNhNDg0NWEyNGYyZjYzZmIyYmFmMTZhZmQi.YAamUA.WGi03w__AklqccdIQgK_pWG5oJg">
<div class="modal-body">
<div class="container-fluid">
<fieldset class="form-group">
<div class="form-group row">
<label class="col-form-label col-sm-5" for="productSubCategory">Product Sub-Category</label>
<select class="form-control col-sm-7 is-invalid" id="productSubCategory" name="productSubCategory" required><option selected value="1">ProductCategory1, ProductSubCategory1</option><option value="2">ProductCategory1, ProductSubCategory2</option><option value="3">ProductCategory2, ProductSubCategory3</option></select>
<div class="invalid-feedback">
<span class="col-sm-7 offset-5">Product combination is already enrolled.</span>
</div>
</div>
<div class="form-group row">
<label class="col-form-label col-sm-5" for="brand">Brand</label>
<select class="form-control col-sm-7 is-invalid" id="brand" name="brand" required><option selected value="1">Brand1</option><option value="2">Brand2</option><option value="3">Brand3</option></select>
<div class="invalid-feedback">
<span class="col-sm-7 offset-5">Product combination is already enrolled.</span>
</div>
</div>
<div class="form-group row">
<label class="col-form-label col-sm-5" for="description">Product Description</label>
<input class="form-control col-sm-7 is-invalid" id="description" name="description" placeholder="New Product" required type="text" value="45">
<div class="invalid-feedback">
<span class="col-sm-7 offset-5">Product combination is already enrolled.</span>
</div>
</div>
</fieldset>
</div>
</div>
<div class="modal-footer">
<div>
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
</div>
<div>
<input class="btn btn-primary" id="submit" name="submit" type="submit" value="Add Product">
</div>
</div>
</form>
</div>
</div>
</div>
AJAX result on Issue #2 (I have copied only the target div since the rest of the html data is just the same, this is right below the nav)
<div class="alert alert-success" id="targetFlash">
Product 45 has been added!
</div>
main.routes.py
#main.route("/products", methods=['GET', 'POST'])
#login_required
def products():
formAdd = frmAddProduct()
formMod = frmModProduct()
q = sess.query(Product.id.label("PId"),
Product.description.label("PDesc"),
Product.isactive.label("PIsactive"),
ProductSubCategory.id.label("PSCid"),
ProductCategory.description.label("PCDesc"),
ProductSubCategory.description.label("PSCDesc"),
Brand.id.label("BId"), Brand.name.label("BName"))\
.select_from(Product)\
.join(ProductSubCategory)\
.join(ProductCategory)\
.join(Brand)\
.all()
page = request.args.get('page', 1, type=int)
qp = paginate.Page(q, items_per_page=5, page=page)
data = sqlaq2dict(qp)
npage = qp.pager(url= url_for('main.products') + "?page=$page",
link_attr=dict({'class':'btn btn-outline-primary mb-4'}),
curpage_attr=dict({'class':'btn btn-primary mb-4'}),
dotdot_attr=dict())
pagenav = Markup(npage)
return render_template("products.html", title='Products', legend='Product',
data=data, pagenav=pagenav, formAdd=formAdd, formMod=formMod)
#main.route("/products/new", methods=['POST'])
#login_required
def addProduct():
formAdd = frmAddProduct()
if formAdd.validate_on_submit():
p = Product()
p.productSubCategory_id = formAdd.productSubCategory.data
p.brand_id = formAdd.brand.data
p.description = formAdd.description.data
p.isactive = formAdd.isactive.data
syncNext('management', 'Product', 'id') # Ensures right ID for Postgres
sess.add(p)
sess.commit()
flash(
f'Product {formAdd.description.data} has been added!', 'success')
# return jsonify({"status" : "success"}) #Cannot have multiple returns
return redirect(url_for('main.products'))
return render_template("products.html", title='Products', legend='Product',
formAdd=formAdd)
forms.py
class frmAddProduct(FlaskForm):
# productSubCategories = sess.query(ProductSubCategory.id,\
# ProductSubCategory.fullDesc)\
# .filter(ProductSubCategory.isactive==True)\
# .all()
psc = sess.query(ProductCategory.description.label("PCDesc"),
ProductSubCategory.id.label("PSCId"),
ProductSubCategory.description.label("PSCDesc"))\
.join(ProductSubCategory)\
.all()
pscDict = sqlaq2dict(psc) #Converts the resulting tuple to dict
productSubCategories = []
for r in pscDict:
i = (r['PSCId'], r['PCDesc'] + ', ' + r['PSCDesc'])
productSubCategories.append(i)
productSubCategory = SelectField('Product Sub-Category',
choices=productSubCategories,
coerce=int,
validators=[InputRequired()])
brands = sess.query(Brand.id, Brand.name)\
.filter(Brand.isactive == True)\
.all()
brand = SelectField('Brand', choices=brands, coerce=int,
validators=[InputRequired()])
description = StringField('Product Description', validators=[
DataRequired()], render_kw={"placeholder": "New Product"})
isactive = BooleanField('Status', default=True)
submit = SubmitField('Add Product')
#---------------------------------------------Should be composite Key
def validate_productSubCategory(self, productSubCategory):
user = sess.query(Product)\
.filter(Product.productSubCategory_id == self.productSubCategory.data,
Product.brand_id == self.brand.data, Product.description ==
self.description.data)\
.first()
if user:
raise ValidationError('Product combination is already enrolled.')
def validate_brand(self, brand):
user = sess.query(Product)\
.filter(Product.productSubCategory_id == self.productSubCategory.data,
Product.brand_id == self.brand.data, Product.description ==
self.description.data)\
.first()
if user:
raise ValidationError('Product combination is already enrolled.')
def validate_description(self, description):
user = sess.query(Product)\
.filter(Product.productSubCategory_id == self.productSubCategory.data,
Product.brand_id == self.brand.data, Product.description ==
self.description.data)\
.first()
if user:
raise ValidationError('Product combination is already enrolled.')
I would like to allow the modal to be displayed on the basis of the id set from the database. Having different fruit/vegetables displayed in the container divided into tiles, I put their id in the id field of the class.
In other words, pressing a button in the overlay class for a particular fruit displays a single modal with the rest of the information.
HTML CODE:
{% block body_block %}
<div class="container-fruits">
<div class="row">
{% for t in thumb %}
<div class="col-lg-3 col-md-4 col-sm-6 col-xs-12 box">
{% thumbnail t.image "255x189" crop="center" as im %}
<div class="hovereffect">
<img class="img-responsive" src="{{ im.url }}" alt="Card image cap">
<div class="overlay">
<h2>{{ t.name }}</h2>
<a id="{{ t.id }}" class="info" data-target="#{{ t.id }}" href="#">show details</a>
</div>
</div>
{% endthumbnail %}
</div>
{% endfor %}
</div>
</div>
{% for t in thumb %}
<div id="{{ t.id }}" class="fruitsModal" tabindex="-1" style="display: none">
<div class="modal-dialog modal-lg ">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h2 class="modal-title">{{ t.name }} information</h2>
</div>
<div class="modal-body">
<h2 class="modal-body-text">{{ t.description }}</h2>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
{% endfor %}
<script src="{% static 'javascript/fruits.js' %}"></script>
{% endblock %}
Javascript/Jquery
$(document).ready(function () {
$('.info').click(function (e) {
$(".fruitsModal").fadeIn('slow');
var image = $(e.relatedTarget).attr('src');
var text = $(e.relatedTarget).attr('t.name');
$(".img-responsive").attr("src", image);
$(".modal-body").attr("modal-body-text", text);
console.log('hello bind');
});
$(".btn-default").click(function () {
$(".fruitsModal").fadeOut('slow');
});
});
To open the modal targeted by a specific ID, you just need to know the ID and
Remove the id id="{{ t.id }}" from your a tag
Rename your target data-target="#modal-{{ t.id }}" to make it a little better to avoid multiple identical ids.
<a data-toggle="modal" class="info" data-target="#modal-{{ t.id }}"....
Finally rename the id of your modals, like the target above
<div id="modal-{{ t.id }}" class="fruitsModal" tabindex="-1" style="display: none">
The tag a becomes:
<a class="info" data-target="#modal-{{ t.id }}" href="#">show details</a>
And the modal:
<div id="modal-{{ t.id }}" class="fruitsModal" tabindex="-1" style="display: none">
<div class="modal-dialog modal-lg ">
1st Option:
If you need to let bootstrap do everything for you, means when you click on a without your script, the modal will show up.
Just add the data-toggle attribute to your a tag, and add the same value of data-target to href.
<a data-toggle="modal" href="#modal-{{ t.id }}" data-target="#modal-{{ t.id }}"
In that case, the data-target="" is not really needed
2nd option:
As you want to do some stuff before showing the modal, this fits your need.
When triggering the a tag with click event, is js, you just need to show the concerned modal
$('.info').click(function (e) {
$(".fruitsModal").fadeIn('slow');
var image = $(e.relatedTarget).attr('src');
var text = $(e.relatedTarget).attr('t.name');
$(".img-responsive").attr("src", image);
$(".modal-body").attr("modal-body-text", text);
console.log('hello bind');
// # retrieve the target modal: data-target="#modal-{{ t.id }}"
var t_modal = $("this").data('target');
$(t_modal).show(); // this is because you have style={display:none}
$(t_modal).modal('show');
});