Managing global objects in Django - django

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).

Related

Best Practice Using Django Signal (For user authentication?)

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.

django-channels: keeping track of users in "rooms"

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.

MVC protecting accessing some action

I have a question regarding some action accessing, i'm not talking here about authorization etc, but more about the direct access to actions.
Basically i have 2 question, 1 general and 1 more contextual:
Situation imaging i have an action : MyArticles/DeleteArticle/id
1) How can i prevent that if someone will just put this url with a proper id remove article? How can i say that it can only be used with a button on my website? And should this action be a get or post?
At this moment i use $.ajax and GET method ....
2) Now imagine i have many people, and if all th ppl are registered, they can delete each others article, what if i want to avoid that and let users only delete their own articles, because at this moment for example if they can guess the id they can directly access the action with id and delete it.
Can anyone provide explanation and some tips about that?
i'm not talking here about authorization etc
Yes, you are. The authorization to delete the article should take place within the action itself, it's not the responsibility of the calling code or of any UI which displays a link to the action.
How can i say that it can only be used with a button on my website?
I imagine any approach to that is going to complicate the issue tremendously. Understand how HTTP requests work... Your application isn't making the request to the action, the user is. They're doing so (in the general case) by clicking a link on an interface provided by your application, but the request itself is coming from the user. (Well, from the user's web browser, which is in their control and not yours.)
The most straightforward approach to this is to encapsulate authorization in the action itself (or, better still, in the model functionality being invoked by the action... but logically that's still part of the "request" being performed).
When you expose a piece of functionality which not everybody should be able to invoke, put the authorization on the functionality itself instead of on the UI which invokes it. That way no matter how it's invoked it always maintains the authorization, instead of just assuming that some other component maintained it.
You have a lot of control in MVC with respect to the USER. To allow a user to delete only his own work, you must remember in the database who wrote what. If this is the case - and you know it, a simple if statement in the beginning of the action will do the trick.

django: routing users through a complex app with class-based views

I'm an advanced beginner at django and python. I'm writing an app to handle registration and abstract submission for a conference, and I'm trying to use class-based views. Users get an emailed link that includes their registration code in the url. Starting at this url, users move through a series of views that collect all the necessary info.
The complication comes from the fact that users often stop half way through, and then want to complete the process several days or weeks later. This means that they might continue from the current page, or they might just click that original link. In addition, after several weeks they might have missed certain deadlines, so, e.g., they can no longer submit an abstract (but they can still register). Along the way, they have checked or unchecked various options that also influence the path they should take through the app.
My question is: where is the best place to put the logic that determines if the user is currently allowed to view that page, and if not, the best url to redirect them too? I thought I would create a custom view class that, e.g., overrides the dispatch method to include global checks (e.g., is conference registration open?), and then subclasses could add additional checks (e.g., has the user entered all the necessary info for her abstract?). The problem I ran into was that the checks were run in the wrong order (I want base class checks run first). I then started investigating custom view decorators or custom middleware. At this point I realized I could use some expert advice about which approach to take. (If it matters, I am not using the django authentication system.) Thanks in advance.
Maybe the form wizard could help you managing the viewing sequence.
In general django greybeards advocate keeping row-wise logic in Models, and table-wise logic in Managers, so it seems appropriate to keep complex view logic in a master view class.
The wizard class can help maintain the order of the views, but to resume an out-dated session you may need to do some model saves (which could get too complex very quickly) or some cookie handling.
In the past, when presented with a similar situation, I took the simplest route and separated user registration and the task that the user wants to perform (event registration). The user registers once but if they fluff up the event registration, they just have to log back in at a later date and do it again (their hassle - not yours!).

Application logic in view code

Should I be writing application logic in my view code? For example, on submission of a form element, I need to create a user and send him an activation email. Is this something to do from a view function, or should I create a separate function to make it easier to test down the road? What does Django recommend here?
I found it very hard to figure out where everything goes when I started using django. It really depends on the type of logic you are writing.
First start with the models: model-methods and managers are a good place to perform row-level logic and table level logic i.e. a model manager would be a good place to write code to get a list of categories that are associated with all blogposts. A model method is a good place to count the characters in a particular blogpost.
View level logic should deal with bringing it all together - taking the request, performing the necessary steps to get to the result you need (maybe using the model managers) and then getting it ready for the template.
If there is code that doesn't fit in else where, but has a logical structure you can simply write a module to perform that. Similarly if there are scraps of code that you don't think belong, keep a utils.py to hold them.
You shouldn't perform any logic really in your templates - instead use template tags if you have to. These are good for using reusable pieces of code that you you neither want in every request cycle nor one single request cycle - you might want them in a subset (i.e. displaying a list of categories while in the blog section of your website)
If you do want some logic to be performed in every request cycle, use either context processors or middleware. If you want some logic to be performed only in one single request cycle, the view is probably the place.
TLDR: Writing logic in your view is fine, but there are plenty of places that might be more appropriate
Separating the registration code into it's own function to make testing easier is a good reason. If you allowed admins to register users in a separate, private view, then a registration function would be more DRY. Personally, I don't think a little application logic in the code will do to much harm.
You might find it instructive to have a look at the registration view in the django-registration app -- just to see how it's written, I'm not saying you should or have to use it. It has encapsulated the user registration into it's own function (there's a level of indirection as well, because the registration backends are pluggable).