I've got a set of key, value pairs dictionary in my Django application. The value in the dictionary is a string type.
{u'question': u'forms.CharField(max_length=512)'}
I need to convert this "value" string to an actual object, and get something like this.
properties = {
'question' : forms.CharField(max_lenth=512)
}
Notice that values in the second dictionary are actual Django form fields and NOT strings. I need to do this manipulation to create dynamic forms. The second dictionary is to be passed to "type" built-in function. Sample code can be found on this page. http://dougalmatthews.com/articles/2009/dec/16/nicer-dynamic-forms-django/ .
If you modify your representation a bit:
fields = {u'question': u'{"field": "django.forms.CharField", "params": {"max_length": 512}}'}
then you can use the following:
from django.utils import importlib, simplejson
def get_field(fname):
module, name = fname.rsplit('.', 1)
return getattr(importlib.import_module(module), name)
print dict((k.encode('ascii', 'ignore'), get_field(v['field'])(**v['params']))
for k, v in ((k, simplejson.loads(v)) for k, v in fields.iteritems()))
Following your code, I suggest to separate field name from field attrs:
my_fields = {u'question': {'name': 'CharField', 'attrs': {'max_length': 512} }}
and then something like:
properties = {}
for field_name, field_def in my_fields.items():
properties[field_name] = getattr(forms, field_def['name'])(**field_def['attrs'])
EDIT: Based on clarifying comments by the OP, this isn't an appropriate solution.
I don't know the constraints you are under, but perhaps the following representation will work better:
{u'question': lambda: forms.CharField(max_length=512)}
You can then "realise" the fields thus:
dict((k, v()) for (k, v) in props.iteritems())
Related
I created a json and passed it do a function.
But when I try to extract data it doesn't work.
data = {}
data['unit'] = { "id": "052e8reb-d801-89g6-8b26-3bd2da914890" }
test_data(data)
def test_data(data: dict):
getattr(data.unit, 'id', None)
getattr(data.get("unit", None), 'id', None)
data.get('unit').get('id', None)
All three methods fail. What should I do to safe get id if unit is not None.
I am new to python.
First of all, that's not JSON - that's a dictionary.
So, you can use it like a standard dictionary - data['unit']['id'] - equivalent to last line (except for if the key is not found), which should work
I have an HTML page that handles several forms.
When making a post request (i.e. submitting the values of the fields of the different forms) i received in django/python this dictionary:
form-0-Name:Dupont
form-0-Town:Paris
form-1-Name:Macron
form-1-Town:Marseille
From this dictionary, how to create a number of dictionaries based on the number of forms that i receive?
In this example, i would like to create two dictionaries named (form_0 and form_1) such that form_0:
{Name: Dupont,Town:Paris} and form_1:{Name: Macron, Town:Marseille}.
for dict like this :
a = {'form-0-Name':'Dupont', 'form-0-Town':'Paris', 'form-1-Name':'Macron','form-1-Town':'Marseille'}
you can proceed like this:
final = {}
for k,v in a.items():
key = '_'.join(k.split('-')[:2])
subkey = k.split('-')[-1]
final.setdefault(key, {}).update({subkey:v})
output :
final = {'form_0': {'Name': 'Dupont', 'Town': 'Paris'},
'form_1': {'Name': 'Macron', 'Town': 'Marseille'}}
Make an auxiliary function:
def get_form_dicts(form_dict):
dictionaries = []
form_strings = list(set([x[0:6] for x in form_dict.keys()]))
for i in form_strings:
dictionaries.append({x.split('-')[2]: v for x, v in form_dict.items() if i in x})
return tuple(form_strings)
Now, presuming that you know how many forms you are going to get:
# Naming django_dict the dict that is created in your application
form_0, form_1 = get_form_dicts(django_dict)
I'm trying to pull data from a dictionary ('data') in which several series are provided:
For instance, equity is extracted with:
data['Financials']['Balance_Sheet']['equity']
As I'm having several functions each calling one different series (e.g. equity, debt, goodwill, etc...), I would like to be able to define the "access" for each of those by defining a string such as:
Goodwill -> data['Financials']['Balance_Sheet']['Goodwill']
Equity->data['Financials']['Balance_Sheet']['Equity']
My idea is to do something like that:
Data_pulled= ACCESS('data['Financials']['Balance_Sheet']['Goodwill']')
What is the ACCESS function required to transform the string into a acccess function?
Hope this is clear! Thanks a lot for your help guys - much appreciated! :)
Max
I question what you're trying to accomplish here. A better answer is probably to write a accessor function that can safely get the field you want without having to type the whole thing out every time.
Consider the following code:
def ACCESS(*strings):
def ACCESS_LAMBDA(dic):
result = dic
for key in strings:
result = result[key]
return result
return ACCESS_LAMBDA
dic = { 'aa': { 'bb': { 'cc': 42 } } }
ABC_ACCESS = ACCESS('aa','bb','cc')
print ABC_ACCESS(dic)
This is called a closure, where you can define a function at runtime. Here you'd create pull_goodwill = ACCESS('Financials','Balance_Sheet','Goodwill') then get the value with Data_pulled = pull_goodwill(data)
This doesn't exactly answer your question, and the star-arguments and Lambda-returned-function are pretty advanced things. But, don't just "call eval()" that's a pretty insecure coding habit to get into. eval() has its uses... But, think about what you're trying to do, and see if there is a simple abstraction that you can program to access the data you want, rather than relying on the python parser to fetch a value from a dict.
edit:
Link to information about closures in python
edit2:
In order to not have to pass a dictionary to the returned lambda-function, you can pass it into the function constructor. Here's what that would look like, note the change to ACCESS's definition now includes dic and that the ACCESS_LAMBDA definition now takes no arguments.
def ACCESS(dic, *strings):
def ACCESS_LAMBDA():
result = dic
for key in strings:
result = result[key]
return result
return ACCESS_LAMBDA
dic = { 'a': { 'b': { 'c': 42 } } }
ABC_ACCESS = ACCESS(dic, 'a','b','c')
print ABC_ACCESS()
(Note here, that if dict is modified, then the ABC_ACCESS value will change. this is because python passes by reference, if you want a constant value you'd need to make a copy of dic.)
I have a dictionary that looks like:
{u'message': u'Approved', u'reference': u'A71E7A739E24', u'success': True}
I would like to retrieve the key-value pair for reference, i.e. { 'reference' : 'A71E7A739E24' }.
I'm trying to do this using iteritems which does return k, v pairs, and then I'm adding them to a new dictionary. But then, the resulting value is unicode rather than str for some reason and I'm not sure if this is the most straightforward way to do it:
ref = {}
for k, v in charge.iteritems():
if k == 'reference':
ref['reference'] = v
print ref
{'reference': u'A71E7A739E24'}
Is there a built-in way to do this more easily? Or, at least, to avoid using iteritems and simply return:
{ 'reference' : 'A71E7A739E24' }
The trouble with using iteritems is that you increase lookup time to O(n) where n is dictionary size, because you are no longer using a hash table
If you only need to get one key-value pair, it's as simple as
ref = { key: d[key] }
If there may be multiple pairs that are selected by some condition,
either use dict from iterable constructor (the 2nd version is better if your condition depends on values, too):
ref = dict(k,d[k] for k in charge if <condition>)
ref = dict(k,v for k,v in charge.iteritems() if <condition>)
or (since 2.7) a dict comprehension (which is syntactic sugar for the above):
ref = {k,d[k] for k in charge if <condition>}
<same as above>
I dont understand the question:
is this what you are trying to do:
ref={'reference',charge["reference"]}
When I store the following document into mongo, something like:
{
name: Somename,
profile: Someprofile
}
When I use a find_one():
I get a result of something like:
{
profile: Someprofile,
_id: 35353432326532(random mongo id),
name: Somename
}
Is there some way in python such that when I do something before or after find_one such that I can get a result in a json string that is ordered like:
{
_id: 35353432326532(random mongo id),
name: Somename,
profile: Someprofile
}
I tried using an OrderedDict like below, but it does not seem to help.
somedocument = db.mycollection
theordereddict = OrderedDict(data_layer.find_one())
print str(theordereddict)
How do I get my output string in the right order in regards to attributes? Is this order dictated by something else before I even insert the document into the database?
collections.OrderedDict doesn't order keys it just preserves order, you need to insert keys into it in the order you want to retrieve them.
d = data_layer.find_one()
def key_function(tuple):
"""This defines the sort order for the sorted builtin"""
return tuple[0]
sorted_dict = collections.OrderedDict((k,v) for k, v in sorted(d.items(),
key=key_function))
That said, it looks like print str(sorted_dict) doesn't give you the output you want. I think you need to build your sorted string representation manually. E.g.:
s = "{" + ",".join(["%s:%s" for k,v in sorted(d.items(), key=key_function)]) + "}"
Basically the same as #Mike Steder's answer but maybe less fancy and more clear:
import json
from collections import OrderedDict
theordereddict = OrderedDict()
d = data_layer.find_one()
for k in sorted(d.keys()):
theordereddict[k] = d[k]
json.dumps(theordereddict)