Testing a session variable - django

I came across Django request.session; I know how to set and test it for a specific value.
request.session['name'] = "dummy"
and somewhere I check
if request.session['name'] == "dummy" :
#do something
But, now I have to check whether the session variable was even set in the first place? I mean how can I check whether there exists a value in the request.session['name'] is set?
Is there a way to check it?

Treat it as a Python dictionary:
if 'name' in request.session:
print request.session['name']
How to use sessions: Django documentation: How to use sessions

get will do all the work for you. Check if the key exists, if not then the value is None
if request.session.get('name', None) == "dummy":
print 'name is = dummy'

Another way of doing this is put it in try.
In this the third example code snippet
if you apply del operation in a session variable it which does not exist, so it throws KeyError.
so check it like this.
try:
print(request.session['name'])
except KeyError:
print('name variable is not set')

Related

How to set the incoming object to true or false in Django

What I want to do is write "True" if there is data suitable for the filters made, otherwise "False"
if ChartSimilar.objects.get(chart=pk, year=year):
print('True')
else:
print('False')
charts.models.DoesNotExist: ChartSimilar matching query does not exist. I get an error
Here the got query does not exist because the object is not available with a particular id so it's an exception. You can handle it by using try, except block.
try:
ChartSimilar.objects.get(chart=pk, year=year)
print('True')
except:
print('False')

Django list matching with if == statement

I'm hoping this is super simple. I just started playing around with Django for fun and have been playing around with making a search engine.
I'm setting a temporary list in a views.py file so I set it like this:
tempsearch_list = Name.objects.filter(
Q(name__iexact='Name Not Found')
)
Later in my code I want to see if it's the same as I originally set so I'm trying to do this:
if tempsearch_list == 'Name Not Found':
This never matches. Even if I put it as the next statement after I set it. What am I doing wrong here. This has to be super simple. I've been trying different things for more time than I'd like to admit.
you filtered the objects as tempsearch_list = Name.objects.filter(Q(name__iexact='Name Not Found')) and later on you when you want to compare if tempsearch_list equals to Name Not Found, you don't need any if statment just use if tempsearch_list.exists().
tempsearch_list.exists() will return True if there was an object named Name Not Found else it returns False
how do I check the query set is still equal to the original way it was set
The queryset(tempsearch_list) won't changed unless you reassign it, and that would be always update in case of adding, editing or removing a Name. but again if you wondering, you can compare it with fresh queryset as if tempsearch_list == Name.objects.filter(Q(name__iexact='Name Not Found'))
Ok, so I appreciate everyone who responded. I think this helped a lot. Here's what I did for now. There's probably a better way to do this but it works
tempsearch_queryset1 = Name.objects.filter(
Q(name__iexact='Name Not Found')
)
tempsearch_queryset2 = Name.objects.filter(
Q(name__iexact='Name Not Found')
)
if set(tempsearch_queryset1) == set(tempsearch_queryset2):
Note. Without the set commands it does not work. This doesn't work:
tempsearch_queryset1 = Name.objects.filter(
Q(name__iexact='Name Not Found')
)
tempsearch_queryset2 = Name.objects.filter(
Q(name__iexact='Name Not Found')
)
if tempsearch_queryset1 == tempsearch_queryset2:
Your problem is compare Queryset and string (Queryset is list of model so you can access model by index and access model field by . like model.name
you can do that like
for tempsearch in tempsearch_list :
if tempsearch.name == "Name Not Found":
You should compare Charfield like name field with string

django orm: Check if obj is in queryset

How can I check whether an obj is in a queryset or not?
I tried this:
self.assertIn(obj, list(MyModel.objects.filter(...))
But it does not work in my case.
AssertionError: <MyModel 137 'unclassified'> not found in
[<MyModel 1676 'foo'>, ..., <MyModel 137 'unclassified'>, ...]
I don't understand it, since it is in the list.
How about
self.assertTrue(MyModel.filter(...).filter(pk=obj.pk).exists())
First of all, it should be MyModel.objects.filter(...). If you omit the .objects, you should've gotten a different error, so I'm assuming you did include it but just forgot it in the question.
If obj is actually in the QuerySet returned, what you did should have worked as Django model instances provides an equal comparator which compares both the type and the primary key. list() is not required around the QuerySet, though it should still work if you used it.
From the Django 1.5 source:
def __eq__(self, other):
return isinstance(other, self.__class__) and self._get_pk_val() == other._get_pk_val()
If it still doesn't work, there are a few possible causes:
The type doesn't match. In this case, it doesn't matter even if the object pk exists in the QuerySet's object pks. (You cannot compare apples to oranges)
There is no such object in the database (i.e. it hasn't been saved yet)
The type matches but the object is not in the QuerySet (i.e. filtered out)
You overrode the __eq__ method and did something weird. Or you overrode the default manager .objects with some custom filter. This scenario is outside the scope of this answer and if you did this, you should probably know how to fix it.
To help you diagnose which is the case, try this:
self.assertTrue(isinstance(obj, MyModel))
# 1. If it fails here, your object is an incorrect type
# Warning: the following tests can be very slow if you have a lot of data
self.assertIn(obj.pk, MyModel.objects.values_list('pk', flat=True))
# 2. If it fails here, the object doesn't exist in the database
self.assertIn(obj.pk, MyModel.objects.filter(...).values_list('pk', flat=True))
# 3. If it fails here, the object did not pass your filter conditions.
self.assertIn(obj, MyModel.objects.filter(...))
# 4. If it fails here, you probably messed with the Django ORM internals. Tsk tsk.
Just with, note the .all()
queryset_result = MyModel.filter(...).all()
if obj in queryset_result:
//obj is in the queryset
The "in" fails because the objects aren't actually equal, as equality is object identity by default. If you want "in" to work, you'd have to implement __eq__ accordingly on your model.
If you don't want to do that, you can check by comparing the pk, like so
self.assertIn(obj.pk, [o.pk for o in MyModel.filter(...)])
I think This is very simple way get to find out object present in queryset or not.
First Example:
obj_list = MyModel.filter(...)
if obj in obj_list:
print "obj in queryset"
else:
print "not in queryset"
Second Example:
obj_list = MyModel.filter(...)
try:
obj_list.get(pk=obj.id)
except:
# If try get success obj is present in query set else your this except get executed.

how to use django object in session

I was wondering how i can check if a object is in session and depending on that, do something.
def login_character(request, character_name):
request.session['character'] = Character.objects.get(name=character_name)
return HttpResponseRedirect(reverse('index'))
some other function:
if request.session['character']:
print request.session['character'].name
else:
print "nothing to see here"
How i try it, i kepe getting back to a KeyError
session uses the standard Python dictionary interface, so you want either:
if 'character' in request.session:
print request.session['character'].name
else:
print "nothing to see here"
Or, in some cases, request.session.get('character') if you just want to have a default value if the key is not present.

Modifying Dictionary in Django Session Does Not Modify Session

I am storing dictionaries in my session referenced by a string key:
>>> request.session['my_dict'] = {'a': 1, 'b': 2, 'c': 3}
The problem I encountered was that when I modified the dictionary directly, the value would not be changed during the next request:
>>> request.session['my_dict'].pop('c')
3
>>> request.session.has_key('c')
False
# looks okay...
...
# Next request
>>> request.session.has_key('c')
True
# what gives!
As the documentation states, another option is to use
SESSION_SAVE_EVERY_REQUEST=True
which will make this happen every request anyway. Might be worth it if this happens a lot in your code; I'm guessing the occasional additional overhead wouldn't be much and it is far less than the potential problems from neglecting from including the
request.session.modified = True
line each time.
I apologize for "asking" a question to which I already know the answer, but this was frustrating enough that I thought the answer should be recorded on stackoverflow. If anyone has something to add to my explanation I will award the "answer". I couldn't find the answer by searching based on the problem, but after searching based upon the answer I found that my "problem" is documented behavior. Also turns out another person had this problem.
It turns out that SessionBase is a dictionary-like object that keeps track of when you modify it's keys, and manually sets an attribute modified (there's also an accessed). If you mess around with objects within those keys, however, SessionBase has no way to know that the objects are modified, and therefore your changes might not get stored in whatever backend you are using. (I'm using a database backend; I presume this problem applies to all backends, though.) This problem might not apply to models, since the backend is probably storing a reference to the model (and therefore would receive any changes when it loaded the model from the database), but the problem does apply to dictionaries (and perhaps any other base python types that must be stored entirely in the session store.)
The trick is that whenever you modify objects in the session that the session won't notice, you must explicitly tell the session that it is modified:
>>> request.session.modified = True
Hope this helps someone.
The way I got around this was to encapsulate any pop actions on the session into a method that takes care of the details (this method also accepts a view parameter so that session variables can be view-specific):
def session_pop(request, view, key, *args, **kwargs):
"""
Either returns and removes the value of the key from request.session, or,
if request.session[key] is a list, returns the result of a pop on this
list.
Also, if view is not None, only looks within request.session[view.func_name]
so that I can store view-specific session variables.
"""
# figure out which dictionary we want to operate on.
dicto = {}
if view is None:
dicto = request.session
else:
if request.session.has_key(view.func_name):
dicto = request.session[view.func_name]
if dicto.has_key(key):
# This is redundant if `dicto == request.session`, but rather than
# duplicate the logic to test whether we popped a list underneath
# the root level of the session, (which is also determined by `view`)
# just explicitly set `modified`
# since we certainly modified the session here.
request.session.modified = True
# Return a non-list
if not type(dicto[key]) == type(list()):
return dicto.pop(key)
# pop a list
else:
if len(dicto[key]) > 0:
return dicto[key].pop()
# Parse out a default from the args/kwargs
if len(args) > 0:
default = args[0]
elif kwargs.has_key('default'):
default = kwargs['default']
else:
# If there wasn't one, complain
raise KeyError('Session does not have key "{0}" and no default was provided'.format(key))
return default
I'm not too surprised by this. I guess it's just like modifying the contents of a tuple:
a = (1,[2],3)
print a
>>> 1, [2], 3)
a[1] = 4
>>> Traceback (most recent call last):
... File "<stdin>", line 1, in <module>
... TypeError: 'tuple' object does not support item assignment
print a
>>> 1, [2], 3)
a[1][0] = 4
print a
>>> 1, [4], 3)
But thanks anyway.