how to generate this sql in sqlalchemy,i am trying hard but didn't know what to do - python-2.7

"select pck.id, pck.name, deb.last_time from (select id, name from dp_package where name like %s limit %s, %s) as pck left join (select package_id, last_time from dp_deb where id in (select max(id) from dp_deb group by package_id)) as deb on pck.id = deb.package_id" %(keyword, start, limit)

Assuming the model is defined:
Base = declarative_base()
class Package(Base):
__tablename__ = 'db_package'
id = Column(Integer, primary_key=True)
name = Column(String)
def __init__(self, name):
self.name = name
class Deb(Base):
__tablename__ = 'db_deb'
id = Column(Integer, primary_key=True)
package_id = Column(Integer, ForeignKey('db_package.id'))
name = Column(String)
last_time = Column(DateTime)
def __init__(self, name, last_time):
self.name = name
self.last_time = last_time
packages = relationship(Package, backref="debs")
the code below should produce the same result (although different SQL query, where one subquery is replaced with simple LEFT OUTER JOIN):
# query parameters
keyword, start, limit = 'xxx', 1, 3
# subquery for the last_time
sq2h = session.query(Deb.package_id, func.max(Deb.id).label("max_id")).group_by(Deb.id).subquery("max_deb")
sq2 = (session.query(Deb.package_id, Deb.last_time).
join(sq2h, Deb.id == sq2h.c.max_id))
sq2 = sq2.subquery("deb")
qry = (session.query(Package.id, Package.name, sq2.c.last_time).
outerjoin(sq2, sq2.c.package_id == Package.id).
filter(Package.name.contains(keyword))
)[start:(start + limit)]
print qry
producing this SQL for SQLite:
SELECT db_package.id AS db_package_id,
db_package.name AS db_package_name,
deb.last_time AS deb_last_time
FROM db_package
LEFT OUTER JOIN(SELECT db_deb.package_id AS package_id, db_deb.last_time AS last_time
FROM db_deb
JOIN (SELECT db_deb.package_id AS package_id,
max(db_deb.id) AS max_id
FROM db_deb
GROUP BY db_deb.id
) AS max_deb
ON db_deb.id = max_deb.max_id
) AS deb
ON deb.package_id = db_package.id
WHERE db_package.name LIKE '%%' || ? || '%%'
LIMIT ? OFFSET ?
('xxx', 3, 1)

Related

How to join like sql in django models

I have these three models which has not contained foreign key
class SchoolReg(models.Model):
# TODO: Define fields here
user = models.ForeignKey('front.User', on_delete= models.CASCADE)
fullname = models.CharField(max_length= 100)
dob = models.CharField(max_length= 50)
class CandidateCode(models.Model):
candidateCode = models.IntegerField()
regId = models.IntegerField()
regCategory = models.CharField(max_length=20)
class Sec1(models.Model):
user = models.ForeignKey(User, on_delete = models.CASCADE, blank= True, null = True)
centreName = models.CharField(max_length= 50, blank= True, null = True)
compRegNo = models.CharField(max_length= 50, blank= True, null = Tru
now I want join these models and make a queryset of student like this
SELECT * from school_reg s
LEFT JOIN sec1 c on s.user_id = c.user_id
LEFT JOIN candidate_code cc on cc.reg_id = s.school_id
WHERE c.center_name = "centreName"
You would need to specify the relationship on the filter statement according to the documentation.
This stack overflow answer even has a great suggestion of using the .query() method to reverse a specific lookup you need.
We can't use select_related() because we don't have foreign key here so on that time we use raw sql
performing raw queries
I use this for the solution
from django.db import connection
with connection.cursor() as cursor:
cursor.execute("""SELECT s.id, s.dob, cc.candidateCode, s.fullname,
q.title, e.examDate, c.centreName from lrnadmin_schoolreg s
LEFT JOIN lrnadmin_bookingexam e on s.exam_id = e.id
LEFT JOIN front_sec1 c ON s.user_id = c.user_id
LEFT JOIN lrnadmin_qualification q ON q.id = s.qualification_id
LEFT JOIN lrnadmin_candidatecode cc ON cc.regId = s.id
WHERE c.id = %s""", [request.POST['centre']])
row = cursor.fetchall()

How to update all values of One2many field in Table for Odoo10

I have a One2many field in inventory for product pack. And I want that all fields values of that One2many field should update in fields of One2many field in sales order, row and column wise. So, Anyone can help me.
My Python code is here:
class ProductTemplate(models.Model):
_inherit = "product.template"
product_pack = fields.One2many('product.pack', 'template_id', string='Product Pack', copy=True)
class ProductDesign(models.Model):
_description = 'Product Pack'
_name = "product.pack"
_rec_name = "product_id"
check_option = fields.Boolean('#')
template_id = fields.Many2one('product.template', string='Template', required="True", ondelete='cascade', index=True, copy=True)
product_id = fields.Many2one('product.product', string='Product', required="True", domain="[('is_pack','=',False)]")
services = fields.Many2one('gold.service')
qty = fields.Integer('Quantity', default=1)
Here in 'wizard' (One2many field table) i want to update all fields (row and column) of product_pack
class SalePackWizard(models.TransientModel):
_name = "sale.pack.wizard"
_description = "Sale Pack Wizard"
product_id = fields.Many2one('product.product', string="Product Pack", required=True, domain="[('is_pack','=',True)]")
wizard = fields.One2many('product.gold','service')
#api.onchange('product_id')
def _onchange_product_pack_name(self):
for w in self.product_id.product_pack:
for s in w:
print "s:", s.product_id.name, s.services, s.qty
r = []
print"r:", r
class ProductDesign(models.Model):
_description = 'Product Pack'
_name = "product.gold"
_rec_name = "products_ids"
service= fields.Many2one('product.val', string='Templates', required="True", ondelete='cascade', index=True, copy=True)
check_box = fields.Boolean('#')
products_ids = fields.Many2one('product.product', string='Product', required="True", domain="[('is_pack','=',False)]")
services = fields.Many2one('gold.service')
qtyy = fields.Integer('Quantity', default=1)
Problem Solved.
Here is the function code of problem:
wizard = fields.One2many('product.gold','service',change_default=True, default=_onchange_action_product_add)
#api.onchange('product_id')
def _onchange_action_product_add(self):
res = self.product_id.product_pack
r = []
value = {}
for var in self.product_id.product_pack:
print "var:::", var
for line in self.product_id.product_pack:
print "line:::", line , line.product_id, line.product_id.name, line.qty, line.services, line.id
data = {'products_ids': line.product_id.id,
'service':var.id, #many2one child field from one2many field
'services':line.services,
'qtyy': line.qty
}
print "data:", data
r.append((0, 0, data))
print "r.append", r.append, r
#return data
value.update(wizard=r)
return {'value': value}

Django foreign key backreference filter results

I have a model as follows:
class Event(models.Model):
name = models.CharField(max_length=50, blank=False, verbose_name="Event name", )
date = models.DateField(auto_now=False, auto_now_add=False, )
hall = models.ForeignKey(Hall, on_delete=models.CASCADE, null=True, related_name='events', )
I have a view just for trying out results:
#api_view(('GET',))
def get_specific_hall(request, cityId, year = None, month = None, day = None):
hall = Hall.objects.filter(city=cityId)
testHall = Hall.objects.get(city=cityId)
date = year + '-' + month + '-' + day
events = []
for event in testHall.events.filter(~Q(date=date)):
events.append(event)
eventSerializer = EventSerializer(events, many=True)
serializer = HallSerializer(hall, many=True)
return Response(serializer.data + eventSerializer.data)
What I want is: I am passing date as a url parameter. I want to return those Hall objects from a specific city and which do not have any associated event for that date. i.e. only available hall.
How can I achieve that?
I updated my view as follows:
#api_view(('GET',))
def get_specific_halls(request, cityId, year = None, month = None, day = None):
date = year + '-' + month + '-' + day
hall = Hall.objects.all().filter(Q (city=cityId) , ~Q(events__date=date))
serializer = HallSerializer(hall, many=True)
return Response(serializer.data)

Django: Aggregate and Sum with a join with another table without the forign key constraint

Here is my models.py file.
from django.db import models
from django.contrib.auth.models import User
class image(models.Model):
name = models.CharField(max_length = 200)
src = models.URLField()
alt = models.CharField(max_length = 200)
points = models.IntegerField(default = 0)
id = models.CharField(max_length = 200, primary_key = True)
hotelId = models.IntegerField()
def __unicode__(self):
return self.name
class imagescore(models.Model):
user = models.ForeignKey(User)
image_id = models.CharField(max_length = 200)
score = models.IntegerField(default = 1)
createdTime = models.DateTimeField(auto_now_add =True)
def __unicode__(self):
if self.score < 0:
status = " rejected "
else:
status = "approved"
return (self.user+ status+ image_id)
pass
I would like to pass on to my template a table that is a result of the SQL Query:
select ei.id,ei.src, ei.hotelId , sum(score)
from eyeballing_image ei LEFT join eyeballing_imagescore eis on ei.id = eis.image_id
where user_id = request.user.id and ei.hotelId = 56565
group by
ei.id,ei.src, ei.hotelId
My app name is eyeballing. O tried using joins and filters bot i couldn't make it work.
Additionally, i tried making the sum(score) part into a separate dict and check the same in the template. Didn't work
Any help will be appreciated.
Your query has two problems, one in column name hotelId. you must use it in query in this way ei."hotelId".
Other problem is in condition user_id = request.user.id because you have not request in sql and you must replace it with a value.
Maybe another problem is in return (self.user + status + image_id) that must be return (self.user + self.status + self.image_id).

Converting raw SQL to Django QuerySet API

Model
class Person(models.Model):
GENDER = (
('M','Male'),
('F','Female'),
)
first_name = models.CharField("First Name", max_length=100)
last_name = models.CharField("Last Name",max_length=100)
middle_name = models.CharField("Middle Name", max_length=100, blank=True)
suffix_name = models.ManyToManyField(SuffixName, verbose_name="Suffix Name",null=True, blank=True)
gender = models.CharField(max_length=1, choices=GENDER)
department = models.ManyToManyField(Department, verbose_name="Department",null=True, blank=True)
def __unicode__(self):
return (u'%s') % (self.last_name.upper() + ', ' + self.first_name + ' ' + self.middle_name)
class Department(models.Model):
department_desc = models.CharField('Department', max_length=100,unique=True)
department_acronym = models.CharField('Department Acronym', max_length=20,blank=True,help_text="Add acronym if any, not required")
location = models.CharField('Location',max_length=100,blank=True)
localnumber = models.CharField('Local Number',max_length=30,blank=True)
active = models.BooleanField('Active',default=True)
def __unicode__(self):
return self.department_desc
How can I convert this raw SQL to a Django query?
SELECT pp.first_name, pd.department_desc, pd.localnumber
FROM person_person as pp
INNER JOIN person_person_department as ppd on pp.id = ppd.person_id
INNER JOIN person_department as pd on pd.id = ppd.department_id
Use QuerySet.values or QuerySet.values_list:
Person.objects.values('first_name', 'department__department_desc', 'department__localnumber')
# -> Returns a ValuesQuerySet that yields dictionaries when iterated.
Person.objects.values_list('first_name', 'department__department_desc', 'department__localnumber')
# -> Returns a ValuesQuerySet that yields tuples when iterated.
Fetching on Person will automatically fetch the related objects, so your query is:
people = Person.objects.all()
Then, you can do the following:
for person in people:
print('Person: {0}'.format(person.first_name))
for dept in person.department_set.all():
print('Desc: {0}, Local Number: {1}'.format(dept.department_desc,
dept.localnumber))
If you want to restrict the returned values, use values_list.