What happens when I change the default return of __unicode__ method to pass multiples foreignkeys - django

I'm wondering, in terms of database efficiency, if I edit the return __unicode__ method and do something like this:
class AnyModel(models.Model):
a_field = models.ForeignKey(A)
b_field = models.ForeignKey(B)
def __unicode__(self):
return "A - B: %s - %s " % (self.a_field.a2.a3, self.b_field.b2.b3)
So, the __unicode__ method will hit the foreign key's foreign key's foreign keys, get a string and then return it.
... Is it too expensive? What criteria should I follow? Is there any general advice I could use? Is it better not to write this kind of __unicode__ methods?

This is what happening with this structure:
def __unicode__(self):
return "A - B: %s - %s " % (self.a_field.a2.a3, self.b_field.b2.b3)
Hits :
(0.000) QUERY = 'SELECT "core_a"."id", "core_a"."a2_id" FROM "core_a" WHERE "core_a"."id" = %s' - PARAMS = (2,); args=(2,)
(0.000) QUERY = 'SELECT "core_a2"."id", "core_a2"."a3_id" FROM "core_a2" WHERE "core_a2"."id" = %s' - PARAMS = (1,); args=(1,)
(0.012) QUERY = 'SELECT "core_a3"."id" FROM "core_a3" WHERE "core_a3"."id" = %s' - PARAMS = (1,); args=(1,)
(0.000) QUERY = 'SELECT "core_b"."id", "core_b"."b2_id" FROM "core_b" WHERE "core_b"."id" = %s' - PARAMS = (1,); args=(1,)
(0.000) QUERY = 'SELECT "core_b2"."id", "core_b2"."b3_id" FROM "core_b2" WHERE "core_b2"."id" = %s' - PARAMS = (1,); args=(1,)
(0.005) QUERY = 'SELECT "core_b3"."id" FROM "core_b3" WHERE "core_b3"."id" = %s' - PARAMS = (1,); args=(1,)
But, if you do this,:
def __unicode__(self):
a_relation = AnyModel.objects.select_related('a_field__a2__a3').get(pk=self.pk)
b_relation = AnyModel.objects.select_related('b_field__b2__b3').get(pk=self.pk)
return "A - B: %s - %s " % (a_relation.a_field.a2.a3, b_relation.b_field.b2.b3)
When execute the line :
a_relation = AnyModel.objects.select_related('a_field__a2__a3').get(pk=self.pk)
1 hit :
(0.000) QUERY = 'SELECT "core_anymodel"."id", "core_anymodel"."a_field_id", "core_anymodel"."b_field_id", "core_a"."id", "core_a"."a2_id", "core_a2"."id", "core_a2"."a3_id", "core_a3"."id" FROM "core_anymodel" INNER JOIN "core_a" ON ( "core_anymodel"."a_field_id" = "core_a"."id" ) INNER JOIN "core_a2" ON ( "core_a"."a2_id" = "core_a2"."id" ) INNER JOIN "core_a3" ON ( "core_a2"."a3_id" = "core_a3"."id" ) WHERE "core_anymodel"."id" = %s' - PARAMS = (1,); args=(1,)
and When execute the second line:
b_relation = AnyModel.objects.select_related('b_field__b2__b3').get(pk=self.pk)
+1 Hit:
(0.000) QUERY = 'SELECT "core_anymodel"."id", "core_anymodel"."a_field_id", "core_anymodel"."b_field_id", "core_b"."id", "core_b"."b2_id", "core_b2"."id", "core_b2"."b3_id", "core_b3"."id" FROM "core_anymodel" INNER JOIN "core_b" ON ( "core_anymodel"."b_field_id" = "core_b"."id" ) INNER JOIN "core_b2" ON ( "core_b"."b2_id" = "core_b2"."id" ) INNER JOIN "core_b3" ON ( "core_b2"."b3_id" = "core_b3"."id" ) WHERE "core_anymodel"."id" = %s' - PARAMS = (1,); args=(1,)
And when execute
return "A - B: %s - %s " % (self.a_field.a2.a3, self.b_field.b2.b3)
Doesn't hit the database.
.
1 - Edit
You can join this, to :
def __unicode__(self):
relation = AnyModel.objects.select_related('a_field__a2__a3', 'b_field__b2__b3').get(pk=self.pk)
return "A - B: %s - %s " % (relation.a_field.a2.a3, relation.b_field.b2.b3)
and will hit only once.
(0.000) QUERY = 'SELECT "core_anymodel"."id", "core_anymodel"."a_field_id", "core_anymodel"."b_field_id", "core_a"."id", "core_a"."a2_id", "core_a2"."id", "core_a2"."a3_id", "core_a3"."id", "core_b"."id", "core_b"."b2_id", "core_b2"."id", "core_b2"."b3_id", "core_b3"."id" FROM "core_anymodel" INNER JOIN "core_a" ON ( "core_anymodel"."a_field_id" = "core_a"."id" ) INNER JOIN "core_a2" ON ( "core_a"."a2_id" = "core_a2"."id" ) INNER JOIN "core_a3" ON ( "core_a2"."a3_id" = "core_a3"."id" ) INNER JOIN "core_b" ON ( "core_anymodel"."b_field_id" = "core_b"."id" ) INNER JOIN "core_b2" ON ( "core_b"."b2_id" = "core_b2"."id" ) INNER JOIN "core_b3" ON ( "core_b2"."b3_id" = "core_b3"."id" ) WHERE "core_anymodel"."id" = %s' - PARAMS = (1,); args=(1,)

Related

Odoo - How to get report data based on company_id

I'm trying to get payroll data for each company's employees in a report based on company_id.
Here's my code:
in my wizard:
class hr_wps_report(osv.osv_memory):
_name = 'hr.wps.report'
_description = 'WPS Report'
_columns = {
'date_from':fields.date("Start Date"),
'date_to':fields.date("End Date"),
'company_id': fields.many2one('res.company', 'Company', select=True, required=False),
}
_defaults = {
'date_from': lambda *a: time.strftime('%Y-%m-01'),
'date_to': lambda *a: str(datetime.now() + relativedelta.relativedelta(months=+1, day=1, days=-1))[:10],
'company_id': lambda self, cr, uid, context: self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.id,
}
def print_report(self, cr, uid, ids, data, context=None):
if context is None:
context = {}
data['form'] = self.read(cr, uid, ids, ['date_from', 'date_to', 'company_id'], context=context)[0]
return self.pool['report'].get_action(cr, uid, [], 'hr_wps.report_wpsreport', data=data, context=context)
in my report:
class wpsreport(report_sxw.rml_parse):
def __init__(self, cr, uid, name, context):
super(wpsreport, self).__init__(cr, uid, name, context=context)
self.localcontext.update({
'time': time,
'get_lines': self._get_lines,
})
def set_context(self, objects, data, ids, report_type=None):
self.date_start = data['form'].get('date_from', time.strftime('%Y-%m-%d'))
self.date_end = data['form'].get('date_to', time.strftime('%Y-%m-%d'))
self.company_id = data['form'].get('company_id')
return super(wpsreport, self).set_context(objects, data, ids, report_type=report_type)
def _get_lines(self, form):
res = []
self.cr.execute("""SELECT hr_employee.name_related,
(SELECT hr_payslip_line.total
FROM hr_payslip_line, hr_payslip
WHERE hr_employee.id = hr_payslip.employee_id
AND hr_payslip_line.slip_id = hr_payslip.id
AND hr_payslip_line.code = 'BASIC'
AND hr_payslip.date_from BETWEEN %s AND %s) as basic,
(SELECT hr_payslip_line.total
FROM hr_payslip_line, hr_payslip
WHERE hr_employee.id = hr_payslip.employee_id
AND hr_payslip_line.slip_id = hr_payslip.id
AND hr_payslip_line.code = 'ALLOWANCES'
AND hr_payslip.date_from BETWEEN %s AND %s) as total_allowance,
(SELECT hr_payslip_line.total
FROM hr_payslip_line, hr_payslip
WHERE hr_employee.id = hr_payslip.employee_id
AND hr_payslip_line.slip_id = hr_payslip.id
AND hr_payslip_line.code = 'DEDUCTIONS'
AND hr_payslip.date_from BETWEEN %s AND %s) as total_deduction,
(SELECT hr_payslip_line.total
FROM hr_payslip_line, hr_payslip
WHERE hr_employee.id = hr_payslip.employee_id
AND hr_payslip_line.slip_id = hr_payslip.id
AND hr_payslip_line.code = 'NET'
AND hr_payslip.date_from BETWEEN %s AND %s) as total
FROM hr_employee,
hr_payslip,
res_company
WHERE hr_payslip.employee_id = hr_employee.id
AND hr_payslip.company_id = res_company.id
AND hr_payslip.date_from BETWEEN %s AND %s
AND hr_payslip.company_id = %s""", (self.date_start, self.date_end, self.date_start, self.date_end, self.date_start, self.date_end, self.date_start, self.date_end, self.date_start, self.date_end, self.company_id))
employees = self.cr.dictfetchall()
for emp in employees:
value = {}
value['name_related'] = emp['name_related']
value['basic'] = emp['basic']
value['total_allowance'] = emp['total_allowance']
value['total_deduction'] = emp['total_deduction']
value['total'] = emp['total']
value['No_working_days'] = 30
value['extra_hours'] = 0
res.append(value)
return res
But I'm getting Error of:
QWebException: "invalid input syntax for integer: "Yourcompany"
AND hr_payslip.company_id = ARRAY[9, 'Yourcompany']
How to fix it?
Try with:
hr_payslip.company_id.id
well I found an answer for my problem and it fixed it
instead of self.company_id in the sql query
replace it with self.company_id[0]

Django updates model instead of inserting (pk=None) (INSERT INTO QUERY)

I'm trying to save a model entry but django insists on updating old entries instead of creating new ones. Here is my code for creating a new entry:
the print statment show log_entry.pk = None before save and log_entry = old_entry.pk after save.
log_entry = QuoteResponseLog()
log_entry.quote_response = self
log_entry.manager = manager
log_entry.message = action.log()
print(log_entry)
log_entry.save(force_insert=True)
print(log_entry)
Edit: QuoteResponseLog model (Django-model-utils)
from model_utils.models import TimeStampedModel
class QuoteResponseLog(TimeStampedModel):
quote_response = models.ForeignKey(
QuoteResponse
)
manager = models.ForeignKey(
Manager
)
message = models.CharField(max_length=256)
def __unicode__(self):
return str(self.created) + " : [" + str(self.manager) + "] : " + self.message + "(" + str(self.pk) + ")"
EDIT 2:
Log entry from actual sql query:
{u'time': u'0.003', u'sql': u'QUERY = u\'INSERT INTO "quote_hub_quoteresponselog" ("created", "modified", "quote_response_id", "manager_id", "message") VALUES (%s, %s, %s, %s, %s)\' - PARAMS = (u\'2014-09-08 11:57:10.150000\', u\'2014-09-08 11:57:10.172000\', 6, 3, u\'Godk\\xe4nnde\')'}
EDIT3: SQLQuery inserted in dbshell works correctly.
The error was trivial, a cascade delete. Deleted self before assignment to lg_entry.quote_response.

Render data on two templates from one function Django

Hi i need to render the data on two templates from one function my code is
def stylepoints(request):
a=Product.objects.all()[:3]
cursor = connection.cursor()
try:
cursor.execute("SELECT facebook_id,name FROM django_facebook_facebookuser WHERE user_id = %s ORDER BY RAND() LIMIT 1",[request.user.id])
except Exception as e:
return HttpResponse("error in fetching Friends")
rows_affected=cursor.rowcount
if rows_affected > 0:
row1 = cursor.fetchall()
row12 = row1[0]
else:
row12 = ''
value = request.user.id
cursor12 = connection.cursor()
cursor12.execute("SELECT Distinct email FROM myaccount_invitation WHERE reference_id = %s AND status = 1 AND invitation_type = 2",[value])
friend = cursor12.fetchall()
if friend:
friends = friend[0]
return render_to_response('swf.html',{'a':a,'userf':row12,'friendshow':friend} , context_instance=RequestContext(request))
like in this i have send a data to one template name as
swf.html
but i need to send the data also to another template such as
swf2.html
please tell me can i render a data to two templates
def view1(request):
template_name='swf1.html'
return stylepoints(request, template_name)
def view2(request):
template_name='swf2.html'
return stylepoints(request, template_name)
def stylepoints(request, template_name):
a=Product.objects.all()[:3]
cursor = connection.cursor()
try:
cursor.execute("SELECT facebook_id,name FROM django_facebook_facebookuser WHERE user_id = %s ORDER BY RAND() LIMIT 1",[request.user.id])
except Exception as e:
return HttpResponse("error in fetching Friends")
rows_affected=cursor.rowcount
if rows_affected > 0:
row1 = cursor.fetchall()
row12 = row1[0]
else:
row12 = ''
value = request.user.id
cursor12 = connection.cursor()
cursor12.execute("SELECT Distinct email FROM myaccount_invitation WHERE reference_id = %s AND status = 1 AND invitation_type = 2",[value])
friend = cursor12.fetchall()
if friend:
friends = friend[0]
return render_to_response(template_name,{'a':a,'userf':row12,'friendshow':friend} , context_instance=RequestContext(request))

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

"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)

Relation between models with composite keys

I have two models with composite keys:
class ContestUser(models.Model):
user_id = models.IntegerField(primary_key = True)
contest_id = models.IntegerField(primary_key = True)
username = models.CharField(max_length = 1536, blank = True)
.
.
.
class ContestRegistration(models.Model):
user_id = models.IntegerField(primary_key = True)
contest_id = models.IntegerField(primary_key = True)
status = models.IntegerField(choices = EJUDGE_CONTEST_STATUSES)
.
.
.
First question is How can I relate them, and query like in join.
Select * from ContestRegistration r join ContestUser u on r.user_id = u.user_id and r.contest_id = u.contest_id where r.contest_id = 3;
Second is How to save an object like this?
cuser = ContestUser.objects.get(user_id = 1, contest_id = 1)
cuser.username = 'username'
cuser.save()
This results in IntegrityError: (1062, "Duplicate entry '1-1' for key 'PRIMARY'")
Executed SQL is:
SELECT * FROM `users` WHERE (`users`.`contest_id` = 1 AND `users`.`user_id` = 1 );
SELECT (1) AS `a` FROM `users` WHERE `users`.`user_id` = 1 LIMIT 1;
UPDATE `users` SET ... WHERE `users`.`user_id` = 1 ;
Django models don't support multiple primary keys: https://docs.djangoproject.com/en/1.3/faq/models/#do-django-models-support-multiple-column-primary-keys
However, as the documentation describes, you can use other properties on ForeignKey fields, like unique_together to do the same thing. Hope that helps you out.