Django select all - django

I have a model-Volunteer and I'm trying to access the table thru python shell.
>>> vollist = Volunteer.objects.all()
>>> vollist
[<Volunteer: Volunteer object>]
For some reason, I dont see the rows that were added.

Related

Django inspectdb ORA-00942: table or view does not exist

Im trying to import existing oracle tables in django.
Installed cx_oracle and i did all the steps for django to communicate with my oracle db.
import cx_Oracle
con = cx_Oracle.connect("PYTHON","PYTHON", "METDBR")
cur = con.cursor()
cur.execute("select * from ICUSTOMER")
res = cur.fetchall()
for row in res:
print(row)
works fine....
when im trying to inspect the table with the command
python manage.py inspectdb icustomer
i get
Unable to inspect table 'icustomer'
The error was: ORA-00942: table or view does not exist
Usually, it is about letter case.
By default, Oracle stores table names in UPPERCASE. If you (or whoever created the table) used mixed case and enclosed table name into double quotes, you have to reference the table exactly like that: using the same letter case (as created), enclosed into double quotes.
Therefore, check exact table name.
Check the USER that is configured in your default ENGINE, this is very probably not the user PYTHON.
You must than qualify the inspected table as PYTHON.ICUSTOMER
and grant the access on it the the engine user (while connected as PYTHON)
GRANT SELECT on PYTHON.ICUSTOMER to <engine user>;

Django-ORM: distinct is needed. Why?

I am playing around with django ORM
import django
django.setup()
from django.contrib.auth.models import User, Group
from django.db.models import Count
# All users
print(User.objects.all().count())
# --> 742
# Should be: All users which are in a group.
# But the result is different. I don't understand this.
print(User.objects.filter(groups__in=Group.objects.all()).count())
# --> 1731
# All users which are in a group.
# distinct needed
print(User.objects.filter(groups__in=Group.objects.all()).distinct().count())
# --> 543
# All users which are in a group. Without distinct, annotate seems to do this.
print(User.objects.filter(groups__in=Group.objects.all()).annotate(Count('pk')).count())
# --> 543
# All users which are in no group
print(User.objects.filter(groups__isnull=True).count())
# --> 199
# 199 + 543 = 742 (nice)
I don't understand the second query which returns 1731.
I know that I can use distinct().
Nevertheless 1731 looks like a bug to me.
What is the intention why below query is not distinct/unique?
User.objects.filter(groups__in=Group.objects.all())
Raw MySQL query looks like this:
SELECT user.id, group.id FROM user LEFT JOIN group ON user.group_id = group.id
The result will contain all possible combinations of users and groups and I guess some users belong to more than one group.
You are trying to fetch all users from all groups, but a user can present in multiple groups that's why distinct is required. if you want users ina specific group instead of doing an all try a filter query.
I assume that User.groups is a ForeignKey or some other relationship that associates each User with zero to many Group instances.
So the query which confuses you:
User.objects.filter(groups__in=Group.objects.all())
That query can be described as:
Access the Group model manager (Group.objects).
Make a QuerySet:
Return all Group instances (Group.objects.all()).
Access the User model manager (User.objects).
Make a Queryset:
Join to the Group model, on the User.groups foreign key.
Return every (User + Group) row which has an associated Group.
That is not “all users which are in a group”; instead, it is “All user–group pairs where the group exists”.
By querying on each of the multiple-value User.groups field, you are implying that the query must contain a join from User to Group rows.
Instead, you want:
Access the User model manager (User.objects).
Make a QuerySet:
Return all rows which have groups not empty.
User.objects.filter(groups__isnull=False)
Note that this – “All users which have a non-empty set of associated groups” – is the inverse of another example query you have (“All users which are in no group”).
Since groups is a ManyToManyField the query translated into INNER JOIN statement.
If you print the following you will see the query generated by the QuerySet:
>>> print(User.objects.filter(groups__in=Group.objects.all()).query)
SELECT `auth_user`.`id`, .... , `auth_user`.`date_joined` FROM `auth_user` INNER JOIN `auth_user_groups` ON (`auth_user`.`id` = `auth_user_groups`.`user_id`) WHERE `auth_user_groups`.`group_id` IN (SELECT `auth_group`.`id` FROM `auth_group`)
As you would see the query joins auth_user and auth_user_groups tables.
Where auth_user_groups is the ManyToManyField table not the table for Group model. Thus a user will come more than once.
You would want to use annotate get users having grous, in my case the numbers are following:
$ ./manage.py shell
>>>
>>> from django.contrib.auth.models import User, Group
>>> from django.db.models import Count
>>>
# All users
>>> print(User.objects.all().count())
556
>>>
# All users which are not in a group.
>>> print(User.objects.annotate(group_count=Count('groups')).filter(group_count=0).count())
44
>>>
# All users which are in a group.
>>> print(User.objects.annotate(group_count=Count('groups')).filter(group_count__gt=0).count())
512
>>>
Annotate is similar to distinct in behaviour. It creates a group by query. You can see and inspect the query as following.
>>> print(User.objects.annotate(group_count=Count('groups')).filter(group_count__gt=0).query)
SELECT `auth_user`.`id`, `auth_user`.`password`, `auth_user`.`last_login`, `auth_user`.`is_superuser`, `auth_user`.`username`, `auth_user`.`first_name`, `auth_user`.`last_name`, `auth_user`.`email`, `auth_user`.`is_staff`, `auth_user`.`is_active`, `auth_user`.`date_joined`, COUNT(`auth_user_groups`.`group_id`) AS `group_count` FROM `auth_user` LEFT OUTER JOIN `auth_user_groups` ON (`auth_user`.`id` = `auth_user_groups`.`user_id`) GROUP BY `auth_user`.`id` HAVING COUNT(`auth_user_groups`.`group_id`) > 0 ORDER BY NULL
When you run a 'DISTINCT' query against a database you end up with a listing of each distinct row in the data results. The reason that you have more 'DISTINCT' rows in your Django result is there is a combinatoric cross multiplication going on, creating extra results.
Other answers have mentioned all of this, but since you're asking the why:
The ORM, in this join, would probably allow you to pull fields attached to the group from the query. So if you wanted, say, all these users and all the groups and the group contact for some kind of massive weird mail merge, you could get them.
The post-processing brought on by DISTINCT is narrowing your results down according to the fields you have pulled rather than the rows in the query. If you were to use the PyCharm debugger or something, you might find that the groups aren't as easy to access using various ORM syntax when you have the distinct as when you don't.

lower() in django model

This is my query
SELECT * FROM `music` where lower(music.name) = "hello"
How can I send this query with django
I tried this but it didn't add lower in the query
>>> Music.objects.filter(name__iexact="hello")
(0.144) SELECT `music`.`id`, `music`.`name`, `music`.`artist`, `music`.`image`, `music`.`duration`, `music`.`release_date`, `music`.`is_persian` FROM `music` WHERE `music`.`name` LIKE 'hello' LIMIT 21; args=('hello',)
<QuerySet []>
You can use Lower database function as below.
>>> from django.db.models.functions import Lower
>>> lower_name_music = Music.objects.annotate(lower_name=Lower('name'))
>>> lower_name_music.filter(lower_name__iexact="hello")
First statement is to import the database function.
Second statement is to add calculated column named lower_name using
Lower function on name column. At this time database is not yet been
queried.
Third statement is to filter using the calculated column. As this
statement prints out result, a query is actually executed against
database.

Different count results from django and database directly

Does Django limit the number of records it checks by default? I am getting two different results from Django shell and database directly.
Database
SELECT count(*) FROM datapoints WHERE sk='dfVRRZOe2O68dEA';
count
-------
11519
Python django shell.
>>> key = 'dfVRRZOe2O68dEA'
>>> print datapoints.objects.filter(sk=key).count()
10000
>>>

Data synchronization issue with Django

I have the following models.py:
class BagOfApples(models.Model):
quantity = models.PositiveSmallIntegerField(default = 0)
Let's create a “bag of apples” object and put an “apple” in it:
>>> from myapp import models
>>>
>>> models.BagOfApples().save()
>>>
>>> bag1 = models.BagOfApples.objects.get(pk = 1)
>>> bag2 = models.BagOfApples.objects.get(pk = 1)
>>>
>>> bag1.quantity += 1
>>> bag1.save()
>>>
>>> bag1.quantity
1
>>> bag2.quantity
0
Is there a way to automatically reload the data in the bag2 variable?
In my real-world application, things are a bit more complicated than that, and the same objects can be modified in different parts of the code after being retrieved by different database queries. This is not even intentional (for instance, this problem occurs to me because Django caches results for OneToOne or ForeignKey relationships).
It would be really helpful to have some kind of manager (maybe a middleware can do this?) that keeps track of the identical objects.
In this example, the manager would automatically detect that bag2 is actually bag1, and would not execute a second query but simply return bag1.
If there is no good way to do this, any other helpful tips on better application design would be appreciated.
The key is to understand when your query is actually executed. The model object will not repeat the query each time you want to access one of its model fields.
To avoid keeping around objects with stale data, I would make sure to query when I actually need to data. In your example, I'd hold on to the information that you know is not going to change (the pk value), and do a get when you need the object with fresh values.
from myapp import models
models.BagOfApples().save()
bag1 = models.BagOfApples.objects.get(pk = 1)
bag1.quantity += 1
bag1.save()
print bag1.quantity # will print 1
bag2 = models.BagOfApples.objects.get(pk = 1)
print bag2.quantity # will print 1 too