How to show user status (Online, Offline) in Django 1.9? - python

I am trying to make a "social" site, where you can add friends, create posts, etc. So the main problem is, how to show user status, using Django Admin API?
Thanks in advance!
In html:
{{ user.is_authenticated }}
In view:
def index(request):
user = User.objects.get(username="root")
return render(request, 'blog/index.jade', {'users': users})
So this basically returns me True or False, but this is the status not for only "root" user, but anyone.

Make Ajax request every 5 seconds which will be handled by view. And on each request update table column last_active corresponding to that user which will update the timestamp (you have to make a last_active column of timestamp type).
Make another Ajax request every 5 seconds to fetch all the users who are online by comparing current time and last_active timestamp corresponding to each user. It will return all the users online.
You can use this logic to make multiuser/singleuser chat system also.
Code for making Ajax request:
(function getOnline() {
$.ajax({
url: '/get_online',
type: "GET",
data:
{
user:user
},
success: function(data) {
console.log("success");
},
complete: function() {
// Schedule the next request when the current one is complete
setTimeout(getOnline, 5000);
},
error: function(xhr, errmsg, err) {
console.log("error");
}
});
})();

You won't be using the Django admin page for that - that is just for database management. What you are referring to with {{ user.is_authenticated }} is part of the Django templating system. That is a variable that is written to the page on page load. It will not change until the user reloads the page. What you're going to need to do is use javascript's setInterval function to routinely do an ajax call back to the server. So you have a js file with an initialization function that calls the setInterval function, which in turn makes an ajax call every 20 seconds or so. The ajax call goes to a url that is defined in your urls.py file, which associates it with a view that is defined in your views.py file. That view queries the database to see if a user is authenticated or not, and then it returns that info in an HttpResponse to your ajax call, which has a callback that saves the response to an object, which you then render to the page in whatever way you want, to let the user know that other users are or are not logged in.

Related

How to load Django ListView via Ajax

Basically code works as I expected, but my ListView is not refreshing. Everything works fine, but template does not load itself, I must push reload button (all data are loaded correctly then).
I done simple form/input for testing and there is no problem with views. My project requires calendar widget for picking months, and simplest way to do this I found on the internet was Ajax approach.
Ajax function:
$(document).ready(function () {
$(function () {
$("#datetimepicker1").datetimepicker({
viewMode: 'months',
format: 'MM/YYYY',
}).on('dp.change', function (e) {
var url = "/booking/update_months/{{hotel_id}}";
$.ajax({
type: 'GET',
url: url,
dataType: 'json',
data: {
month: e.date.month(),
},
success: function (data) {
},
error: function (data) {
}
});
})
});
});
Url "/booking/update_months/{{hotel_id}}" refers to first View function I'm using for this functionality:
#csrf_exempt
def update_months(request, hotel_id):
if request.GET.get('month'):
month = request.GET.get('month')
request.session['month'] = int(month) + 1
return HttpResponseRedirect(reverse('booking:hotel_statistics', args=(hotel_id,)))
else:
return render_to_response(request, 'booking/hotel_statistics.html')
Then in HotelStatistics ListView I'm doing some stuff in get_context_data function, nothing special here. Just by some "prints" I've tested that the code is being executed until the end of the class.
class HotelStatistics(ListView):
model = Reservation
context_object_name = 'reservations'
template_name = 'booking/hotel_statistics.html'
def get_context_data(self, **kwargs):
.
.
.
return context
I'm pretty sure that I'm missing something with Ajax functionality, It's my first approach to this language. Thanks in advance for your help.
Why are you using AJAX here? Unless I am missing something, you should just have the date picker inside an HTTP GET form that is submitted.
template.html
<!-- The action attribute hardcoded URL value should be replaced with a Django url templatetag. This will allow the url to be resolved based on the router configuration. i.e. {% url "booking:update_months" hotel_id %} -->
<form action="/booking/update_months/{{ hotel_id }}" method="GET">
<input id="date" name="date">
<button type="submit">Update</button>
</form>
<script>
$(document).ready(function() {
$("#date").datetimepicker({
viewMode: 'months',
format: 'yyyy-mm-dd',
});
});
</script>
view.py
#csrf_exempt
def update_months(request, hotel_id):
date = request.GET.get("date")
if date:
request.session["month"] = datetime.strptime(date, "%Y-%m-%d").month
return redirect("booking:hotel_statistics", False, hotel_id)
return render(request, "booking/hotel_statistics.html")
The code above submits an HTTP GET form, resulting in a server side 301 and therefore a "refresh" of your statistics page with the update session data.
Notice, we are sending up the full date information. I am not sure if you are doing this separately, but if you are allowing users to update each date part independent, you could now bring that together into a single update_date function.

Django - retrieve information if only it's needed

I'm looking at building a site where you have a detail view of an object, and more data about that object can be shown to the user by clicking to open a modal pop up box. I was wondering how, in Django, this data can only be loaded if the user chooses to open the modal box - otherwise there's no point in it being there.
def detail_view(request):
...
extra_data = Object.objects.all().values_list('rating', flat=True) # Only required if a user open the modal box
return render(request, 'detail.html', {'extra_data':extra_data})
Any ideas on how this might be achieved whilst using as little JavaScript as possible?
This is a very broad question, although the following is a generic structure of how you can achieve this. The code below is just for reference. It is just to demonstrate the structure. You need two views, first view will fetch the basic info for all items. The second view fill fetch the additional details for the selected item.
The assumption is that you will have a button for opening the modal, to show the more details.
The javascript is listening to the click event on that button, and it is fetching more details that is to be displayed from the server, and then displaying it in the modal container.
Disclaimer: This is not the most optimal way to do this, this is just a quick and dirty solution.
//Assuming there is a button with id myButton using which user will toggle modal
$("#myButton").on("click", function(e) {
e.preventDefault();
var modal = null;//whatver the modal is
var model_id = 1;//store the id of the model in a accessible location and load it here
var modalContainer = $("#modalContent") // the element which is the container of the modal which will hold its contents
$.ajax({
url: "/get_item_detail", //this url should call viewB
type: "GET",
data: {
"id": model_id
},
success: function(response) {
var html = "<div></div>" //generate your html content for the modal container
modalContainer.html(html); //put the generated html content inside the modal Container
modal.open(); //open the modal here
},
error: function(response) {
}
})
});
from django.shortcuts import render
from django.http import JsonResponse
import json
def viewA(request):
#Fetch the basic info for all objects
items = Sample.objects.all()
return render(reqeust, "template.html", {
"items": items
})
def viewB(request):
#Fetch the additional detail of the concerned object
id = request.GET.get("id", None) #get id or if no id, set None
detailed_item = Sample.objects.get(id=id)
return JsonResponse(json.loads(detailed_item), safe=False)

Validate WTForm before submitting

Is it possible to validate a WTForm field after leaving the field but before submit?
For example, after entering a username, that field is validated to see if its available and shows a checkmark, before the user clicks submit.
When the field is changed, perform a check and change the text in an adjacent node. Some things can be validated directly in the browser. To validate against data on the server, send a request with JavaScript to a view that checks the data and returns a JSON response.
#app.route('/username-exists', methods=['POST'])
def username_exists():
username = request.form['username']
exists = check_if_user_exists(username)
return jsonify(exists=exists)
<input id='username' name='username'>
<p id='username-status'></p>
var username_input = $('#username');
var username_status = $('#username-status');
$('#username').on('focusout', function () {
$.post(
"{{ url_for('username_exists') }}",
{
username: username_input.val()
},
function (data) {
username_status.text(data.exists ? '✔️' : '🙅');
}
);
});
This example uses jQuery, but the concept is not specific to any library.
Alternatively, post the entire form to a separate view that only validates the fields, then return jsonify(form.errors) and do something with them in the browser. The code would be essentially the same as above, with some extra logic to put the error messages next to the correct fields.
Remember to still validate the data when the form is submitted, as requests can be made outside the browser with other

Render_template second time after page is already loaded

I am trying to query a database through my website and dynamically add columns with the results using Jinja templates. I am using flask and on my views function. I am rendering the values like this
return render_template('query.html',my_list=my_list )
The thing is that when I load the page the user hasn't queried the database yet, so my_list is empty. The user queries the database by pressing a button on the html page and making an ajax request through jquery. My question now is if its possible to return my_list using jinja templates even after the page is already loaded, meaning I have to return render_template a second time (after submit button) to get the values for my_list.
p.s. I prefer not to use json parsing.
Here is some sample code. I query the database with the values of intranetID of column SubmitterID and platform of column Platforms to return the whole entry to the database with the values of the rest of the columns as well.
#app.route('/querydbvalues',methods=['POST', 'GET'])
def querydbvalues():
if request.method == 'POST' or request.method == 'GET':
results = models.mydatabase.query.filter_by(SubmitterID=qIntranetID,Platforms=qPlatform).all()
my_list = [i.user for i in results]
return render_template('query.html',my_list=my_list )
and on my html page
{% for n in my_list %}
<li>{{n}}</li>
{% endfor %}
on the Javascript file when you press the button i make the ajax request like this
$("#SearchDatabase").click(function(){
var tmp = document.getElementById("qIntranetID").value;
var tmp2 = document.getElementById("qPlatform").value;
jQuery.ajax({
dataType: "json",
url:"/querydbvalues", //tell the script where to send requests
data:{text:tmp,text2:tmp2},
type:'GET',
contentType: 'application/json',
success: function(results){
//do something
}
});
});
The Ajax call is a completely separate request. You can do what you want in that request, including render templates.

How to make view that add product working correct in django/python

I have view in django that add product to the cart( i use django-carton 1.2). That my code:
def add(request,product_id):
cart = Cart(request.session)
product = Product.objects.get(pk=product_id)
if product.quantity >=1:
cart.add(product, price=product.price)
product.quantity-=1
product.save()
return render (request,'shopping/show-cart.html')
else:
return HttpResponse("No product ")
After that view has worked a certain product add to the cart, cart with all products is showing. The problem: when in browser I make function "reload current page" it increase quantity of products in my cart. At the same my remove product view is working, but it only try delete the product when page reload from the function of browser
You should only do actions that modify data - like add and delete - on a POST request, not a GET. You need to create a form in your page, even if it just contains a single button, and check if request.method == 'POST' in the view before doing anything.
Either include a form tag within your html that POSTS information or you can use an Ajax request call.
<script type="text/javascript">
$(document).ready(function(){
$('#add_cart_button').click(function(e)
{
$.ajax({
url: 'xxxxxxx',
type: 'POST',
dataType: 'html',
data: {
'somevariable' : 'somevalue'
},
async: false,
success: function(data){
$('#target').html(data);
},
error: function(XMLHttpRequest, textStatus, errorThrown) {
alert("Status: " + textStatus); alert("Error: " + errorThrown);
}
});
When you make the Ajax call, it sends whatever you have in your data dictionary to the specified url. From there, Django implements whatever function you want to process that data on the backend and returns the information back. The success function basically gets that information back and does whatever you want with it. In your case, you probably just want to re-render that chunk of HTML that displays the items in your cart.The target tag within the success function is where that chunk of HTML will be rendered, so include a target div tag in your html where you want it to be displayed.
You can access the data from the ajax request in your view by doing request.POST.get('key',somedefaultvalue) (if you want to have a default value if it can't find the dictionary or if it's empty) or just request.POST[key].

Categories

Resources