how to extract value in queryset and convert to string - django

the output of my code is currently
book_name = book.objects.values('book_name').filter(book_id=book_id)
book_name =str(book_name[0])
this code should give me 'Chronicles of Narnia '.
but it instead returns {'book_name': 'Chronicles of Narnia '}. how do i extract the value i need.
*note there will only be 1 value in this query every time

You could use values_list, option flat will mean the returned results are single values:
book.objects.values('book_name')
.filter(book_id=book_id).values_list('book_name', flat=True)
# <QuerySet [book_name1, book_name2, book_name3, ...]>

Related

how to find if string is in a result of a query set in Django

I have the following object result from query set on a model as follow:
ddd = Post_Sub_Category.objects.filter(
category_name__category_name__iexact=dd
).values_list('sub_category_name', flat=True)
the query set I obtained:
<QuerySet ['car', 'spare parts', 'truck', 'motor cycle']>
then tried:
print(ddd.values('sub_category_name'))
I obtained the following result:
<QuerySet [
<Post_Sub_Category: car>,
<Post_Sub_Category: spare parts>,
<Post_Sub_Category: truck>,
<Post_Sub_Category: motor cycle>
]
How to access the values only and make list of them as string:
['car','spare parts','truck','motor cycle'].
the first query set seems that it gave me what I want. However, When I use following if statement. it does not executed:
if 'car' in ddd:
# do some thing
as you can see car should be in the list. so, I could not understand why the if statement has not been executed.
any help or suggestion?
I think you might need to index that. The values list actually looks like it returns a list. Can you try:
try:
ddd = ddd[0]
except IndexError:
# Catch index error
pass
if 'car' in ddd:
# do some thing
If that doesn't work, try explicitly converting your QuerySetList to a regular ole list, as in this question, like this:
ddd = list(ddd)
Also, this looks a little strange to me: category_name__category_name__iexact=dd. Posting your corresponding models would be helpful.

Fetch value of selection field instead of key

I defined a selection field in one model.
type = fields.Selection([('a','A'),('b','B'),('c','C')])
In one of function i tried to get string value instead of key.
#api.multi
def testFunc(self):
for res in self:
print'Value',res.type //It prints 'a'.
I need to print 'A'.
How can i do this?
Choose One of the solutions :
The most importing thing that you can get the selection list like this:
self._fields['type'].selection
So try this:
# convert the list to dictionary
dict(self._fields['type'].selection).get(self.type)
IF you want the label to be translated in user language:
# here the label return is translated.
value = dict(self.fields['state']._description_selection(self.evn)).get(self.type)
You can use this method, it returns the string value, translated if it's the case:
#api.multi
def testFunc(self):
for res in self:
print'Value', dict(res.fields_get(["type"],['selection'])['type']["selection"]).get(res.type)
A possible and simple solution would be:
VALUES_TYPE = [('a','A'),('b','B'),('c','C')]
type = fields.Selection(VALUES_TYPE )
dict(VALUES_TYPE )[self.type]

Randomly set one-third of na's in a column to one value and the rest to another value

I'm trying to impute missing values in a dataframe df. I have a column A with 300 NaN's. I want to randomly set 2/3rd of it to value1 and the rest to value2.
Please help.
EDIT: I'm actually trying to this on dask, which does not support item assignment. This is what I have currently. Initially, I thought I'll try to convert all NA's to value1
da.where(df.A.isnull() == True, 'value1', df.A)
I got the following error:
ValueError: need more than 0 values to unpack
As the comment suggests, you can solve this with Series.where.
The following will work, but I cannot promise how efficient this is. (I suspect it may be better to produce a whole column of replacements at once with numpy.choice.)
df['A'] = d['A'].where(~d['A'].isnull(),
lambda df: df.map(
lambda x: random.choice(['value1', 'value1', x])))
explanation: if the value is not null (NaN), certainly keep the original. Where it is null, replace with the corresonding values of the dataframe produced by the first lambda. This maps values of the dataframe (chunks) to randomly choose the original value for 1/3 and 'value1' for others.
Note that, depending on your data, this likely has changed the data type of the column.

Dictionary error in Python 2.7

I have a file in the format:
0000 | a1_1,a3_2 | b2_1, b3_2
0001 | a1_3 | b4_1
and I'm trying to create a dictionary which has
{ 'a1' : set(['b2', 'b3', 'b4']), 'a3': set(['b2', 'b3']) }
and this is how my code looks like:
def get_ids(row, col):
ids = set()
x = row.strip().split('|')
for a in x[col].split(','):
ids.add(a.split('_')[0])
return ids
def add_to_dictionary(funky_dictionary,key, values):
if key in funky_dictionary:
funky_dictionary[key].update(values)
else:
funky_dictionary[key] = values
def get_dict(input_file):
funky_dictionary = {}
with open(input_file,'r') as ip:
for row in ip:
a_ids = get_ids(row,1)
b_ids = get_ids(row,2)
for key in a_ids:
add_to_dictionary(funky_dictionary,key,b_ids)
return funky_dictionary
So my problem is this when I lookup values for certain key in the dictionary, it returns me with way more values than expected. E.g.
For the above example the expected value of a3 would be set(['b2', ' b3'])
However with the code, I'm getting set(['b2', ' b3', 'b4'])
I cant figure out whats wrong with the code. Any help?
The issue you have is that many of your dictionary's values are in fact references to the same set instances. In your example data, when the first line is processed, 'a1' and 'a3' both get mapped to the same set object (containing 'b2' and 'b3'). When you process the second line and call update on that set via the key 'a1', you'll see the added value through 'a3' too, since both values are references to the same set.
You need to change the code so that each value is a separate set object. I'd suggest getting rid of add_to_dictionary and just using the dictionary's own setdefault method, like this:
for key in a_ids:
funky_dictionary.setdefault(key, set()).update(b_ids)
This code always starts with a new empty set for a new key, and always updates it with new values (rather than adding a reference to the b_ids set to the dictionary directly).

django queryset counts substrings in charField

One field in my model is a charField with the format substring1-substring2-substring3-substring4 and it can have this range of values:
"1-1-2-1"
"1-1-2-2"
"1-1-2-3"
"1-1-2-4"
"2-2-2-6"
"2-2-2-7"
"2-2-2-9"
"3-1-1-10"
"10-1-1-11"
"11-1-1-12"
"11-1-1-13"
For example I need to count the single number of occurrences for substring1.
In this case there are 5 unique occurrences (1,2,3,10,11).
"1-X-X-X"
"2-X-X-X"
"3-X-X-X"
"10-X-X-X"
"11-X-X-XX"
Sincerely I don't know where I can start from. I read the doc https://docs.djangoproject.com/en/1.5/ref/models/querysets/ but I didn't find a specific clue.
Thanks in advance.
results = MyModel.objects.all()
pos_id = 0
values_for_pos_id = [res.field_to_check.split('-')[pos_id] for res in results]
values_for_pos_id = set(values_for_pos_id)
How does this work:
first you fetch all your objects (results)
pos_id is your substring index (you have 4 substring, so it's in range 0 to 3)
you split each field_to_check (aka: where you store the substring combinations) on - (your separator) and fetch the correct substring for that object
you convert the list to a set (to have all the unique values)
Then a simple len(values_for_pos_id) will do the trick for you
NB: If you don't have pos_id or can't set it anywhere, you just need to loop like this:
for pos_id in range(4):
values_for_pos_id = set([res.field_to_check.split('-')[pos_id] for res in results])
# process your set results now
print len(values_for_pos_id)
Try something like this...
# Assumes your model name is NumberStrings and attribute numbers stores the string.
search_string = "1-1-2-1"
matched_number_strings = NumberStrings.objects.filter(numbers__contains=search_string)
num_of_occurrences = len(matches_found)
matched_ids = [match.id for match in matched_number_strings]
You could loop through these items (I guess they're strings), and add the value of each substring_n to a Set_n.
Since set values are unique, you would have a set, called Set_1, for example, that contains 1,2,3,10,11.
Make sense?