How to use notify in Django with Bootstrap? - django

Trying to put those notification system on my templates.
I use a:
{% for message in messages %}
<<What I need to put here to create a notifiy for each error message??>>
{% endfor %}

Solved with:
<script>
{% for message in messages %}
$(document).ready(function() {
$.pnotify({
title: '{{ message.tags|upper }}',
text: '{{ message }}.',
type: '{{ message.tags }}',
hide: false,
styling: 'bootstrap',
closer_hover: false,
sticker_hover: false
});
});
{% endfor %}
</script>

Related

Toast with Django CreateView message How to show

I'm new in Django and I'm creating a CRUD. However I want to show a Success message in a Toast for successfully submit, but I don't know how to do it exactly.
The view class once is inserted, redirect correctly to List, but no messages showed.
This is my view class
class AlmacenesCreateView(SuccessMessageMixin, CreateView):
model = Almacen
form_class = AlmacenesForm
template_name = 'pages/create.html'
success_url = reverse_lazy('almacenes')
success_message = "Bien!!!!"
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['title'] = "New Almacen"
return context
And this is the script for the toast
$(function () {
let mensaje ="{{ messages.0 }}";
const Toast = Swal.mixin({
toast: true,
position: 'top-end',
showConfirmButton: false,
timer: 3000
});
if (mensaje != "") {
Toast.fire({
icon: 'success',
title: mensaje,
})
}
});
My doubt is how I can show the success message
You have to loop over messages and then print icon accordingly
{% for message in messages %}
<script>
$(function () {
let mensaje ="{{ message }}";
const Toast = Swal.mixin({
toast: true,
position: 'top-end',
showConfirmButton: false,
timer: 3000
});
if (mensaje != "") {
Toast.fire({
icon: "{% if message.tags %}{{ message.tags }}{% endif %}",
title: mensaje,
})
}
});
</script>
{% endfor %}
You can even consider using things like this
Swal.fire({
title: "Thank you?",
text: "success message here",
type: "success",
showCancelButton: true,
confirmButtonColor: "#DD6B55",
confirmButtonText: "Yes, delete it!",
closeOnConfirm: false
}, function() {
swal("Successful!", "success message here", "success");
});
});
Did you follow the documentation here and there :
In your template, use something like:
{% if messages %}
<ul class="messages">
{% for message in messages %}
<li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
Then you can check in your console if you don't have any Javascript errors for your code. I've never used Swal library.

How to add comment on django site with ajax call and without refreshing?

On site exists form where users able to comment products. Comments are connected with products. jQuery is used from Bootstrap base.html (it's worked with another ajax-call). I'm fighting with ajax comment during the week). Trying to do it only for one product to understand how it works. Without ajax system of comments works fine, but I decided to add smooth in comment add without refreshing of the page and I do task with POST and ajax for the first time (before I did two pretty simple examples with get and form reset after successful response to ajax from back-end). Could somebody advice what should be add in template and view ? I suppose problem is connected with my poor knowledge of js.
I am using
is_ajax = request.META.get('HTTP_X_REQUESTED_WITH') == 'XMLHttpRequest'
because this is working with django 4.0, and old function is_ajax() was removed.
views.py
def ajax_test(request):
product = Product.objects.get(id=4)
comments = product.comment_set.order_by('-created_at')
form = UserCommentForm
context = {'product':product,'comments':comments,'form': form}
return render(request, 'store/ajax_test.html', context)
def ajax_receiver(request):
is_ajax = request.META.get('HTTP_X_REQUESTED_WITH') == 'XMLHttpRequest'
if request.method == 'POST' and is_ajax:
product = Product.objects.get(id=4)
form = UserCommentForm(data=request.POST)
user = Comment.objects.get(author=user)
if form.is_valid() and request.user.is_authenticated:
new_comment = form.save(commit=False)
new_comment.author = request.user
new_comment.product = product
new_comment.save()
comment_info = {
"author": new_comment.author,
"new_comment": new_comment.content,
"created_at": new_comment.created_at,
}
return JsonResponse({"comment_info": comment_info}, status=200)
else:
return JsonResponse({"success": False}, status=400)
template
{% extends "store/base.html" %}
{% load bootstrap4 %}
{% block page_header %}
<h1>тестирую аякс</h1>
{% endblock page_header %}
{% block content %}
<div class="container">
<div class="row py-3">
<div class="col-3 order-2" id="sticky-sidebar">
<div class="sticky-top">
<form id="UserCommentForm" method='post' class="form">
{% csrf_token %}
{% bootstrap_form form %}
{% buttons %}
<button name="submit" class="btn btn-primary" name="comment">Добавить комментарий</button>
{% endbuttons %}
</form>
</div>
</div>
<div class="col" id="main">
<h3>Комментарии:</h3>
{% for comment in comments %}
<h6 class="card-header">
{{ comment.author }}<small> добавлен {{ comment.created_at|date:'M d, Y H:i' }} </small>
</h6>
<div class="card-body">
<h4>{{ comment }}</h4>
<form action="" method="POST">
{% csrf_token %}
</form>
</div>
{% empty %}
<p>Для данного товара ещё нет комментариев.</p>
{% endfor %}
</div>
</div>
</div>
{% block javascript %}
<script type="text/javascript">
$(document).ready(function(){
$("#UserCommentForm").submit(function(e) {
// prevent from normal form behaviour
e.preventDefault();
// serialize the form data
var serializedData = $(this).serialize();
$.ajax({
type : 'POST',
url : "{% url 'store:ajax_receiver' %}",
data : serializedData,
success : function(response){
??? what should be there to post ???
},
error : function(response){
console.log(response)
}
});
});
});
</script>
{% endblock javascript %}
{% endblock content %}
Finally I found the decision, it's just to reload block of comments without refreshing, there is the code, the space before ' #main' is important!:
<script type="text/javascript">
$(document).ready(function(){
$("#UserCommentForm").submit(function(e){
// prevent from normal form behaviour
e.preventDefault();
// serialize the form data
var serializedData = $(this).serialize();
$.ajax({
type : 'POST',
url : "{% url 'store:ajax_receiver' %}",
data : serializedData,
success : function(response){
$('#main').load(' #main', function(){
/// can add another function here
});
$("#UserCommentForm")[0].reset();
},
error : function(response){
console.log(response)
}
});
});
});
</script>
In your ajax success write the following code to show new comment:
let comment_info = response["comment_info"];
let author = comment_info["author"];
let comment = comment_info["comment"];
let created_at = comment_info["created_at"];
html = "<h6 class='card-header'> "+author+"</h6>"
// i have writting only part of html write the full just like you do when you show comments
$("#main").append(html);

sweetalert not working on django template

I started with the following code to send the ID to a method to delete an object of model.But the first ID is always sent.
this is my HTML and JavaScript code:
{% for yad in yads %}
<form action="{% url 'del-yadd' %}" method="post" id="myform">
{% csrf_token %}
<button type="button" name="yidd" value="{{yad.id}}" id="btndelme" class=" btn btn-danger" onclick="
swal({
title: 'warning!',
text: 'do you want to delete?',
type: 'warning',
showCancelButton: true,
confirmButtonColor: '#3085d6',
cancelButtonColor: '#d33',
cancelButtonText:'no',
confirmButtonText: 'yes'
},
function(isConfirm) {
if (isConfirm) {
document.querySelector('#myform').submit();
}});
">delete</button>
</form>
{% endfor %}
and this is my Django view code:
def delete_yadd(request):
id=request.POST['yidd']
yad=Yadd.objects.filter(id=id).delete()
return redirect('home')
The reason why your SweetAlert is not showing is because it needs to be called right near the end of the html document by using a javascript function. Things I have changed are the way you call the sweetalert function like below:
{% for yad in yads %}
<form action="{% url 'del-yadd' %}" method="post" id="myform">
{% csrf_token %}
<button type="button" name="yidd" value="{{yad.id}}" id="btndelme" class=" btn btn-danger" onclick="confirm()"></button>
</form>
{% endfor %}
<script>
function confirm() {
swal({
title: 'warning!',
text: 'do you want to delete?',
icon: 'warning',
showCancelButton: true,
confirmButtonColor: '#3085d6',
cancelButtonColor: '#d33',
cancelButtonText: 'no',
confirmButtonText: 'yes'
},
function (isConfirm) {
if (isConfirm) {
document.querySelector('#myform').submit();
}
})
}
</script>

How to center a Leaflet Map forms in a Django template

after 2 days trying to do it by myself, I need some help please
I'm using GeoDjango and Leaflet. I have a model "listing" having a field location as PointField, my form uses LeafletWidget as per below.
As it is, it is working but when I create a new listing, there is nothing in location, so it shows a default world map.
I would like in my template to setup the following:
CENTER: ({{ user.lat }}, {{ user.lng }}) and zoom: 10
since I know that the New listing will be in the same geographical area as the user.
And I have NO idea how to do it!!!
Model.py
location = models.PointField(null=True, blank=True)
forms.py
from leaflet.forms.fields import PointField
from leaflet.forms.widgets import LeafletWidget
...
LEAFLET_WIDGET_ATTRS = {
'map_height': '600px',
'map_width': '50%',
'display_raw': 'true',
'map_srid': 4326,
}
...
class ListingForm(forms.ModelForm):
required_css_class = 'required'
...
location = forms.PointField(
widget=LeafletWidget(attrs=LEAFLET_WIDGET_ATTRS))
...
template.html
<!-- form start -->
<form action="{% url 'listing_new' %}" method="POST" class="listing-form" role="form" novalidate enctype="multipart/form-data" id="listingform">
{% csrf_token %}
<div class="box-body">
{{ form.non_field_errors }}
{% for field in listingform %}
<div class="fieldWrapper form-group {% if field.errors %} field_error{% endif %} ">
<label for="{{ field.id_for_label }}">
{{ field.label }}{% if field.field.required %}<span class="required-asterisk">*</span>{% endif %}
</label>
{{ field }}
{% for error in field.errors %}
<span class="help-block">{{ error }}</span>
{% endfor %}
</div>
{% endfor %}
</div>
<div class="box-footer">
<button type="submit" class="btn btn-primary" form="listingform">Submit</button>
</div>
</form>
I tried to use the following:
<script type="text/javascript">
window.addEventListener("map:init", function (e) {
var detail = e.detail;
detail.options.djoptions['center']=[{{ listing_lat }}, {{ listing_lng }}];
detail.options.djoptions['zoom']=10;
console.log(detail.options);
console.log(detail.loadmap);
}, false);
</script>
BUT it doesn't modify the code auto-generated by the leaflet widget:
<div id="id_location-map" class="leaflet-container-default"></div>
<script type="text/javascript">
(function () {
function loadmap() {
var djoptions = {"srid": null, "extent": [[-90, -180], [90, 180]], "fitextent": true, "center": null, "zoom": null, "minzoom": null, "maxzoom": null, "layers": [["OSM", "//{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", "\u00a9 OpenStreetMap contributors"]], "overlays": [], "attributionprefix": null, "scale": "metric", "minimap": false, "resetview": true, "tilesextent": []},
options = {djoptions: djoptions, initfunc: loadmap,
globals: false, callback: id_location_map_callback},
map = L.Map.djangoMap('id_location-map', options);
}
var loadevents = ["load"];
if (loadevents.length === 0) loadmap();
else if (window.addEventListener) for (var i=0; i<loadevents.length; i++) window.addEventListener(loadevents[i], loadmap, false);
else if (window.jQuery) jQuery(window).on(loadevents.join(' '), loadmap);
})();
</script>
So, the solution is to add this piece of JS in the template:
<script type="text/javascript">
window.addEventListener("map:init", function (e) {
var detail = e.detail;
detail.map.setView([{{user_lat}},{{user_lng}}], 10);
}, false);
</script>
in simple JS, you'd set it up like:
map.setView([{{ user.lat }}, {{ user.lng }}], 10);
But with GeoDjango, you could try:
LEAFLET_WIDGET_ATTRS = {
'map_height': '600px',
'map_width': '50%',
'display_raw': 'true',
'map_srid': 4326,
}
LEAFLET_CONFIG {
'DEFAULT_CENTER': ({{ user.lat }}, {{ user.lng }}),
'DEFAULT_ZOOM': 10,
}
See this documentation: https://buildmedia.readthedocs.org/media/pdf/django-leaflet/latest/django-leaflet.pdf
In your Django.settings files add these lines:
LEAFLET_CONFIG = { 'DEFAULT_CENTER': (41.25 ,20), # Latitude , Longitude
'DEFAULT_ZOOM': 8,
'MAX_ZOOM': 28,
'MIN_ZOOM': 1,
'SCALE':'both',
'TILES': [], }

How to display a multi layer JSON in Django template?

So I have this JSON response:
{
"orders": [
{
"orderId": "4123456789",
"dateTimeOrderPlaced": "2017-02-09T12:39:48+01:00",
"orderItems": [
{
"orderItemId": "2012345678",
"ean": "0000007740404",
"cancelRequest": false,
"quantity": 10
}
]
}
]
}
I passed it in my view with the .json() method. I use this in my template:
{% for key, value in orders.items %}
{{ key }}: {{ value }}
{% endfor %}
I get this in my HTML:
orders: [{'orderId': '2529081520', 'dateTimeOrderPlaced': '2019-09-07T00:12:16+02:00', 'orderItems': [{'orderItemId': '2298728074', 'ean': '8945005881389', 'cancelRequest': False, 'quantity': 1}]}]
But how to dissect it further? For example to get the OrderId or the ean?
You can access dictionary items with the template variable dot-notation, like this
{% for order in orders.orders %}
{{ order.orderId }}
{% for item in order.orderItems %}
{{ item.ean }}
{% endfor %}
{% endfor %}
Assuming the context variable orders contains your parsed JSON, this template would be rendered like this:
OrderId: 4123456789
EAN: 0000007740404