How to exclude fields when using Django _meta.get_fields() - python

My model has the standard "id" field, and I would like to exclude it when I use _meta.get_fields(). My current solution looks something like this:
context_var = (MyModel._meta.get_fields())[1:]
It works well enough, but I don't really like the slice solution. I'd rather remove the id field by name, or use a method that explicitly excludes the id field. Is there a more elegant solution?

You can do this:
context_var = [f for f in MyModel._meta.get_fields() if f.name != 'id']

Alternatively, you can use Python's built-in filter() function:
In [1]: context_var = filter(lambda x: x.name != 'id', MyModel._meta.fields)
In [2]: type(context_var)
Out[2]: filter
In [3]: for item in context_var: print(item)
MyModel.field1
MyModel.field2
...
The resulting value is of type filter which you can iter through, but, depending on what you need to do with context_var later, you might want to convert it into a tuple:
In [4]: context_var = tuple(filter(lambda x: x.name != 'id', MyModel._meta.fields))

Related

Sort a list from different classes by one field - Django

I connect multiple queryset from different objects into one list:
query_1 = Room.objects.all()
query_2 = Apartment.objects.all()
query_3 = Plot.objects.all()
all_user_objects = list(chain(query_1, query_2, query_3))
How can I add a sort by created_at date from the newest?
I try this:
all_user_objects.order_by('-created_at')
and this:
from operator import attrgetter
all_user_objects = list(chain(query_1, query_2, query_3), key=attrgetter('-created_at'))
You can use sorted() for this:
from operator import attrgetter
all_user_objects = list(sorted(chain(query_1, query_2, query_3), key=attrgetter('created_at'), reverse=True))

Remove multiple dictionary value from a list using Python

My data is as follow
dd=[{'id':'aa','age':22,'data':{},'background':{}},
{'id':'bb','age':23,'data':{},'background':{}},
{'id':'cc','age':24,'data':{},'background':{}},
{'id':'dd','age':25,'data':{},'background':{}},
{'id':'ee','age':26,'data':{},'background':{}}
]
How to remove several responses based on id? I have almost 100 responses that need to be removed.
As example:
id = ' aa bb cc '
Use list comprehension to filter out the data you do not want.
However, you should not use the name id
dd = [item for item in dd if item['id'] not in id]
You can also use filter, and lambda functions here,
dd = list(filter(lambda x : x["id"] not in a, dd))

List of all columns for given data types

Is it possible to groupby datatypes in pandas?
For e.g. I need a list of all columns of "objects" or "float" types.
This code will return exactly what I need. I am looking for a better way to achive this (if possible).
from collections import defaultdict
food_count = defaultdict(list)
for i, v in dict(df.dtypes).items():
food_count[v].append(i)
dict(food_count)
{dtype('<M8[ns]'): ['agency_spot_time'],
dtype('int64'): ['cost', 'spot_id', 'Event'],
dtype('O'): ['channel'],
dtype('float64'): ['viziters']}
You could use groupby and agg:
food_count = (lambda s: (
pd.Series(s.index, s).groupby(level=0).agg(list).to_dict()))(df.dtypes)
A more readable version of this is:
s = df.dtypes
food_count = pd.Series(s.index, s).groupby(level=0).agg(list).to_dict())

Formatting Multiple Columns in a Pandas Dataframe

I have a dataframe I'm working with that has a large number of columns, and I'm trying to format them as efficiently as possible. I have a bunch of columns that all end in .pct that need to be formatted as percentages, some that end in .cost that need to be formatted as currency, etc.
I know I can do something like this:
cost_calc.style.format({'c.somecolumn.cost' : "${:,.2f}",
'c.somecolumn.cost' : "${:,.2f}",
'e.somecolumn.cost' : "${:,.2f}",
'e.somecolumn.cost' : "${:,.2f}",...
and format each column individually, but I was hoping there was a way to do something similar to this:
cost_calc.style.format({'*.cost' : "${:,.2f}",
'*.pct' : "{:,.2%}",...
Any ideas? Thanks!
The first way doesn't seem bad if you can automatically build that dictionary... you can generate a list of all columns fitting the *.cost description with something like
costcols = [x for x in df.columns.values if x[-5:] == '.cost']
then build your dict like:
formatdict = {}
for costcol in costcols: formatdict[costcol] = "${:,.2f}"
then as you suggested:
cost_calc.style.format(formatdict)
You can easily add the .pct cases similarly. Hope this helps!
I would use regEx with dict generators:
import re
mylist = cost_calc.columns
r = re.compile(r'.*cost')
cost_cols = {key: "${:,.2f}" for key in mylist if r.match(key)}
r = re.compile(r'.*pct')
pct_cols = {key: "${:,.2f}" for key in mylist if r.match(key)}
cost_calc.style.format({**cost_cols, **pct_cols})
note: code for Python 2.7 and 3 onwards

replace None with Null, in place

I have a requirement to drop my test results into a csv for reporting. In my python test code when I don't have a value, my variables are filled in the python way with None.
I have been asked to replace these with "Null" in the CSV for the reporting tool. I am thinking this is easy and has probably be solved a hundred times.
Here is the code I came up with:
for field in (TestCase.productUnderTest,TestCase.versionUnderTest,TestCase.name,TestCase.results,TestCase.lastTestEnd,TestCase.parent,TestCase.level):
if field == None:
field = 'Null'
ME.csvoutput.write("%s,%s,%s,%s,%s,%s,%s\n" % (TestCase.productUnderTest,TestCase.versionUnderTest,TestCase.name,TestCase.results,TestCase.lastTestEnd,TestCase.parent,TestCase.level))
Unfortunately that only changes the field within the scope of the for loop. How can I change it for the scope of the write statement.
(I would be quite happy to just write "Null" and leave my variables unchanged, but I can work either way.)
result = [TestCase.productUnderTest,TestCase.versionUnderTest,TestCase.name,TestCase.results,TestCase.lastTestEnd,TestCase.parent,TestCase.level]
result = map(lambda x:x==None and 'Null' or str(x), result)
ME.csvoutput.write(",".join(result)+'\n')
To keep your code, you can try:
for field_name in ('productUnderTest','versionUnderTest','name','results','lastTestEnd','parent','level'):
if getattr(TestCase, field_name) is None:
setattr(TestCase, 'Null')
I suggest to look at the csv module.
Do it like this:
fields = [str(field) or "Null" for field in (TestCase.productUnderTest,TestCase.versionUnderTest,TestCase.name,TestCase.results,TestCase.lastTestEnd,TestCase.parent,TestCase.level)]
ME.csvoutput.write("%s\n" % ",".join(fields))))
Or, even more powerfull: use generator object instead:
fields = (str(field) or "Null" for field in (TestCase.productUnderTest,TestCase.versionUnderTest,TestCase.name,TestCase.results,TestCase.lastTestEnd,TestCase.parent,TestCase.level))
You should use method Pandas fillna:
from pandas import DataFrame
DataFrane.fillna(value='NULL', inplace=True)
Example
import pandas as pd
df = pd.read_csv(csv_file)
df.fillna(value='NULL', inplace=True)

Categories

Resources