Django Session Persistent but Losing Data - ajax

I have been working for hours trying to understand the following problem: I have a user send an Ajax request to dynamically send a form and record that the number of forms to read on submission has increased. Toward this end I use request.session['editing_foo'] = { 'prefix_of_form_elements' : pkey } so that I can associate them with the database for saving and loading (-1 is for new forms that haven't been saved yet).
However, when I use the following code (see bottom) I get the following bizarre output:
1st Click:
{} foousername
next_key 1
1
{u'1-foo': -1}
2nd Click:
{} foousername
next_key 1
1
{u'1-foo': -1}
3rd Request:
{} foousername
next_key 1
1
{u'1-foo': -1}
What the heck is going on?
id_fetcher = re.compile(r'\d')
#login_required
def ajax_add_foo(request):
def id_from_prefix(key):
return int( id_fetcher.search(key).group(0) )
if 'editing_foos' not in request.session:
print "reinitializing"
request.session['editing_foos'] = {}
print request.session['editing_foos'], request.user
keys = request.session['editing_foos'].keys()
if len(keys) == 0:
next_key = 1
else:
print [ id_from_prefix(key) for key in keys ]
next_key = max([ id_from_prefix(key) for key in keys ]) + 1
print "next_key", next_key
fooform = FooForm(prefix=next_key)
print next_key
request.session['editing_foos'].update( {create_prefix(FooForm, next_key) : -1 } ) # This quote is new and has no pkey
print request.session['editing_foos']
return render_to_response( 'bar/foo_fragment.html',
{'fooform' : fooform, },
context_instance=RequestContext(request))
Thank you all very much!
Note: This is a followup to a previous question concerning the same source code.

I don't think I completely understand the question, but you may want to take a look at which session engine you're using
if you're using the cache session engine you need to make sure you have caching properly set up (for instance the dummy cache would just throw out your session data)
another possibility is that your session isn't being saved because you're not changing the session, you're changing a mutable object that is stored in the session. you can try forcing the session to save by adding this somewhere in your view:
request.session.modified = True

Related

How to detect the end_interaction signal using the dialogflow_cx python library?

I am using the DialogFlow CX python library for an agent integration. Once I send a request through detect_intent, I want to be able to check in the response for a flag that determines if the interaction with the agent has ended.
For this, I found a property within the ResponseMessage data type response called end_interaction. I tested this with one of my agents, and effectively once the interaction ends, I can see the end_interaction within the array of response messages:
# inspecting query_result.response_messages
[
text {
text: "Goodbye."
},
end_interaction {
}
]
Now, the problem is that I want to trigger some actions whenever we receive the signal, but since the end_interaction field is being sent empty whenever I try to check it returns me False:
# Both response messages from the example above return False under a bool
bool(query_result.response_messages[0].end_interaction) == False # text message response
bool(query_result.response_messages[1].end_interaction) == False # end_interaction signal
I have tried many things, such as checking with isinstance and hasattr, but they return True for all scenarios since the ResponseMessage data type always has an end_interaction attr.
Any help for finding how to detect and check for this signal is highly appreciated! Thanks!
To detect and check for the end_interaction field, you can use the following in your detect_intent:
any("end_interaction" in d for d in response.query_result.response_messages)
Please note that this will return True if the end_interaction field is found in the response_messages list and False if not. You can use this to determine if the interaction with the agent has ended.
Here is a python sample code of the detect_intent with the end_interaction field for your reference:
def detect_intent_texts(agent, session_id, texts, language_code):
session_path = f'{agent}/sessions/{session_id}'
print(f"Session path: {session_path}\n")
client_options = None
agent_components = AgentsClient.parse_agent_path(agent)
location_id = agent_components["location"]
if location_id != "global":
api_endpoint = f"{location_id}-dialogflow.googleapis.com:443"
print(f"API Endpoint: {api_endpoint}\n")
client_options = {"api_endpoint": api_endpoint}
session_client = SessionsClient(client_options=client_options)
for text in texts:
text_input = session.TextInput(text=text)
query_input = session.QueryInput(text=text_input, language_code=language_code)
request = session.DetectIntentRequest(
session=session_path, query_input=query_input
)
response = session_client.detect_intent(request=request)
print("=" * 20)
print(f"Query text: {response.query_result.text}")
response_messages = [
" ".join(msg.text.text) for msg in response.query_result.response_messages
]
print(f"Response Messages:\n {response.query_result.response_messages}")
print(f'End of interaction: {any("end_interaction" in d for d in response.query_result.response_messages)}')
Here is the result:

Mongo db won't connect with my code or write to the database

This is my code and I'm trying to get it so when a user does the add command, it stores their id and number they have used the command, but this isn't working, please can someone help.
num = 0
#client.command()
async def add(ctx):
global num
num += 1
await ctx.send('non')
mongo_url = "mongodb+=true&w=majority"
cluster = MongoClient(mongo_url)
db = cluster["mongo_url "]
collection = db["mongo_url "]
ping_cm = {"bank":num}
collection.insert_one(ping_cm)
I assume your mongo_url token is incorrect, it should have your name and password and db that you are storing it to, but you are accessing your token currently instead of your bank name, whatever that is called,
for example,
db = cluster["mongo_url "] #This has been set to your token, your mongo_url which won't do anything
You have used "bank" in other parts of your code, which is really confusing but I assume thats what you want to do and access, this will then store it in different rows for each user id who uses the command
num = 0
#client.command()
async def add(ctx):
global num
num += 1
await ctx.send('non')
mongo_url = "YOUR_MONGO_DATABASE_URL"
cluster = MongoClient(mongo_url)
db = cluster["bank"]
collection = db["bank"]
ping_cm = {"bank":num}
collection.insert_one(ping_cm)
await ctx.channel.send("Bank Updated!")
Make sure you are providing your mongo url "properly" otherwise the code won't be working at all they should look like this: eg.
EXAMPLE ONLY
mongo_url = "mongodb+srv://name:password#bank.9999000.mongodb.net/bank?retryWrites=true&w=majority" #EXAMPLE
You can get the URL when you go to the database you want to connect to, the click manage > db_url and copy that where I have included “YOUR_MONGO_DATABASE_URL" that should work if it is correct

cherrypy: how to get all active sessions (storage_type = "file")

My aim is to track all logged user, in a website powered by cherrypy.
With sessions stored in RAM (tools.sessions.storage_type = "ram"), i can get the information through :
cherrypy.session.cache.values()
But with sessions stored in a file (tools.sessions.storage_type = "file"), trying to do the same, i get:
AttributeError: 'FileSession' object has no attribute 'cache'
How to access the information stored in the session files ?
EDIT :
The proposition of Andrew Kloos is to load the sessions files from the directory (given by tools.sessions.storage_path), and un-pickle the files.
This works in most cases, but sometimes, one of the files is still LOCKED, and unpickling fails.
On the other hand, I can not believe that there is a session object for the current session (namely cherrypy.session), and that there is no available object for the other sessions, and that one is obliged to go through the sessions files ...
Ok looking at the cherrypy/lib/sessions file I see that getting the session values runs this load function...
def _load(self, path=None):
if path is None:
path = self._get_file_path()
try:
f = open(path, "rb")
try:
return pickle.load(f)
finally:
f.close()
except (IOError, EOFError):
return None
So you just need to mimic that but also loop through all the sessions in the session file folder. Try something like this...
import cherrypy
from cherrypy._cpcompat import pickle
import os
class HelloWorld(object):
#cherrypy.expose
def asdf(self):
# loop through all the files in the sessions folder
for FileName in os.listdir(os.path.abspath(os.path.dirname('sessions')) + '/sessions'):
# **EDIT**
if(FileName.find('.lock') == -1)
f = open(os.path.abspath(os.path.dirname('sessions')) + '/sessions/' + FileName, "rb")
sessiondata = pickle.load(f)
print(sessiondata[0]['FirstName'])
# **EDIT**
cherrypy.session['FirstName'] = 'adsdf'
return 'hi'
cherrypy.config.update({
'tools.sessions.on' : True,
'tools.sessions.storage_type' : 'file',
'tools.sessions.storage_path' : 'sessions'
})
cherrypy.quickstart(HelloWorld())
Hope this helps!
I'll just give you a simple one liner using python.
sessions = os.listdir('./tmp/sessions')
sessions = filter(lambda session: '.lock' not in session, sessions)
First, you list the session files in the directory.
Then, you filter out the lock files.

How to make 'perishable' link in Tornado

i want to make a link that is valid only for 24 hours, this is for a validation purpose, so my question is simple:
How do i make this link valid only for this time; i've a hint:
Get the epoch time.
Make a link using only this value: something.com/time/1359380374
When the user clics on the link, extract this value and compare.
I hear about Hash values? why? we cant get the time from the hash value (invert the process) so how this is done?
Your best bet is to have the users email send as an argument and then query the database to see if their link has expired:
Requested link query: update users set locked_stamp = now();
Request url: http://yourdomain.com/?email=useremail
Query: select true from users where email = '$email' and locked_stamp > now()-interval 1 hour and now() limit 1
Result: You have a person requesting within the hour with email: $email.
I have a script that using base64 to encode the timestamp... but its not secure by any means.
import tornado.web
import base64, re, time
import sys
def get_time():
"""Method used to get the current time in b64"""
return base64.b64encode(str(int(time.mktime(time.localtime()))))
class WebHandler(tornado.web.RequestHandler):
def get(self, _time):
timecheck = base64.b64decode(_time)
try:
#require it to be all digits
assert re.match('^\d+$', timecheck) is not None
# Must be within 1 hour: greater then 1 hour ago and less then now
assert int(timecheck) > int(time.mktime(time.localtime()))-3600 and \
int(timecheck) < int(time.mktime(time.localtime()))
except AssertionError:
raise tornado.web.HTTPError(401,'Woops! Unauthorized.')
else:
self.write('Pass')
# Route
application = tornado.web.Application([
(r"/([^\/]+)/?", WebHandler),
])
if __name__ == "__main__":
application.listen(8889)
tornado.ioloop.IOLoop.instance().start()
the same way it sets secure cookies:
signed_message = self.create_signed_value(secret, name, value)
Then you can check it:
message = self.decode_signed_value(secret, name, value, max_age_days=31, clock=None,min_version=None)
Secret should be a long random number, but you only need one per app. min_version could be DEFAULT_SIGNED_VALUE_VERSION (which is currently 2).
Don't roll your own solution. Use the one in the library. It's there. It works.

Django Form Preview - Adding the User to the Form before save

class RegistrationFormPreview(FormPreview):
preview_template = 'workshops/workshop_register_preview.html'
form_template = 'workshops/workshop_register_form.html'
def done(self, request, cleaned_data):
# Do something with the cleaned_data, then redirect
# to a "success" page.
# data = request.POST.copy()
# data['user_id'] = u'%s' % (request.user.id)
# cleaned_data['user'] = u'%s' % (request.user.id)
#f = self.form(cleaned_data)
#f = self.form(data)
#f.user = request.user
f = self.form(request.POST)
f.save()
pdb.set_trace()
return HttpResponseRedirect('/register/success')
As you can see, I've tried a few ways, and that have been commented out. The task is apparently simple: Add the user from request to the form before save, and then save.
What is the accepted, working method here?
If the user can't be modified, I would say it shouldn't even be included in the form in the first place.
Either way, using the commit argument to prevent the resulting object being saved immediately should work (assuming FormPreview uses ModelForm):
obj = form.save(commit=False)
obj.user = request.user
obj.save()

Resources