Inheriting django Model causes a model to have a default primary key (id),
by default django generates BigAutoField for primary keys.
I have Checked some of the famous apps written in django like posthog, zulip, sentry, mozilla addons-server and all of them have used custom primary key.
(some of them have used both custom primary key and default)
I'm wondering when should we override this behavior and have custom primary key?
to clarify: obviously, my question is not when should change the primary key to something else (e.g. to name or email field), cause that depends on your desicion
actually.
I wanna know what is drawback of the default primary key and should I be worried about it?
One drawback is that the default autofield increments by 1 each time, so your first model instance will have an id of 1 then 2 then 3 etc. Let's say that you can access user public profiles by domain.com/<userid>/profile. This is a security risk because it's trivial to find out the database ID of any given user, the number of users etc, and this holds true for any model that uses that pattern.
Related
The title of this post suggests this may be a simple scenario like this answer but it's actually a bit more complicated.
I'm working on a Blazor site that will serve as a new frontend to an existing set of tables. There is a table of company Clients with a primary key called ClientId.
There are also Users, which represent company employees, with a primary key of UserId.
All of the columns in Client are stored in this table with the exception of the client's relationship to the user (good relationship, don't know them well, etc.). In the existing EmployeeRelationship table, the ClientId and UserId both serve as the primary key, as the EmployeeRelationship is dependent on both the Client and User. This is fine but I have been unable to make EF Core accept this relationship.
What I'd like to do is add the EmployeeRelationship property to my Client object such that I can reference it like Client.EmployeeRelationship.Description. The problem then is the User object, as EF has no idea what to do with the secondary PK on EmployeeRelationships if I call .Include, as there is no FK for User in the Client object.
Would it be possible to provide this foreign key when I call Include on Client?
For example, something like:
Context.Clients.Select(x => x).Include(x => EmployeeRelationship, UserId);
Where {UserId} can be used to provide the missing foreign key.
If not, how can I get around this issue? I also find it odd that whoever created this table used the UserId and ClientId as the primary key because it means the User/Client tables share the same name for the PK, but I'm not sure if this is a problem. It seems like the UserId and ClientId should be foreign keys but this still wouldn't solve my problem.
Is it better to have Id attribute in the model as the primary key despite of no need to use it to uniquely identify records?
I am using asp.net core and entity framework, this is my model
public class PreRegistration
{
public int Id {get; set;}
public string PhoneNumber {get; set;}
public string VerificationCode {get; set;}
}
Is it anyhow useful/better for my model to have an integer Id (auto-incremented) when I can easily use the phone-number for identification purposes?
In ASP.NET Identity Core, the IdentityUser model has an Id attribute when we can easily use Email, UserName, etc attribute to uniquely identify the records. Why is it so?
It is a best practice to have a surrogate key on a table for a few reasons:
Phone numbers, email addresses, and usernames change, even if you are promised that they never will. It might be as simple as the need to allow for fixing typos made by users during data entry.
Numeric keys are easier to reference in a data model. Each foreign key reference will need a copy of the key value.
Numeric keys are very easy to index and are supported by Identity column mechanisms.
Some frameworks do not work as well for updates and deletes without a simple numeric key.
There may be other good reasons, but the most compelling is the first point--the difficulty of changing data that has been used as a primary key and referenced as foreign keys.
Of course, the phone number is likely required to be unique if you were intending to use it as a primary key, so go ahead and add a unique constraint on phone number.
Your question boils down to "should I use a surrogate key or a natural key as my primary key?".
There are 3 requirements for a primary key.
Uniqueness - a primary key must be unique, even in the face of typos, or geography, or data changes. Names are definitely not unique. A phone number is unique within a geography, but you'll need to include international dialing code to guarantee uniqueness. Your data model include a verification code, but not a "status" - so a user entering the wrong phone number could create duplicates on phone number. The combination of phone number and verification code would be unique, but you wouldn't want to use it as a foreign key because you wouldn't know which record has been verified.
Not null - this depends mostly on your business logic, but if there's a state in which you don't yet know the phone number, but want to link the record to other tables, it wouldn't be suitable.
Invariant - you may think phone numbers don't change, but this isn't true. In London, UK, we've had several changes to phone numbers over the last 30 years.
So, the answer to your question is probably to use a surrogate key.
I'm a little confused if I should use composite primary keys or surrogate keys.
Initially I wanted to use composite primary keys when they were needed so have a more clear database, but some parts of the keys could change and JPA doesn't allow to update an object's primary key.
For example I have a Product entity that has a primary key composed of a String code and another entity Account. The code can be updated, but with JPA I can only do that with JPQL which I'd like to avoid. Is it good in this case to use an auto incremented primary key?
Does this mean that the only solution is to use surrogate keys?
Thanks
As you said, according specification JPA does not support update of primary keys:
The application must not change the value of the primary key[10]. The
behavior is undefined if this occurs.[11]
...
[10] This includes not
changing the value of a mutable type that is primary key or an
attribute of a composite primary key.
[11] The implementation may, but
is not required to, throw an exception. Portable applications must not
rely on any such specific behavior.
Using surrogate key is in my opinion best option, most of the time also auto incremented one.
Other option would be removal of entity with original key and recreating it with new key (and other values from original entity). That is plenty of work, especially for entities with many relationships.
HERE,i have seen ER diagram that there is no auto increment id key is available but in data dictionary i saw id .In er diagram which attribute is used as primary key is used as unique key in data dictionary and auto increment id is used as primary key which one is not in the ER diagram.why this happen?
field KEY other NULL?
id Primary key auto increment Not null
Name Unique key Not Null
.... ........... ...........
Can any one say why primary key id is used without showing it in the ER diagram?and why ER diagram's primary key is used as UNIQUE key in the data dictionary?
There is no difference in principle between a primary key and any other key. All keys are supposed to be irreducibly unique and non-nullable whether you choose to designate them as a "primary" one or not. So designating any one primary key when you have several possible candidate keys is a somewhat flexible, informal concept that is only as important as the designer wants it to be. Perhaps the difference you are seeing just reflects different opinions or intended uses. Of course another possibility is that someone made a simple mistake.
The use of I'd might be for consistency; some frameworks assume that every table has id as the primary key, which standardizes/simplifies working with tables. But the "real" primary key from the ER diagram would be a valid key, so why not inform the DB off this by flagging it as UNIQUE?
One possiblity ID is a surrogate key, NAME is natural one, there are a number of advantages to a design using surrogate keys. For instance they are (well should be) immutable.
If there's another table linked by ID, you could change name (e.g. fix a spilling mestike) without breaking referential integrity, or havng to rekey the dependant tables.
Another would be you didn't want Name to be unique anymore, perhaps add another column for context, and make Name and Context a compound unique key, imagine how painful it would be to rework all the related tables.
Rule 1 of surrogates though, don't expose them.
I want to make a primary key from 2 fields in Django.
Fields are below
- current Time
- userId
How Can I do this??
Time + userid {PK } [ Current Time + userid]
Thank you!!
Most of the time, you don't actually need your multi-column key to be the primary key.
Django operates best with surrogate keys - that is, it automatically defines an autoincrement field called id and sets that to be the primary key. That suits for almost all uses.
If you then need to enforce a unique constraint on your model across two or more fields, you can use the unique_together setting in the inner Meta class.
It's not built into Django (see #373), but see the bottom of http://code.djangoproject.com/wiki/MultipleColumnPrimaryKeys for the discussion. I've copied over the "alternative methods" section here for posterity.
Alternative methods
notnotpeter: Currently, you can "fake"
it by declaring one of the keys to be
primary in Django and adding a unique
constraint to the model. (needs more
info...examples?)
mjm: This only works when there is a
non-compound unique key to use, if I
understand what's being proposed here.
As such, it may be workable as a way
to squeeze a design that naturally has
CKs into Django, but it's of no use
for working with an existing schema
that has only the CK.
djansoft: It can be done using
unique-together.
Tobu: You can't use just one key. A
use case for illustration: a
NamespacedTag? model with a CK made of
a namespace and a name. The primary
key can't be just the namespace or
just the name since that would be
ambiguous. The only solution (and I
dislike it since it is bad modelling
and forces database accesses to be
serialized on a counter) is to use an
AutoField?.
toszter: Call me nutty, but why not
declare any number of columns as
primary key in your model, which
django then uses to create a "hidden"
pk_composite column that's just a hash
of the three pk values in the row?
When you do a lookup on a pk, you
assume the ENTIRE combination of
values is the primary key, nothing
more or less. So when you look up
according to the values needed to
create the full pk_composite, the hash
always computes and if the hash
algorithm is public, can be used off
the URL, the querystring in db
lookups, and just about anywhere.
Seems pretty simple in my mind but
then again I am not going into great
detail here.
That being said, I would create an ID on the table and make that the primary key. Then add a unique contraint on the user_id + timestamp.
If the key has to be single-column:
id is added "out-of-the-box" (variable.id) and for current time just add
from django.db import models
date = models.DateTimeField( auto_now_add=True)
in yourapp/models.py
so you have your 2 values, out of witch you can make your key in any shape you want.
if you want multi-column-key then read the other answer. Hope to help you.