I have to table with relation.
State
id
name
City
id
name
state
Which is better in performance?
city.state.id or city.state_id
city.state_id is better anyway. city.state will do another fetch from database.You can avoid this using select_related.If you need only id of foriegn key, no need of select_related here.Just do city.state_id(since foriegn key id will fetch in the query which gives city object).
city.state_id is better than city.state.id. Because It makes only a query instead of two.
BTW, You can use Django Debug Toolbar for debugging queries.
the <field>_id field you see is the database column name
docs
Behind the scenes, Django appends "_id" to the field name to create its database column name. In the above example, the database table for the Car model will have a manufacturer_id column
So this means it doesn't need to make a separate query to retrieve the foreign key instance (See Select a single field from a foreign key for more details).
But this assumes you haven't used select_related or prefetch_related
Related
I'm having a problem and don't have much time so solve it.
I have thoses tables in my database, one called wall and the other is users.
For the wall table, I can add a foreign like you can see :
But in the users table, I can't and I don't know why. Both tables are empty.
Here you can see the users table :
And this is the error code I get :
I think there is not possible to create foreign key to the same table.
In this SQL you change table 'user' and add to this table foreign key from 'user' table.
If I'm wrong please correct me.
Here is example:
alter table `wall` add constraint `id_user_constraint_name` foreign key (`id_user`) references `users`(id);
If you don't have a 'id_user' column use this sql:
alter table `wall` add column id_user bigint;
Is it possible to change primary key of many to many field from default to uuid?
Table is already populated. What is the best way for migration?
You can create a migration that executes raw queries, add a new field to the table in the middle then generate the new UUID.
After that, another set of queries to drop the constraints on ID, add the new constraints to the new UUID field, and lastly drop the old ID field.
https://docs.djangoproject.com/en/2.0/ref/migration-operations/#runsql
**
Difference between creating a foreign key for consistency and for joins
**
I am fine to use Foreignkey and Queryset API with Django.
I just want to understand little bit more deeply how it works behind the scenes.
In Django manual, it says
a database index is automatically created on the ForeignKey. You can
disable this by setting db_index to False. You may want to avoid the
overhead of an index if you are creating a foreign key for consistency
rather than joins, or if you will be creating an alternative index
like a partial of multiple column index.
creating for a foreign key for consistency rather than joins
this part is confusing me.
I expected that you use Join keyword if you do query with Foreign key like below.
SELECT
*
FROM
vehicles
INNER JOIN users ON vehicles.car_owner = users.user_id
For example,
class Place(models.Model):
name = models.Charfield(max_length=50)
address = models.Charfield(max_length=50)
class Comment(models.Model):
place = models.ForeignKeyField(Place)
content = models.Charfield(max_length=50)
if you use queryset like Comment.objects.filter(place=1), i expected using Join Keyword in low level SQL command.
but, when I checked it by printing out queryset.query in console, it showed like below.
(I simplified with Model just to explains. below, it shows all attributes in my model. you can ignore attributes)
SELECT
"bfm_comment"."id", "bfm_comment"."content", "bfm_comment"."user_id", "bfm_comment"."place_id", "bfm_comment"."created_at"
FROM "bfm_comment" WHERE "bfm_comment"."place_id" = 1
creating a foreign key for consistency vs creating a foreign key for joins
simply, I thought if you use any queryset, it means using foreign key for joins. Because you can get parent's table data by c = Comment.objects.get(id=1) c.place.name easily. I thought it joins two tables behind scenes. But result of Print(queryset.query) didn't how Join Keyword but Find it by Where keyword.
The way I understood from an answer
Case 1:
Comment.objects.filter(place=1)
result
SELECT
"bfm_comment"."id", "bfm_comment"."content", "bfm_comment"."user_id", "bfm_comment"."place_id", "bfm_comment"."created_at"
FROM "bfm_comment"
WHERE "bfm_comment"."id" = 1
Case 2:
Comment.objects.filter(place__name="df")
result
SELECT "bfm_comment"."id", "bfm_comment"."content", "bfm_comment"."user_id", "bfm_comment"."place_id", "bfm_comment"."created_at"
FROM "bfm_comment" INNER JOIN "bfm_place" ON ("bfm_comment"."place_id" = "bfm_place"."id")
WHERE "bfm_place"."name" = df
Case1 is searching rows which has comment.id column is 1 in just Comment table.
But in Case 2, it needs to know Place table's attribute 'name', so It has to use JOIN keyword to check values in column of Place table. Right?
So Is it alright to think that I create a foreign key for joins if i use queryset like Case2 and that it is better to create index on the Foreign Key?
for above question, I think I can take the answer from Django Manual
Consider adding indexes to fields that you frequently query using
filter(), exclude(), order_by(), etc. as indexes may help to speed up
lookups. Note that determining the best indexes is a complex
database-dependent topic that will depend on your particular
application. The overhead of maintaining an index may outweigh any
gains in query speed
In conclusion, it really depends on how my application work with it.
If you execute the following command the mystery will be revealed
./manage.py sqlmigrate myapp 0001
Take care to replace myapp with your app name (bfm I think) and 0001 with the actual migration where the Comment model is created.
The generated sql will reveal that the actual table is created with place_id int rather than a place Place that is because the RDBMS doesn't know anything about models, the models are only in the application level. It's the job of the django orm to fetch the data from the RDBMS and convert them into model instances. That's why you always get a place member in each of your Comment instances and that place member gives you access to the members of the related Place instance in turn.
So what happens when you do?
Comment.objects.filter(place=1)
Django is smart enough to know that you are referring to a place_id because 1 is obviously not an instance of a Place. But if you used a Place instance the result would be the same. So there is no join here. The above query would definitely benefit from having an index on the place_id, but it wouldn't benefit from having a foreign key constraint!! Only the Comment table is queried.
If you want a join, try this:
Comment.objects.filter(place__name='my home')
Queries of this nature with the __ often result in joins, but sometimes it results in a sub query.
Querysets are lazy.
https://docs.djangoproject.com/en/1.10/topics/db/queries/#querysets-are-lazy
QuerySets are lazy – the act of creating a QuerySet doesn’t involve
any database activity. You can stack filters together all day long,
and Django won’t actually run the query until the QuerySet is
evaluated. Take a look at this example:
I have 3 tables say, TextObj, User, SecurityCheck. The third table has a Foreign Key attribute (textobj) referencing TextObj and there is a many-to-many field (sharedWith) from SecurityCheck to User.
class SecurityCheck(models.Model):
textobj=models.ForeignKey(TextObj)
owner=models.CharField(max_length=255)
sharedWith=models.ManyToManyField(User)
def __init__(self,owner,filename,requestingUsername):
self.owner=owner
self.textobj=TextObj.filter(filename=filename)
self.sharedWith.add(User.objects.filter(username=requestingUsername))
I need to do a query which fetches all the instances of Textobj which have a particular user in the sharedWith field and a particular filename(which is an attribute of TextObj)
You can easily do queries that span (reverse) relationship:
TextObj.objects.filter(securitycheck__sharedWith=user, filename="foo")
https://docs.djangoproject.com/en/dev/topics/db/queries/#lookups-that-span-relationships
Django offers a powerful and intuitive way to “follow” relationships in lookups, taking care of the SQL JOINs for you automatically, behind the scenes. To span a relationship, just use the field name of related fields across models, separated by double underscores, until you get to the field you want.
It works backwards, too. To refer to a “reverse” relationship, just use the lowercase name of the model.
I've got 2 existing models that I need to join that are non-relational (no foreign keys). These were written by other developers are cannot be modified by me.
Here's a quick description of them:
Model Process
Field filename
Field path
Field somethingelse
Field bar
Model Service
Field filename
Field path
Field servicename
Field foo
I need to join all instances of these two models on the filename and path columns. I've got existing filters I have to apply to each of them before this join occurs.
Example:
A = Process.objects.filter(somethingelse=231)
B = Service.objects.filter(foo='abc')
result = A.filter(filename=B.filename,path=B.path)
This sucks, but your best bet is to iterate all models of one type, and issue queries to get your joined models for the other type.
The other alternative is to run a raw SQL query to perform these joins, and retrieve the IDs for each model object, and then retrieve each joined pair based on that. More efficient at run time, but it will need to be manually maintained if your schema evolves.