Primary key and unique key in django - django

I had a custom primary key that need to be set up on a particular data in a model.
This was not enough, as an attempt to insert a duplicate number succeeded. So now when i replace primary_key=True to unique=True it works properly and rejects duplicate numbers!!. But according this document (which uses fields).
primary_key=True implies null=False
and unique=True.
Which makes me confused as in why does
it accept the value in the first place
with having an inbuilt unique=True ?
Thank you.
Updated statement:
personName = models.CharField(primary_key=True,max_length=20)

Use an AutoField with primary_key instead.
Edit:
If you don't use an AutoField, you'll have to manually calculate/set the value for the primary key field. This is rather cumbersome. Is there a reason you need ReportNumber to the primary key? You could still have a unique report number on which you can query for reports, as well as an auto-incrementing integer primary key.
Edit 2:
When you say duplicate primary key values are allowed, you indicate that what's happening is that an existing record with the same primary key is updated -- there aren't actually two objects with the same primary key in the database (which can't happen). The issue is in the way Django's ORM layer chooses to do an UPDATE (modify an existing DB record) vs. an INSERT INTO (create a new DB record). Check out this line from django.db.models.base.Model.save_base():
if (force_update or (not force_insert and
manager.using(using).filter(pk=pk_val).exists())):
# It does already exist, so do an UPDATE.
Particularly, this snippet of code:
manager.using(using).filter(pk=pk_val).exists()
This says: "If a record with the same primary key as this Model exists in the database, then do an update." So if you re-use a primary key, Django assumes you are doing an update, and thus doesn't raise an exception or error.
I think the best idea is to let Django generate a primary key for you, and then have a separate field (CharField or whatever) that has the unique constraint.

Related

Changing primary key in Django caused constraint does not exist error

I have Django project with DigestIssue model among others and there were Django auto created primary key field id and my field number. I wanted to get rid of duplication and set number as PK because number is unique and with same values as id. But I have foreign keys referencing this model.
I doubt that they will migrate automatically after such operation. I tried, hoping for such automigration and got constraint "idx_16528_sqlite_autoindex_gatherer_digestissue_1" of relation "gatherer_digestissue" does not exist error ("sqlite" in constraint name is historical thing, I switched to PostgreSQL a time go). I tried more complicated way, following https://blog.hexack.fr/en/change-the-primary-key-of-a-django-model.html but got same error on PK switching step.
So the question is - how to replace in Django old primary key with new one with same values and referenced by other models?

Django foreign key: auto-lookup related object when the update record has the key value

I have legacy code which had no foreign keys defined in the schema.
The raw data for the row includes the key value of the parent, naturally.
My first porting attempt to postgresql just updated the field with the raw value: I did not add foreign keys to Django's models.
Now I am trying to add foreign keys to make the schema more informative.
When I add a foreign key, django's update requires me to provide an instance of the parent object: I can no longer update by simply providing the key value. But this is onerous because now I need to include in my code knowledge of all the relations to go and fetch related objects, and have specific update calls per model. This seems crazy to me, at least starting from where I am, so I feel like I am really missing something.
Currently, the update code just pushes rows in blissful ignorance. The update code is generic for tables, which is easy when there are no relations.
Django's model data means that I can find the related object dynamically for any given model, and doing this means I can still keep very abstracted table update logic. So this is what I am thinking of doing. Or just doing raw SQL updates.
Does a solution to this already exist, even if I can't find it? I am expecting to be embarrassed.
The ValueError comes in django ORM code which knows exactly which model it expects and what the related field is: the missing step if to find the instance of related object.
db.models.fields.related_descriptors.py:
in this code, which throws the exception, value is supposed to be an instance of the parent model. Instead, value is the key value. This basically I think tells me how I can inspect the model to deal with this in advance, but I wonder if I am re-inventing the wheel.
if value is not None and not isinstance(value, self.field.remote_field.model._meta.concrete_model):
raise ValueError(
'Cannot assign "%r": "%s.%s" must be a "%s" instance.' % (
value,
instance._meta.object_name,
self.field.name,
self.field.remote_field.model._meta.object_name,
)
)
You could use _id suffix to set id value directly
For given model
class Album(models.Model):
artist = models.ForeignKey(Musician, on_delete=models.CASCADE)
You can set artist by id in following manner
Album.objects.create(artist_id=2)

Can I create a related Django field between two models with a shared foreign key value?

I have two models:
class Foo(Model):
special_id = IntegerField(primary_key=True)
class FooDetail(Model):
special_id = IntegerField(primary_key=True)
special_id comes from an outside source -- it's a foreign key into another database. Yes, Foo and FooDetail should be combined into a single model -- but assuming I can't -- can I create a related field between the two models such that I can use it in queries (like in values or select_related)?
I could add a ForeignKey('FooDetail') in Foo, but I'd be essentially storing the special_id twice.
If you want to use the ORM's features for related models, you should create a relationship (one-to-one in this case) between the two models. In one of the models you can (and should) then omit the special_id reference.
You can use the foreign key as a primary key in FooDetail, and if you keep special_id as a primary key in Foo, you'll be saving exactly the same type and amount of columns and data as in your example (namely one column in each that contains the relevant special_id).
What you get though is the benefit of a relationship and enforced integrity.
The only difference is that when you introduce a new special_id, you have to create Foo first to be able to point to it in FooDetail – hardly a big price to pay.
If you get a warning on setting the reference field to Foo to be the primary key then it might be that you defined it as a ForeignKey. You should define the field as a OneToOneField since you're dealing with a one-to-one relationship as noted above. The field is still technically a foreign key (= reference to the primary key of a row in another table) which is why I used this term; but it has a unique constraint that allows it to be used as a primary key.

How to create a foreign key for a non-key table field?

Simply put, i want to create a structure that has a component MAKTX, and to have a foreign key relation with MAKT-MAKTX.
More generally i want to have a foreign key check for a field that's not part of a primary key.
I see the button "Non-key-fields/candidates", but i don't really know how to use it.
Also, i don't want to use the "key fields of a text table" relation... but i don't know if that's relevant.
Is this even a good thing that i'm trying to do? I don't see any reason why it shouldn't be possible, but you might object.
[EDIT]: I have to mention that I don't really know what I'm doing. I really just want to fill a table i created with values from another, and to make sure that those values (namely MAKTX - kind ofvalues) in my table are always values from MAKT. Suppose i do the initial filling with a SELECT statement, i want the consistency to work even if i later insert new entries manually.
So I don't know whether this makes sense or not, it just sounds to me like a good idea to have the system perform this check automatically, if possible.
Main condition for creating foreign key relation is that the field should be a primary key in your reference table. While in the table you are creating foreign key its not necessary that the field is a primary key or not. The main reason for this is that foreign key cant be null.
Refer to below link for step by step process for creating foreign key relation in abap.
http://learnabaponline.blogspot.in/2013/04/how-to-create-table-in-abap.html
First off, I agree with vwegerts's comments, what you're trying to do doesn't seem to make any sense.
Perhaps this would make more sense: create your own table without the MAKTX field. Then create a database view, joining your table and the MAKT table (and set a default language in the selection conditions if you want to). This way you'll have the descriptions joined with your data, without duplicating the actual data (which is what it looks like you're trying to do).

Django and sqlite email authentication

I wanted to create an email authenticated django user model, and I basically followed the steps in this website:
http://www.micahcarrick.com/django-email-authentication.html
And also included the table alteration code in a post_syncdb function in a managmenet module, to make the email a unique identifier. This should work ok with MySql. BUT, it wont work for sqlite. This is because sqlite's table alteration is limited and wont allow you to change that attribute OR even add a column with a unique identifier.
If there is no elegant way of doing this, then I might have to switch to MySql.
http://www.sqlite.org/faq.html#q26
So, it UNIQUE is fully supported, but you cannot alter a table using UNIQUE. So dump the table to a new table that has the UNIQUE constraint then alter and rename the tables. Or just dump it, modify the dump and reimport it.
I think, in your post_syncdb hook, you can add:
cursor.execute(
"CREATE UNIQUE INDEX IF NOT EXISTS auth_user_email_unique "
"ON auth_user (email COLLATE NOCASE);"
)
you may have to break out different blocks based on settings.DATABASES['default']['ENGINE']