I am building a voting mechanism for a site. A similar one seen on Stackoverflow.
For instance, if user clicked up-arrow, vote = True. If he clicks again on it, vote = None. The app is working fine except if we submit votes very fastly.
We tried to click arrows very very fastly and see how voting is happening by logging the data. Unfortunately, we are seeing some misbehavior. By fast, I mean, clicking the arrow continuously without stopping for some seconds!
The expected log data should be like
vote=True
vote=None
vote=True
vote=None
..
But I observed it like
vote=True
vote=True
vote=None
vote=None
The observed log data mentioned as second case, seems to be a bit unordered..
This could mean that the requests received by django are not handled as a queue! Which in our case is a bit dangerous. Or database is taking some time to store and during that period another requests are handled which is causing the error.
I hope you are understanding my issue. So, I am wondering if you can let me know what's going on here and how to control it.
You cannot make assumptions about the order in which a browser sends (asynchronous) requests, the order in which they arrive at the server and the order in which they are handled by a single or multi-instance (threaded, worker) Django application.
So what you describe above is what you actually might expect. Doing synchronous requests may help a bit. The best option is probably to (asynchronously) wait for the server's response before allowing further clicks.
You must be having a flow similar to this:
-> User clicks button
-> check if user has already voted up
-> if no:
-> vote up request goes
-> vote up after validation
-> response is sent back to browser
-> else:
-> vote none request goes
-> remove the vote after validation
-> response is sent back to browser
If you don't disable the button for the time when a request has already been sent and its response is awaited, then you will get into such situations.
Say, request1 was considered a vote up and request was sent.
Before request1's response came and user clicked again, then this request will also be considered as a vote up, which is not what you expect.
You should either disable the button, just before making the ajax call and enable it again when the response is received.
Or whenever user clicks, you should flip the button type i.e. make it vote-none for vote-up request and vice versa, even before making the ajax call. And when the ajax response is received, validate the previous action again. It will vary only in cases, when any validation fails on server side, like the user might not have permission to vote up.
You can see this happening in SO if you try to vote-up your own post. It first changes to vote-none mode and then later when the response is received from server, it changes back and also gives an error message.
PS: I tried to vote-up my own posts for educational purposes only ;)
Related
The flashing system basically makes it possible to record a message at
the end of a request and access it on the next (and only the next)
request
Please can I have an example wherein a msg recorded at the end of a request will need to be accessed in the next request?
flashing is very useful for websites.
Let's say you have a login system on your website and you want to notify user after they logout, then you can simply add a flash message saying something like "You have been logged out!"
Everything works fine without flashing but it gives extra confirmation to the user and makes website more user-friendly.
How can I close sessions in Django if a user moves from my site to another or if he close the browser.
From both the question and comments, seems you would like to "close" session when user exits your site without any aid from JS. The answer is it depends how you define "close".
Root of the problem is that HTTP is stateless. Each request coming into the server is completely independent request without any relation to any other requests which means there cannot be any state. Since state is very useful we hack HTTP to add state by using sessions. The idea is that browser sends some identifier to some state stored on the server which allows the server to retrieve that state hence give some context to the request. The key there is that the browser is sending that data. In other words, if the browser at some point will stop sending requests, (e.g. user closes the tab), the server will never know that. Therefore if you define "close" session as removing session from the server, no that cannot be possible without some JS help.
If however all you are trying to achieve is log the user out when they exit your site, that can partially be done in Django with the use of SESSION_EXPIRE_AT_BROWSER_CLOSE setting. Here are additional docs about that. The idea here is that when Django sends the session cookie back to the browser, it will indicate to it that the session cookie should expire when the browser is closed. In that case when the browser is closed, the browser itself will invalidate the session hence the user will be forced to create new session on next visit. This is partial solution since the session will still be stored on the server and I believe only works when browser is completely closed (I dont think closing tabs works but not certain). To mitigate the issue of the server accumulating old sessions, Django provides a management command clearsessions which you should run on regular basis.
The use case:
User makes order his payment gets accepted and his details are getting post to a django's view. Using these details django's view creates user and everything that is necessary (Username and password is provided by me). Then before returning it sends email to clients email with his data (Username and password for now).
But sometimes I get a gateway timeout error from apache(app is deployed on openshift). Because the user is created I assume that the timeout comes from the email sending part. How can I make sure everything went ok and inform the user? How can I make sure that if the email isn't sent I can resend it? What is the best practice at that?
If you have timeouts with an API or Service, you should fire your POST / sendmail request with AJAX...
Serialize the whole form (like jQuery's serialize())
Send that data via AJAX (with jQuery's ajax())
Inform the User of success or error (alert() or jQuery UI dialog)
You can find a lot of examples on this website.
Another "dirty" approach would be to add the attribute target="_blank" to your form tag what opens your lazy request in a new tab / window.
I have a problem with my website. there it is :
No problem in this case :
User A do a request.
Django server update data...
Object 1 is updated.
Object 2 is updated.
Object 3 is updated.
Django render the result.
User A do a request.
Problem apear in this case :
User A do a request.
Django server update data...
Object 1 is updated.
Object 2 is updated.
User A do another request !
User A do another request !
Django render the result.
the problem is that if the user makes a request while the server has not finished working, the server stop the process and data are no longer good.
I think i have to block client side (by displaying a loading message for exemple) but i want to be sur the user cant make a request on the server if another treatemment still working.
thanks for your time.
This sounds like you have a long running process, and the user gets tired of waiting, clicks on "stop" in the browser; the other scenario is - user opens another tab and sends the same request again.
A few ways to solve this problem.
Use the transaction middleware to prevent your db objects from being corrupted if the request is interrupted.
Use a task queue like celery. At the first request, offload your task to the queue/broker. Send the user a message that their request has been accepted for processing. Now the user is free to send a duplicate request. If they do, you can check what is the status of the queue and reject the duplicate requests.
I have a django app and I use messages in order to show some limits that user passes.
My problem is that all my messages are shown after the second request.
I mean, after adding a message and going to a page where the the message should be shown, I don't see it, but I start seeing it after a refresh.
What am I doing wrong?
This is probably how those messages are intended to work: You "trigger" them e.g. to show success/failure and then redirect to another page where it's displayed. Remember: In case an action succeeded you should never stay on the page requested via POST but redirect so reloading won't re-POST whatever was sent.