TL;DR - How do I maintain a list of users in each room so that I can send that data to the front-end to display a list of participants in this room.
I'm designing a collaborative web application that uses django-channels for websocket communication between the browser and the server. A room can be joined by more than one user and every user should be aware of every other user in the room. How would I go about achieving this using django-channels (v2)?
I already went through the documentation and a few example projects available online but none of them have added a similar functionality. I also know about django-channels-presence but the project doesn't seem to be actively maintained so I didn't really bother looking into examples using that.
Here's what I've come up with so far:
- For every room, I create an object in the database and those objects can keep track of the users that are in the room. So for e.g in the WS consumer's connect() method I could do a get_or_create_room() call and room.add_participant(self.user_name) (or fetch this from the scope) and in the disconnect() method I could remove myself from the room. The problem with this, however, is that I might end up creating race conditions? I think? Also since I'm fetching objects from the ORM, I have to make sure that every time, before using this object I have to re-fetch it from the DB because it can (and will) become outdated quickly. This doesn't seem ideal at all.
- Another way I can think of is attaching data to self.channel_layer in the consumer where I can do something like setattr(self.channel_layer, f'users_{room_id}', {}) and maintain this dictionary for every user entering and leaving. This again doesn't sound very safe and I didn't see anyone using this so I'm unsure.
Any help regarding this would be appreciated. I'd also like to be able to see how existing applications do this if anyone can point me to one?
so in short there is no way to ask channels for the members in a group so you either need to:
Write some info into the db, with a timestamp so that you can see if it is old
or
send a message every (n seconds) over the channel group (machine readable item with the users id) then your consumers (or frontend) can maintain a list of users and filter this to those that have a resent timestamp. The disadvantage here is it might take a few seconds to detect all the users in a chat room.
You can't do anything like writing to a dict or global object since this is not shared over all the consumers.
Related
Context:
I was going through various guides, tutorials and also posts here in the stackoverflow.
I need to handle process, e.g., - “pick topic —> show author list —> delete all —> ask confirmation —> show result —> go back to author list”
The obvious (and simplistic) approach is to create sets of views for each process.
And save process state in session variables or pass via URL-s (however, I discovered this method can be very brittle if too many information is passed). Also I need to tell each view where to go next, and this mushrooms into a bulky chain of instructions repeated for each URL request.
Instead, I want two extra things:
encapsulate a process at single place
re-use views, e.g. to re-use Topic List view to pick a single topic. That is, to work in “picker mode”. (btw, if I try to do this with multiple view classes, the next view class needs to know what to do and where to return…)
I also checked django workflow libs, and so on. and still not convinced.
Question:
if I create global object to encapsulate process and reference it from the current session - is this a good idea? My main concern is that - as sessions come and go, who will be cleaning up this global object?
is it possible to somehow make this clean up automatic? that is, when session goes away, some method is called where I can clean up or help GC to collect unneeded object? Like C++ destructors?
after working further with code, it occured to me that if I add global object to the session (and nowhere else) - it must be garbage collected in due course, because session itself is managed by Django.....
also, reading https://docs.djangoproject.com/en/3.1/topics/class-based-views/intro/ in my 3rd pass, found that Django's as_view() instatiates a new instance of class based views on each HTTP request.
so, everything is per request basis, and data will be transient. So only way to maintain state across HTTP requests is to either persist in the database or use sessions (or keep passing "state" from each request to request via URL parameters, but it is bulky, unsafe. my understanding is that this is a fallback mechanism if cookies are not allowed and session can be simulated via this way, e.g. PHP does it).
I am new to Django and want to know deeper about the concept of signals.
I know how it works but really don't understand when should one really use it.
From the doc it says 'They’re especially useful when many pieces of code may be interested in the same events.'
What are some real applications that use signals for its advantage?
e.x. I'm trying to make a phone verification after user signup. Because it can be integrated inside the single app and the event that interested for the signal is only this 'verify' function, therefore I don't really need signal. I can just pass the information from one view to the other, rather than using pre_save signal from the registration.
I'm sorry if my question is kind of basic. But I really want to know some insight what is the real application, in which many codes interested in one particular event and what are some trade off in my application.
Thanks!!
Often signals is used when you need to do some database-specific low-level stuff. For example, if you use ElasticSearch for better searching documents on your site, you may want to automatically update search indexes, when new document is created or old one was edited.
Also you may have some complex logic of managing database objects. For example, you may need some specific logic of deleting object. For example, when user is deleted, you may want change all the links to his profile by some placeholder, or when new message is created or other action is performed by user, you want to update "last visited" field in user's profile and there's no direct relation between this action and updating the profile.
But when you're just implementing business-logic as in your example with verification, you don't need to use signals, because you don't need any universal logic related to deleting/creating/editing any object: you have a certain object with which you work and can do stuff directly.
I want to use third party's REST API providing real-time foreign exchange rates in my django app which should continuously show changing exchange rates.
my code works but only on every page reload. but I want my code to be running continuously and showing exchange rate on page even if the page is not reloaded.
def example(request)
RATE__API_URL = 'REST API url'
while True
rate = requests.get(RATE__API_URL).json()
b = rate['rates']['EURUSD']['rate']
context = {'b': b}
return render(request, 'example.html', context)
on my example.html
<h1>
{{b}}
</h1>
code is running and does not show any errors
There are a few ways you can solve your requirement and none of them are the "right way", also much of it depends of what you have in your code, so I'll try to lay them out for you, and given the extent of what needs to be done while providing some links so you can work on it, but I will not give code because you'll require a fair amount of tailored code (sorry for that) and the references are good enough for you to develop your own solution.
The first thing you have to keep in mind is than you'll need to solve two really big and really different requirements:
The first part of your solution is retrieving the data from the source in a timely manner. The second part is to have a way to update the data in the template without the need for the user to reload the page.
To retrieve the data you said you already have an API where you'll get the data, but your code is not an efficient way to approach this, and it also may generate a risk because it is prone to hit too many times the API server; the best way I can think of would be if the API has webhooks or push notifications to which you can subscribe (which I doubt), the second best choice is to implement a Celery task, that way you will be calling the data regularly, and you'll not eat the API service resources.
With the first part out of the way, what you have left to do is to implement a way to call regularly from the UI for the newest data. Perhaps the simplest way to solve it is to implement an asynchronous call with Javascript/JQuery embedded in a script inside your template, but remember:
For this to work you'll need a model to store the data (If you don't
have an use for historic data, then just keep the most recent
one).
You'll need a view that exposes the data to your UI call (one that sends a JSON)
Another solution is to implement websockets, and the best way to achieve this for Django is using django-channels. You'll have to implement two main things:
In the backed you need to define the consumers flow so you can send
the data to the UI.
In the template you need to implement the websocket connection and a way to handle the updating part of the data for the user.
If you choose this way, and given than you don't need historic data, you can obviate the model and go straight from the Celery task to the UI through the consumer.
I'm building a magento (1.9CE) store which needs to interface with another system and I could use some guidance.
Although not particularly relevant, I'm communicating with the 'other' system using web services (it's on another server) but what I need help with is finding the places where I need to put in code to do what I want.
There are three major functions that I need to implement:-
When a user clicks on the product detail page I need to make a call to check the stock levels on the other system, update the magento stock levels and THEN display the product detail page.
When a sale is completed, I need to send details of that sale to the other system.
When a new product is added I need to communicate with the other system. This may be a bit more complex because there are a few checks I need to do during the 'add product' process, for example, check the SKU is valid, that tghe product doesn't already exists, etc. I think until I start coding this I shan't realise the full extent of this functionality!
Any guidance gratefully received!
Even though this might (and probably will) dramatically slow down your store, if you want real-time information, I guess the easiest way would be with observers.
You can use catalog_controller_product_init_before: This will trigger when the product detail page is starting loading, so you should be able to upload the stock at this point, before the page has finished loading, so that if there is no stock it will not be buyable, which I guess that's what you want.
You can use sales_order_place_after: This will be triggered after a new order has been placed and saved in the database.
You can use catalog_product_new_action or catalog_product_save_after: Depending on how you create your products the first one might not be triggered. The second one will always be triggered once a product (new or existing) has been saved, so at this point you will need to check if the product is new or existing, and do your stuff depending on that.
For an example of how to create an extension and usage of observer events, check this out.
I hope it helps!
I have the following situation: there is a table in the DB that is queried when the form loads and the retrieved data is filled into a DataGridView via the DataTable underneath. After the data is loaded the user is free to modify the data (add / delete rows, modify entries).
The form has 2 buttons: Apply and Refresh. The first one sends the changes to the database, the second one re-reads the data from the DB and erases any changes that have been made by the user.
My question is: is this the best way to keep a DataGridView synchronized with the DB (from a users point of view)?
For now these are the downsides:
the user must keep track of what he is doing and must press the button every while
the modifications are lost if the form is closed / app crash / ...
I tried sending the changes to the DB on CellEndEdit event but then the user also needs some Undo/Redo functionality and that is ... well ... a different story.
So, any suggestions?
I would say that the way you are currently doing it is fine. If you start attempting to update the database while the user is still making edits you can run in to issues updating or modfiying things that the user may ultimately decide they did not want to change. Additionally this has the chance to greatly increase the number of database calls.
Forcing the user to click apply helps ensure that only the changes the user actually wants are sent to the database.
As for losing the changes if the app crashes before applying them, I would be more concernced with why the app is crashing.
The only important thing to remember is that you should refetch the data before saving it and the refetched data should still match the data you originally displayed to the user. If it doesn't, someone else made a change your user will be unknowingly overwriting. Your users probably will not like that.
How you handle this is dependent on what your client needs in their database.