I´m trying to delete_all the results of a query with a join between two tables like:
availabilitiesToDelete = Mmk::Availability.find_by_sql(["SELECT a.id
FROM mmk_availabilities a, mmk_resources r
WHERE a.resource_id = r.id
AND r.company_id = ?", mmkCompany.id])
availabilitiesToDelete.delete_all
but I´m getting error
NoMethodError (undefined method `delete_all' for #<Array:0x007fa657f2a4e0>)
How can I do it?
find_by_sql in rails-4 return Array object and not a ActiveRecord::Relation object. delete_all is AR query which will throw error in your case.
Perhaps you can proceed further as,
availabilitiesToDelete.each(&:delete)
As ray has already pointed out in his answer, find_by_sql will return an Array on which you therefore cannot call delete_all.
However, you could use a second query to delete all the records at once without causing an n+q query like this:
Mmk::Availability.where(id: availabilitiesToDelete.map(&:id)).delete_all
Related
To optimize a lot my database I would like to make as less as possible any query.
I'm trying to get an object, increment the field "count_limit" and make an If statement after on the Customer instance.
To achieve it I've made this query who worked well.
Customer.objects.filter(user=user).update(count_limit=F('count_limit') + 1)
So after this query, count_limit has been incremented by 1 as I wanted.
When I'm trying to get the Customer instance as a result of this query, it returns "1".
Is it possible to make both, update the instance and get it as a return object ?
Thanks a lot
The update() method will return the number of updated rows. If you are using Postgres, then you can use the returning clause with the raw query.
query = 'UPDATE customer SET count_limit=(customer.count_limit + 1) WHERE customer.user_id=%s returning *'
updated_obj = Customer.objects.raw(query, [user.id])
I don't know if this can be achieved by ORM, but suggestions will be appreciated.
Make sure that the table name in raw query is correct. If you haven't definer db_table in the meta class of your model, then by default it will be myapp_model.
And to prevent SQL injection, from the Docs:
Do not use string formatting on raw queries or quote placeholders in
your SQL strings!
Follow Docs on raw()
You are looking for F functions: https://docs.djangoproject.com/en/3.0/ref/models/expressions/#f-expressions
Example from their documentation how to increase a counter
from django.db.models import F
reporter = Reporters.objects.get(name='Tintin')
reporter.stories_filed = F('stories_filed') + 1
reporter.save()
I am trying to annotate User with the count of delayed leads objects. The calculation of delayed leads is complex (uses RawSQL) implemented using a custom model manager. Hence, I am trying to implement this using a subquery.
sq = Lead.delayed.filter(assigned_to_id=OuterRef('pk'))
User.objects.annotate(num=Count(Subquery(sq.count())))
However, I keep getting this error:
ValueError: This queryset contains a reference to an outer query and may only be used in a subquery.
UPDATE:
I tried adding only('id') so my code:
sq = Lead.delayed.filter(assigned_to_id=OuterRef('id')).only('id')
User.objects.annotate(num=Count(Subquery(sq)))
This generated the sql query:
SELECT `auth_user`.`id`, `auth_user`.`username`, `auth_user`.`first_name`,
`auth_user`.`last_name`, COUNT((SELECT U0.`id` FROM
`lead` U0 WHERE U0.`assigned_to_id` = (`auth_user`.`id`))) AS `count`
FROM `auth_user` GROUP BY `auth_user`.`id`;
This is throwing error:
ERROR 1242 (21000): Subquery returns more than 1 row
I would like to have my query generated as:
SELECT `auth_user`.`id`, `auth_user`.`username`, `auth_user`.`first_name`,
`auth_user`.`last_name`, (SELECT COUNT(U0.`id`) FROM `marketing_lead` U0 WHERE
(more complex conditions here) U0.`assigned_to_id` = (`auth_user`.`id`)) AS `count`
FROM `auth_user` GROUP BY `auth_user`.`id`;
How can I acheive that using django ORM?
Alternative question label might be How to use Count() not perform grouping (GROUP BY) or How to count all in a Subquery
Check this answer for custom Count function to just perform simple count on any queryset without grouping.
Unfortunately, so far haven't found native django option for this.
Though the answer from Oleg was quite close to my requirement but I was still getting an SQL error on the query generated by django. Hence, I ended up implementing using cursor.
House.objects.filter(owner__isnull=True) will produces following SQL:
SELECT "app_House"."id", "app_House"."name" FROM "app_House"
LEFT OUTER JOIN "app_Owner" ON ("app_House"."id" = "app_Owner"."house_id")
WHERE "app_Owner"."id" IS NULL
Is there a syntax available to force Django to omit the where clause?
If I understand you correctly, you want to select all houses without doing a database query each time you need informations about the owner.
For this Case the django-api hast the select_related() method. In your case you would have to use the following query:
House.objects.all().select_related('owner')
I’m trying to retrieve individual attributes from a record after retrieving it from the database. I get an error indicating an undefined method.
I retrieve the table here:
t = Table.where('##fil = ? ', r.referenced_object_ID)
I know I’m getting a record because I can list all the attributes in the record using:
t.to_json
and get this result:
[{"##fil":"1026.0","objtyp":"FIL","objatr":"CPT","fil":"Account”,…
However, when I try to use:
t.fil
I get
undefined method ‘fil’…
To directly get single record if fil is unique
t = Table.find_by_fil(r.referenced_object_ID)
If fil is not unique then use your approach then use
t.first.fill #to get first record
Or if you need all record use loop
t..each do |tbl|
tbl.fil
end
'where' clause always returns us an array. So in your case you can access it as
t.first.fil
I have a problem with Doctrine (Symfony2.1). I want to prevent lazy-loading by join fetching subentities (OneToMany relation) but I got only one result for those subentities.
For example:
public function getSingleProjectQuery($project){
$query = $this->createQueryBuilder('p')
->select(array("p", "fb"))
->where('p.id = :project_id')->setParameter('project_id', $project)
->leftJoin('p.feedbacks', 'fb')
->groupBy('p.id')
->getQuery();
return $query;
}
In this example Doctrine returns me the "Project"-object and one single "feedback" object (but there are more than one feedbacks...).
When I replace the select to this: ->select(array("p"))
I got all the "Feedback" objects but there are then lazy-loaded (many queries).
see http://docs.doctrine-project.org/en/latest/reference/dql-doctrine-query-language.html#joins
You should remove the groupBy clause.