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.
Related
I have flow where users can create (model) forms. If form is valid, object gets saved and flow continues, but selection is in multiple pages. I need to keep current state of created object, which cannot be saved before it's completely valid.
One thing I can do is to always pass things around those views in the ModelForm to make sure, that user never loses data, but I also wanna make sure, that if he leaves the flow and comes back, he doesn't lose data, that he already entered previously.
That's why I decided I wanna save all the fields to session.
Is this correct approach?
How would you do this?
Where would you put this session logic?
What's best way of getting the fields from incomplete form to be saved?
Edit:
Please don't give me advice on how to use session, I am talking more about high level logic and architecture than specific implementation.
I should describe my flow a bit more. Model has 3 fields.
normal dropdown (foreign key referencing another model)
textfield
another foreign key, but this time not done by select, but it's own separate page with lots of filters to help user pick the right (foreign) model
Flow is not linear, because user can start in different parts of page.
Sometimes user can go to page, where he has first 2 fields + button "Browse", which takes you to selection page for 3rd field. Then after he selects field there, he comes back.
But sometimes he selects first this field and then comes to screen with 2 remaining fields, where he needs to fill those.
django-formtools offers a great way to do this using Form wizard.
The form wizard application splits forms across multiple Web pages. It
maintains state in one of the backends so that the full server-side
processing can be delayed until the submission of the final form.
More info here https://django-formtools.readthedocs.io/en/latest/wizard.html
to save in session:
request.session["variable_name"] = "value"
to get from session request.session["variable_name"]. sure you can use request.session.get("..") in both too
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.
This is may be an obvious question to a Django expert, but is there a way that I can save all user inputs (clicks through content without having to explicitly save every entry in a table). If this is possible, then how do I access it later?
If I have to create models, like this I can:
#(within a view function)
UserInputs.objects.get_or_create(user=request.user,
selection1=request.POST.get('selection1'),
id=request.POST.get('id')),
thumbs_up=request.POST.get('thumbs_up'),
thumbs_down=request.POST.get('thumbs_down'),
comments=request.POST.get('comments')
)
Is there an easier way to get it done? Because I have lots and lots of different user click inputs and specifying every one like this will really slow down my application.
Is this data by chance saved in one of the sessions tables? Or can we create a custom sessions table to do this?
In my app, i let the user create a record on clientside and fiddle with it prior to saving. The record is of a pretty complex model with a lot of realtionships. To edit the record, a modal dialog opens and displays a form.
Example scenario:
You've created a new record on client side. It's in the blank state.
Then you proceed to edit the record. You make changes to the form in the modal dialog and press OK. The record now is in state A.
Then you proceed to edit the record again, turning the record to state B. But this time you mess the form up and decide to Cancel.
When you hit Cancel, the record should revert to state A.
The problem is that this is an unsaved record and thus record.rollback() can not be used.
All i could think of is making a copy of a record and feeding it to the form. But most of the form's fields are bound to related records, thus, you'd have to clone the record's related records recursively. This is a huge hack that i don't want to go for.
Any simpler suggestions?
The approach I have used is based on the buffered proxy pattern within my controllers.
This way your controller can just throw away the buffer on cancel or apply the buffer to models and orchestrate model saves when the user OKs the changes.
Here is an ember package you can use to get started:
https://www.npmjs.com/package/ember-buffered-proxy
I am using Django's native Authorization/Authentication model to manage logins for my WebApp. This creates instances of the User model.
I would like to write a simple class-based-APIView that can tell me if a specific email is already used (IE: Is there already a user with the given email in my database?). The first time this API is called, it should get the matching User object from the DB. But subsequent times it is called, it should return it from the Memcache (if and only if, the underlying row in the database is unchanged). How can I do that??
Should I inherit from generic.APIView? Why or why not? What would the view look like? In particular I want to understand how to properly do the memcaching and cache-coherency checking. Furthermore, how would this memcaching scheme work if I had another API that modified the User object?
Thanks. I was unable to find detailed idiot-proof manual on using memcaching properly in Django.
Caching is perhaps the simplest part of django - so I'll leave that discussion to the last. The bigger problem is figuring out when your model changed.
You can decide what constitutes an update. For example, you might consider that only when a particular field is updated, then the cache is updated. Your cache update process should be limited to the writing/updating code or view. If you go about this method, then I would recommend django-model-utils and its StatusField - you can add this logic in save() method by overriding it; or implement it at the code that is updating models.
You can also do a simpler approach, that is, no matter what is updated - as long as save() is called, expire the cache and repopulate it.
The rest of the code is very simple.
Attempt to fetch the item from the cache, if the item doesn't exist (called a cache miss), then you populate the cache by fetching from the database. Otherwise, you'll get the item from the cache and then you save yourself a database hit.
The cache interface is very simple, you set('somekey', 'somevalue') you can optionally tell it when to expire the item. Then you try to get('somekey'), if this returns None, then its a cache miss (perhaps the item expired), and you have to fetch it and populate the cache. Otherwise, you'll get the cached object.