I'm building a small Django app. The user is to build up a list of pairs of strings, by repeatedly submitting a pair of forms. The list is stored as value of a session variable.
But there is a problem. When the list is loaded by the view, the strings which were to be elements of the pairs in the list wind up getting prefixed by the letter u. So for example as elements of the list instead of
['a','b']
['c','d']
we get
[u'a',u'b']
[u'c',u'd']
My impression is that Django treats values of session variables as strings. So maybe the problem has something to do with the conversion of lists?
Here is the source of the view:
def plisting(request):
if 'plist' not in request.session:
request.session['plist']=[]
plist = request.session['plist']
if 'entry' in request.POST:
entry = str(request.POST['entry'])
key = str(request.POST['key'])
plist = plist+[[entry,key]]
request.session['plist'] = plist
return render(request,'evaluator/plisting.html',{'plist':plist})
The u at the beginning of the string returned to your view function just means that the strings are encoded in unicode. You need not handle it specially in your code. Accessing the list just normally will return you the expected strings.
This is what I mean:
>>> a = [u'a',u'b']
>>> b = [u'c',u'd']
>>> a[1]
'b'
>>> b[0]
'c'
As evident from the output, when you access the elements, you do not see the 'u' as part of the strings.
Hope this helps.
Related
I wonder if there is a way to create variables automatically using strings, e.g. I have the following code (which does not work properly in Python):
def function(lst1, string1):
lst2 = 'processed_' + string1
lst2 = [] #here I created a string called lst2, but I want to use the string as the variable name.
for i in range(len(lst1)):
if abs(lst1[i]) >= 0.0001 :
lst2.append(i)
return lst2
function(list1, 'price') # list1 is a list which contains the index for column numbers, e.g., [1,2,3]
function(list1, 'promotion')
function(list1, 'calendar')
I would expect that with the function I would be able to create lists such as processed_price, processed_promotion, and processed_calendar, and the function will return these lists.
However the code above would not work as in Python. I wonder how should I write the code properly to achieve the same goal?
getattr(object, name, [default])
setattr(object, name, value)
To get or set values for a variable named via a string, use one of the above as appropriate. However, any time you use user input, it can be a source of injection attacks — the user could use a name that you did not expect them to use but the name is valid so the user gets access to data they should not have access to.
So it is usually advisable to use the user input as a key into a dictionary you define.
dictionary = {
'apple': 'my_value'
}
dictionary[user_input] = 'their_value'
I have a QueryDyct object (request.data) in my method and want to do some modifications on it so I have copied it: data_dict = data.copy(). On creating an empty list in it, it creates an additional inner list:
data_dict['emails'] = []
data_dict['emails'].append('foo#mail.com')
data_dict['emails'].append('bar#mail.com')
Instead of crating an empty list and append data into it, it creates a list of list, and appends data into inner list:
On PyCharm watch it is shown as:
Why it behaves like this?
And for the further processing it is treated (by django validator) as an email with address ['foo#mail.com', 'bar#mail.com'], but I want to have two different emails with appended addresses.
How can I construct normal empty list in QueryDict ?
A QueryDict is a MultiValueDict to begin with, as you can repeat GET-parameters. I.e. it handles its values in lists by default. Good news is that you can use its features directly to handle lists:
from django.http.request import QueryDict
d = QueryDict(mutable=True)
d.setlist('emails', ['abc#abc.com', 'def#abc.com'])
d['emails']
# 'def#abc.com'
d.getlist('emails')
# ['abc#abc.com', 'def#abc.com']
d.appendlist('emails', 'foo#bar.baz')
d
# <QueryDict: {'emails': ['abc#abc.com', 'def#abc.com', 'foo#bar.baz']}>
d.urlencode()
# 'emails=abc%40abc.com&emails=def%40abc.com&emails=foo%40bar.baz'
I'm working on rewriting a lengthy Rexx script into a Python program and I am trying to figure out the best way to emulate the functionality of a Rexx compound variable. Would a dictionary be the best bet? Obviously, a dictionary will behave differently and won't be exactly the same as a compound variable.
Python dictionaries and Rexx stems are both associative arrays. They differ a bit in how they behave. Rexx's rules are very simple:
An array reference is split into the "stem" and the "tail", separated by a single dot.
The stem is a variable name, case-independently. This is the dictionary.
The tail is processed to identify an element of the array. It is split into one or more dot-separated substrings. Each substring is treated as a variable: if there is a variable with that case-independent name, its value is used instead of its name. Otherwise the name is uppercased and used. The string is put back together, dots and all. This is the key.
The array can have a default value, set by stem. = value, which applies to all unset elements.
So, the result of a an array reference stem.tailpart1.tailpart2.tailpart3 in Python is:
def evaluate_tail(tail, outer_locals):
result = []
for element in tail.split('.'):
if element in outer_locals:
result.append(str(outer_locals[element]))
else:
result.append(str(element).upper())
return '.'.join(result)
array_default_value = 4
stem = {'A.B.C': 1, 'A.9.C': 2, 'A..q': 3}
b = 9
d = 'q'
tail1 = 'a.b.c'
tail2 = 'a..b'
tail3 = 'a..d'
stem.get(evaluate_tail(tail1,locals()), array_default_value) # 'stem.a.b.c' >>> stem['A.9.C'] >>> 2
stem.get(evaluate_tail(tail2,locals()), array_default_value) # 'stem.a..b' >>> stem['A..9'] (not found) >>> (default value) >>> 4
stem.get(evaluate_tail(tail3,locals()), array_default_value) # 'stem.a..d' >>> stem['A..q'] >>> 3
Rexx-Stem variable and python-dictionaries are similar but there are differences.
Considder creating a RexxStem class based on a dictionary
Simple Stem expressions
a.b
can be translated to python as
a[b]
Compound Stem expressions
From my experience
a.b.c.d
would be translated to python as
a[b + '.' + c + '.' + d]
Try running the following rexx with your current interpretter and see what you
get:
a.2.3 = 'qwerty'
zz = 2'.'3
say a.zz
in some rexx interpreters you would get 'qwerty'. Not sure if that is all
Initializing a Stem Variables
in rexx you can initialize a stem variable lic
a. = 'abc'
Some common uses are
no = 0
yes = 1
found. = no
if ... then do
found.v = yes
end
....
if found.y = yes then do
..
end
or
counts. = 0
do while ...
if ... then do
counts.v = counts.v + 1;
end
end
Initial Value of a stem variable
Like all Rexx variables, the default/initial value of a variable so the default value of a.2.3 is A.2.3. If you are coming from another language this may seem strange but it can be quite handy in debugging - if a variable name pops up unexpectedly --> you have not initiated. It also means numeric expressions crash if you do not initialize a variable.
This not something you need to implement, just be aware of.
I am not a Python person but I know what a Dictionary is.
Depending on how complex the Rexx compound variable is, yes.
a.b
...is easily translatable to a dictionary.
a.b.c.d.e.f.g.h
...is less easily translatable to a dictionary. Perhaps a dictionary within a dictionary within a dictionary within a dictionary within a dictionary within a dictionary within a dictionary.
I have a list of string.
list=['cretd_dt','rcvd_dt']
The actual code is:
query = table.update().values(
cretd_dt = Join_All_Dates.iloc[index]['cretd_dt'],
rcvd_dt= Join_All_Dates.iloc[index]['rcvd_dt'])
I want the cretd_dt= and rcvd_dt= to be used from inside the list. That is if the list has a,b, then inside the query it must be .values( a=join[index]['a']) etc.
list=['a','b']
query = table.update().values(
a = Join_All_Dates.iloc[index]['a'],
b= Join_All_Dates.iloc[index]['b'])
Build a dict and unpack it as arguments to values():
# Don't shadow builtins such as list
the_list = ['a', 'b']
query = table.update().values(**{k: Join_All_Dates.iloc[index][k] for k in the_list})
though you don't need to unpack, since Update.values() accepts a dict as a positional argument directly as well.
As far as I know if you iterate over a list and update its element, you dont update list itself.
list_var = ['a','b','c']
for l in list_var:
l = 'x'
print list_var
it prints out ['a', 'b', 'c'], not X's
Below code belongs to one of my project.
if hasattr(self.model, 'get_disabled_always_fields'):
for field in self.model.get_disabled_always_fields():
for form in self.formset_instance:
try:
form.fields[field].widget.attrs['readonly'] = True
except KeyError as e:
pass
It updates the list element and it effect the list we were iterating.
Question is , why formset forms affected by for loop modifications.
How variable references work
a = 1 really just means "make a an alias for the value carried by the expression 1". a = 1 + 2 really just means "evaluate 1 + 2 and then make a and alias for the result of that.
However, a[0] = 1 means "set the first value of a to the expression 1".
So, if you're looping through a list, you're essentially going through each value in the iterable and for each value, you set form to that value. Doing form = a within the list just changes the meaning of form. Doing form[0] = a modifies form.
If you don't want it to be modified, consider cloning form at the beginning of the loop using form = form[:].
I hope the concepts of how variables work in this case is now clear; it can be a bit confusing!
In first example you assign elements of list_var to l, then reassigning the same exact l variable.
In second example you operate with form.fields[field].widget.attrs['readonly'] and not field(by which you iterate). So if you would be doing:
for field in self.model.get_disabled_always_fields():
for form in self.formset_instance:
field = 'something' # or
form = 'something2'
nothing would change as it haven't in first example.