How to avoid N+1 query when using model_to_dict - python

I'm trying to avoid N+1 issue as described in http://docs.peewee-orm.com/en/latest/peewee/relationships.html#avoiding-the-n-1-problem but still additional queries are executed.
My model:
from peewee import (SqliteDatabase, Model, BigAutoField, CharField, ForeignKeyField)
db = SqliteDatabase(':memory:')
class TestModel(Model):
class Meta:
database = db
legacy_table_names = False
class TestUser(TestModel):
id = BigAutoField(primary_key=True)
name = CharField()
class Book(TestModel):
id = BigAutoField(primary_key=True)
name = CharField()
user = ForeignKeyField(TestUser, backref='books')
class Movie(TestModel):
id = BigAutoField(primary_key=True)
name = CharField()
user = ForeignKeyField(TestUser, backref='movies')
class Tape(TestModel):
id = BigAutoField(primary_key=True)
name = CharField()
user = ForeignKeyField(TestUser, backref='tapes')
And my test:
from peewee import JOIN
from playhouse.shortcuts import model_to_dict
from playhouse.test_utils import count_queries
from test_n_plus_1l import *
def test_should_avoid_n_plus_one_problem():
db.create_tables([TestUser, Book, Movie, Tape])
tu = TestUser.create(name='Test')
Book.create(name='Book1', user_id=tu.id)
Movie.create(name='Movie1', user_id=tu.id)
Tape.create(name='Tape1', user_id=tu.id)
with count_queries() as counter:
tu = TestUser.select(TestUser, Book, Movie, Tape) \
.join_from(TestUser, Book, JOIN.LEFT_OUTER) \
.join_from(TestUser, Movie, JOIN.LEFT_OUTER) \
.join_from(TestUser, Tape, JOIN.LEFT_OUTER) \
.where(TestUser.id == tu.id).get()
model_to_dict(tu, backrefs=True, manytomany=True, max_depth=4)
assert counter.count == 1
And after running it I'm getting assertion error:
E assert 4 == 1
Peewees prints executed sql, so I clearly see that joins were executed, but why peewee executes additional queries:
('SELECT "t1"."id", "t1"."name", "t2"."id", "t2"."name", "t2"."user_id", "t3"."id", "t3"."name", "t3"."user_id", "t4"."id", "t4"."name", "t4"."user_id" FROM "test_user" AS "t1" LEFT OUTER JOIN "book" AS "t2" ON ("t2"."user_id" = "t1"."id") LEFT OUTER JOIN "movie" AS "t3" ON ("t3"."user_id" = "t1"."id") LEFT OUTER JOIN "tape" AS "t4" ON ("t4"."user_id" = "t1"."id") WHERE ("t1"."id" = ?) LIMIT ? OFFSET ?', [1, 1, 0])
('SELECT "t1"."id", "t1"."name", "t1"."user_id" FROM "book" AS "t1" WHERE ("t1"."user_id" = ?)', [1])
('SELECT "t1"."id", "t1"."name", "t1"."user_id" FROM "movie" AS "t1" WHERE ("t1"."user_id" = ?)', [1])
('SELECT "t1"."id", "t1"."name", "t1"."user_id" FROM "tape" AS "t1" WHERE ("t1"."user_id" = ?)', [1])

The problem is that each TestUser may have any number of associated Books, Movies or Tapes. So this is an instance where you may benefit from using the prefetch() helper instead - because of the direction of the foreign-keys. That said, you're best off profiling, as prefetch() may not be any faster than just doing the queries.
Here is an example of using prefetch(). Note how each user has multiple Tweets and Notes, and each Tweet has multiple Flags -- but we only execute a total of 4 queries:
class User(Base):
name = TextField()
class Tweet(Base):
user = ForeignKeyField(User, backref='tweets')
content = TextField()
class TweetFlag(Base):
tweet = ForeignKeyField(Tweet, backref='tweet_flags')
flag_type = IntegerField()
class Note(Base):
user = ForeignKeyField(User, backref='notes')
content = TextField()
db.create_tables([User, Tweet, TweetFlag, Note])
for i in range(10):
user = User.create(name='user-%s' % i)
for t in range(10):
tweet = Tweet.create(user=user, content='%s/tweet-%s' % (user.name, t))
for f in range(3):
TweetFlag.create(tweet=tweet, flag_type=f)
for n in range(5):
Note.create(user=user, content='%s/note-%s' % (user.name, n))
from playhouse.shortcuts import model_to_dict
from playhouse.test_utils import count_queries
with count_queries() as counter:
q = User.select().order_by(User.name)
p = prefetch(q, Tweet, TweetFlag, Note)
accum = []
for res in p:
accum.append(model_to_dict(res, backrefs=True))
print(counter.count)
print(accum[0])
Output:
4
{'id': 1,
'name': 'user-0',
'notes': [{'content': 'user-0/note-0', 'id': 1},
{'content': 'user-0/note-1', 'id': 2},
{'content': 'user-0/note-2', 'id': 3},
{'content': 'user-0/note-3', 'id': 4},
{'content': 'user-0/note-4', 'id': 5}],
'tweets': [{'content': 'user-0/tweet-0',
'id': 1,
'tweet_flags': [{'flag_type': 0, 'id': 1},
{'flag_type': 1, 'id': 2},
{'flag_type': 2, 'id': 3}]},
...

Related

Updating data in a model from views Django

Hi i have a problem with updating data which is stored in a model. I would like to update the data which is stored in a model without a form, it is a function which sums up every user transaction and after every change I would like it to update.
my models:
class Portfolio(models.Model):
portfolio_id = models.AutoField(primary_key=True,blank=True)
portfolio_title = models.CharField(unique=True,max_length=200, null=True,blank=True)
user_name = models.ForeignKey(Customer, null=True, on_delete=models.SET_NULL,blank=True)
p_shares_num_sum = models.DecimalField(decimal_places=2,default=0,max_digits=999,editable=True, null=True,blank=True)
p_last_mod_date = models.DateField(auto_now_add=False,null=True,editable=True,blank=True)
p_comp_num_sum = models.DecimalField(decimal_places=2,default=0,max_digits=999,editable=True, null=True,blank=True)
p_to_buy_percentage = models.CharField(max_length=200,editable=True, null=True,blank=True)
p_profit_earned = models.DecimalField(decimal_places=6,editable=True,default=0,max_digits=999, null=True,blank=True)
def __str__(self):
return self.portfolio_title if self.portfolio_title else ''
```
The data which I want to send to it after every entry on site, with function
shares_num = visdata.aggregate(Sum(('shares_number')))
shares_num_sum = (shares_num['shares_number__sum'])
shares_num_sum = format(shares_num_sum, ".0f")
#profit_earned = visdata.aggregate(Sum(('course')))
#profit_sum = (profit_earned['course__sum'])
fare_paid = visdata.aggregate(Sum(('fare')))
fare_sum = (fare_paid['fare__sum'])
mod_date = visdata.order_by('-date').first().date
to_buy = visdata.filter(buy_sell='+').count()
to_sell = visdata.filter(buy_sell='-').count()
to_buy_percentage = 0
to_buy_percentage = to_buy / comp_number
to_buy_percentage = (to_buy_percentage) * 100
to_buy_percentage = format(to_buy_percentage, ".0f")
to_buy_percentage = str(to_buy_percentage) + '%'
#for customer restriction delete object and change VisData to visdata
aggregated_data = visdata.annotate(
intermid_result=F('course') - F('fare')
).annotate(
record_total=F('shares_number') * F('intermid_result')
).aggregate(
total=Sum('record_total')
)
profit_earned = aggregated_data['total']
profit_earned = format(profit_earned, ".2f")
summary_data = [int(shares_num_sum),int(comp_number),mod_date,str(to_buy_percentage),float(profit_earned)]
The function is written and prints me:
[4, 2, datetime.date(2021, 12, 20), '100%', 0.9]
If you have that data from function in your view, just get your current portolio object and asign to it's fields values, then call save() method from that object.
For example:
portfolio_object = Portfolio.objects.get(pk=some_pk)
portfolio_object.some_field = summary_data[0]
... here the rest of values
portfolio_object.save()
Remember that it'll execute every time you open that view, so think about some optimalization.

How do i append to EmbeddedDocumentListField in MongoEngine Flask?

Im trying to append additional info to an existing list but i received an error message instead.
Error: 4.Invalid embedded document instance provided to an
EmbeddedDocumentField: ['family']
class Family(db.EmbeddedDocument):
name = db.StringField()
# gender = db.StringField()
class House(db.Document):
house_id = db.IntField(required=True, unique=True)
housingType = db.StringField(required=True)
family = db.EmbeddedDocumentListField(Family)
def to_json(self):
return {
"house_id": self.house_id,
"housingType": self.housingType,
"family_members": self.family
}
#app.route('/api/add_family/<h_id>', methods=['POST'])
def add_family(h_id):
content = request.json
h = House.objects(house_id=h_id).get()
h.family.append(content['family'])
h.save()
return make_response("Added family member successfully", 201)
What im trying to achieve is as follows:
Current data:
{
'house_id': 1,
'family': [{'name': 'John', 'Gender': 'Male'}]
}
After appending, it should look like this:
{
'house_id': 1,
'family': [{'name': 'John, 'Gender': 'Male'}, {'name': 'Peter', 'Gender': 'Male'}]
}
Here is my solution. Hopefully it helps.
#app.route('/api/add_family/<h_id>', methods=['POST'])
def add_family(h_id):
'''
family member is added only if its not already in the database
'''
edited = False
content = request.json
h = House.objects.get(house_id=h_id).to_json()
h = json.loads(h)
family_arr = h['family']
if family_arr:
# family_arr not empty
count = family_arr[-1].get('id') + 1
else:
count = 1
for new_name in content['family']:
if not dup_name_check(family_arr, new_name['name']):
new_name.update({'id': count})
family_arr.append(new_name)
count += 1
edited = True
if edited:
House.objects.get(house_id=h_id).update(family=family_arr)
return make_response(f"Successfully added family member in House ID:{h_id}", 201)
else:
return make_response(f"Duplicated entries detected!", 400)

Instance Error On Foreign Key Field Django

Im stumped and need help on my function.
I have two tables student and student information. Student information is all guardian information of that student. I separated this data from the main student table so you can add as many guardians as you want to a students file with new records. The error I'm getting is as followed.
Cannot assign "'1'": "StudentInformation.studentpsid" must be a "Student" instance.
Attached you will see my code. Studentpsid in student information is a foreign key from student.
def ImportStudentGuardian(request):
AuthTokenP(request)
print("Getting student guardian data from SIS for K-8")
#Pulls K-8 Guardians
url = "removed for posting"
payload = {}
token = APIInformation.objects.get(api_name="PowerSchool")
key = token.key
headers = {'Authorization': 'Bearer {}'.format(key)}
response = requests.request("GET", url, headers=headers, data = payload)
encode_xml = response.text.encode('utf8')
xml_string = ET.fromstring(encode_xml)
students = xml_string.findall("student")
for student in students:
#XML Values
psid = student.find("id").text
try:
mother = student.find("contact").find("mother").text
except Exception:
mother = ""
try:
father = student.find("contact").find("father").text
except Exception:
father = ""
if Student.objects.filter(studentpsid=psid).exists():
print("Accessing guardian information.")
m = StudentInformation.objects.create(studentpsid=psid,guardian_name = mother, relation = "Mom") <---- Function Fails here
print("Record doesn't exist for mom, creating record.")
m.save()
d= StudentInformation.objects.create(studentpsid=psid,guardian_name = father, relation = "Dad")
print("Record doesn't exist for dad, creating record.")
d.save()
return ("Updated Guardian Information ")
Model
class Student(models.Model):
studentpsid= models.CharField(primary_key = True , default = "", max_length = 50, unique = True)
student_name = models.CharField(max_length = 50)
first_name = models.CharField(max_length = 50, default = "")
last_name = models.CharField(max_length = 50,default = "")
gender = models.CharField(max_length = 1,default = "")
student_grade = models.CharField(max_length = 2, default = "")
home_room = models.CharField(max_length = 5, default = "")
student_enrollment = models.CharField(max_length = 2, default = "")
school_number = models.CharField(max_length = 15, default = "")
email = models.EmailField(default = "")
projected_graduation_year = models.CharField(max_length = 4, default = "")
counseling_goal = models.TextField(max_length = 255)
class_name = models.ManyToManyField(TeacherClass)
image = models.ImageField(default ="default.png", upload_to ='student_pics')
# Guardian Information For Student
class StudentInformation(models.Model):
studentpsid = models.ForeignKey(Student,on_delete = models.CASCADE, default = "" ,)
guardian_name = models.CharField(max_length = 50, default = "")
RELATION_CHOICES = [
(0, 'None'),
(1, 'Mom'),
(2, 'Dad'),
(3, 'Other'),
]
relation = models.PositiveSmallIntegerField(choices = RELATION_CHOICES,)
guardian_cell = models.CharField(max_length = 12, default = "")
guardian_email = models.EmailField(max_length = 80,blank = True, default = "")
prefered_contact = models.BooleanField(default = False, blank = True)
DAY_CHOICES = [
(0, 'None'),
(1, 'Monday'),
(2, 'Tuesday'),
(3, 'Wednesday'),
(4, 'Thursday'),
(5, 'Friday'),
]
day_of_week = models.PositiveSmallIntegerField(choices = DAY_CHOICES, default = 0 )
time = models.CharField(max_length= 7, default = "", blank = True)
While creating a record with the foreign key relation, and instance of the related table should be provided, so the table can maintain a relationship for that particular record.
Get the instance of the Student table with the given psid and use that while creating the StudentInformation record
EDIT : Included the part for creating the record only if mother and father values are available.
for student in students:
#XML Values
psid = student.find("id").text
try:
psid_obj = Student.objects.get(studentpsid=psid) #(pk = psid) also works as the field is primary key
try:
mother = student.find("contact").find("mother").text
m = StudentInformation.objects.create(studentpsid=psid_obj,guardian_name = mother, relation = "Mom")
m.save()
except Exception as err1:
print "Error at Mom", str(err1)
try:
father = student.find("contact").find("father").text
d= StudentInformation.objects.create(studentpsid=psid_obj,guardian_name = father, relation = "Dad")
d.save()
except Exception as err2:
print "Error at Dad",str(err2)
except:
print "Student Record Not found"
As the error says, you are assigning a char data type to the ForeignKey field.
You should first get the instance of that Student, and then assign it to your StudentInformation object, like this:
if Student.objects.filter(studentpsid=psid).exists():
print("Accessing guardian information.")
student = Student.objects.get(pk=psid) # this will fail if the student doesn't exist
m = StudentInformation.objects.create(studentpsid=student,guardian_name = mother, relation = "Mom") <---- Function Fails here
print("Record doesn't exist for mom, creating record.")
m.save()
d= StudentInformation.objects.create(studentpsid=student,guardian_name = father, relation = "Dad")
print("Record doesn't exist for dad, creating record.")
d.save()
return ("Updated Guardian Information ")

In Odoo 10,how can I specify a data in create_date,create_uid,instead of value in system,when I use method named 'create' to create a record

I create new record with the method named create() in local database with data pulled away from remote database.As we all know,there are four normal fields in Odoo such as create_date,write_date,create_uid,write_uid.I want these data to be in a remote databaseļ¼Œbut when I use method named create() to create the record,these data are the data at the time of local creation and not the remote data.
For example,in remote database,the creat_date is '2019-10-11',I can't change the value that is finally written to the local database even if I pass the value of the remote database into the dictionary.Finally,the value of field named create_date is '2019-12-03' rather than '2019-10-11'.The '2019-12-03' is the date now.The situation is similar for other fields such as write_date,create_uid,write_uid.
Please help me,thanks to everyone who thought about this question.
Following is my code.
The Class Model
class ReportRentalIncomeFromProperty(models.Model):
_name = 'report.rental.income.from.property'
_description = 'The report about the income from property rental'
_order = 'product_id, start_date'
# create_date = fields.Datetime('Created on')
create_uid = fields.Char('Created by')
# write_date = fields.Datetime('Last Modified on')
write_uid = fields.Char('Last Contributor')
product_id = fields.Many2one('product.product', 'Property House')
area_id = fields.Many2one('res.country.area', 'City')
district_id = fields.Many2one('res.country.district', 'District')
town_id = fields.Many2one('res.country.town', 'Town')
road_name = fields.Char('Road')
start_date = fields.Date('Start Date')
end_date = fields.Date('End Date')
should_pay = fields.Float('Should Pay')
real_pay = fields.Float('Real Pay')
balance_pay = fields.Float('Balance Pay')
rental_compliance_rate = fields.Float('Rental Compliance Rate(%)', group_operator="avg")
company_id = fields.Many2one('res.company', string='Company')
parent_company_id = fields.Many2one('res.company', related='company_id.parent_id', store=True,
string='Parent Company')
actual_business = fields.Many2many(
'rh.commercial.activities',
'house_rental_rent_income_business_db',
'actual_business_id',
'commercial_activities_id',
string='Actual business')
The function to pull away remote data to create new record in local database.
#api.multi
def synchronization_contract_performance_rate(self):
self.env['report.rental.income.from.property'].search([]).unlink()
product_dict = {}
A_product = self.env['product.product'].search([])
for a in A_product:
product_dict[a.name] = a.id
activities_dict = {}
D_activities = self.env['rh.commercial.activities'].search([])
for d in D_activities:
activities_dict[d.name] = d.id
address_dict = {}
i = 0
address_model_list = ['res.country.area', 'res.country.district', 'res.country.town']
address_field_list = ['area_id', 'district_id', 'town_id']
for addr in address_model_list:
C_address = self.env[addr].search([])
addr_dict = {}
for c in C_address:
addr_dict[c.name] = c.id
address_dict[i] = addr_dict
i += 1
record_list_1 = self.company_recursive_func()
for list_1 in record_list_1:
database = list_1[0]
link_url = list_1[1]
if link_url.startswith('http://'):
_uri = link_url.replace('http://', '')
my_odoo = odoorpc.ODOO(_uri, port=48080)
if link_url.startswith('https://'):
_uri = link_url.replace('https://', '')
my_odoo = odoorpc.ODOO(_uri, port=443, protocol='jsonrpc+ssl')
username = list_1[2]
password = list_1[3]
my_odoo.login(database, username, password)
company_id = list_1[4]
company_code = list_1[5]
product_actual_business_dict = {}
A_product_actual_business_ids = my_odoo.env['product.product'].search([])
A_product_actual_business = my_odoo.execute('product.product', 'read', A_product_actual_business_ids,
['actual_business'])
for a in A_product_actual_business:
name_list = []
for b in my_odoo.execute('rh.commercial.activities', 'read', a.get('actual_business'), ['name']):
name_list.append(b.get('name'))
product_actual_business_dict[a.get('id')] = name_list
remote_ids = my_odoo.env['report.rental.income.from.property'].search([])
remote_data_dict = my_odoo.execute('report.rental.income.from.property', 'read', remote_ids, ['product_id',
'start_date',
'create_date',
'create_uid',
'write_date',
'write_uid',
'end_date',
'should_pay',
'balance_pay',
'real_pay',
'rental_compliance_rate',
'area_id',
'road_name',
'district_id',
'town_id'])
for data in remote_data_dict:
remote_product_name = data.get('product_id')[1]
product_id = product_dict.get(remote_product_name + '(' + company_code + ')',
None)
if product_id:
i = 0
address_id_list = []
for address_field in address_field_list:
if data.get(address_field):
remote_address_name = data.get(address_field)[1]
local_address_id = address_dict[i].get(remote_address_name, None)
address_id_list.append(local_address_id)
else:
address_id_list.append(None)
i += 1
ids_list = []
find_names = product_actual_business_dict.get(data.get('product_id')[0])
for find_name in find_names:
id = activities_dict.get(find_name, None)
if id:
ids_list.append(id)
value = {
'product_id': product_id,
'area_id': address_id_list[0],
'district_id': address_id_list[1],
'town_id': address_id_list[2],
'road_name': data['road_name'],
'start_date': data['start_date'],
'end_date': data['end_date'],
'should_pay': data['should_pay'],
'real_pay': data['real_pay'],
'create_date': data['create_date'],
'create_uid': data['create_uid'][1],
'write_date': data['write_date'],
'write_uid': data['write_uid'][1],
'balance_pay':data['balance_pay'],
'rental_compliance_rate': data['rental_compliance_rate'],
'company_id': company_id,
'actual_business': [(6, 0, ids_list)]
}
self.env['report.rental.income.from.property'].create(value)
my_odoo.logout()
You can change standart odoo fields after you create your record with sql query
property_id = self.env['report.rental.income.from.property'].create(value)
self.env.cr.execute("UPDATE report_rental_income_from_property SET create_date='%s', create_uid=%s, write_date='%s', write_uid=%s WHERE id=%s" %
(value['create_date'], value['create_uid'], value['write_date'], value['write_uid'], property_id))

CASE WHEN with ORM (SQLalchemy)

I am using SQLAlchemy with the ORM paragdim. I don't manage to find a way to do a CASE WHEN instruction. I don't find info about this on the web.
Is it possible ?
See sqlalchemy.sql.expression.case function and more examples on the documentation page. But it would look like this (verbatim from the documentation linked to):
case([(orderline.c.qty > 100, item.c.specialprice),
(orderline.c.qty > 10, item.c.bulkprice)
], else_=item.c.regularprice)
case(value=emp.c.type, whens={
'engineer': emp.c.salary * 1.1,
'manager': emp.c.salary * 3,
})
edit-1: (answering the comment) Sure you can, see example below:
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True, autoincrement=True)
first_name = Column(String)
last_name = Column(String)
xpr = case([(User.first_name != None, User.first_name + " " + User.last_name),],
else_ = User.last_name).label("full_name")
qry = session.query(User.id, xpr)
for _usr in qry:
print _usr.fullname
Also see Using a hybrid for an example of case used in the hybrid properties.
I got this to work with an aggregate function, in this case func.sum
My Example Code
from sqlalchemy import func, case
my_case_stmt = case(
[
(MyTable.hit_type.in_(['easy', 'medium']), 1),
(MyTable.hit_type == 'hard', 3)
]
)
score = db.session.query(
func.sum(my_case_stmt)
).filter(
MyTable.success == 1
)
return score.scalar()
My Use Case
MyTable looks like this:
| hit_type | success |
-----------------------------
| easy | 1 |
| medium | 1 |
| easy | 0 |
| hard | 1 |
| easy | 0 |
| easy | 1 |
| medium | 1 |
| hard | 1 |
score is computed as such:
score = num_easy_hits + num_medium_hits + (3 * num_hard_hits)
4 successful easy/medium hits and 2 successful hard hits gives you (4 + (2*3)) = 10
Here is the link in the doc:
http://docs.sqlalchemy.org/en/latest/core/sqlelement.html?highlight=case#sqlalchemy.sql.expression.Case
but it confused me to see those examples, and there is no runnable code.
I have try many times, and I have met many kinds of problem.
Finally, I found two ways to implement "Case when" within sqlalchemy.
The first way:
By the way, my occasion is I need to mask the phone field depending on if the user has logged in.
#staticmethod
def requirement_list_common_query(user=None):
`enter code here` phone_mask = case(
[
(db.true() if user else db.false(), Requirement.temp_phone),
],
else_=func.concat(func.left(Requirement.temp_phone, 3), '****', func.right(Requirement.temp_phone, 4))
).label('temp_phone')
query = db.session.query(Requirement.company_id,
Company.uuid.label('company_uuid'),
Company.name.label('company_name'),
Requirement.uuid,
Requirement.title,
Requirement.content,
Requirement.level,
Requirement.created_at,
Requirement.published_at,
Requirement.end_at,
Requirement.status,
# Requirement.temp_phone,
phone_mask,
User.name.label('user_name'),
User.uuid.label('user_uuid')
)
query = query.join(Company, Company.id == Requirement.company_id) \
.join(User, User.id == Requirement.user_id)
return query
Requirement is my one of my models.
the user argument in the method 'requirement_list_common_query' is the logged-in user if the user has logged in.
the second way:
the occasion here is I want to classify the employees depend on their income.
the models are:
class Dept(Base):
__tablename__ = 'dept'
deptno = Column(Integer, primary_key=True)
dname = Column(String(14))
loc = Column(String(13))
def __repr__(self):
return str({
'deptno': self.deptno,
'dname': self.dname,
'loc': self.loc
})
class Emp(Base):
__tablename__ = 'emp'
empno = Column(Integer, primary_key=True)
ename = Column(String(10))
job = Column(String(9))
mgr = Column(Integer)
hiredate = Column(Date)
sal = Column(DECIMAL(7, 2))
comm = Column(DECIMAL(7, 2))
deptno = Column(Integer, ForeignKey('dept.deptno'))
def __repr__(self):
return str({
'empno': self.empno,
'ename': self.ename,
'job': self.job,
'deptno': self.deptno,
'comm': self.comm
})
Here is the code:
from sqlalchemy import text
income_level = case(
[
(text('(emp.sal + ifnull(emp.comm,0))<1500'), 'LOW_INCOME'),
(text('1500<=(emp.sal + ifnull(emp.comm,0))<3500'), 'MIDDLE_INCOME'),
(text('(emp.sal + ifnull(emp.comm,0))>=3500'), 'HIGH_INCOME'),
], else_='UNKNOWN'
).label('income_level')
emps = sess.query(Emp.ename, label('income', Emp.sal + func.ifnull(Emp.comm, 0)),
income_level).all()
for item in emps:
print(item.ename, item.income, item.income_level)
why did I use "text"? Because code like this in SQLAlchemy 1.2.8 can't be implemented. I have tried so long and I can't find way like this, as #van has said:
case([(orderline.c.qty > 100, item.c.specialprice),
(orderline.c.qty > 10, item.c.bulkprice)
], else_=item.c.regularprice)
case(value=emp.c.type, whens={
'engineer': emp.c.salary * 1.1,
'manager': emp.c.salary * 3,
})
hopes it will help!

Categories