I have model AAA with UUID as primary key. Many models have relation to this model.
Now I want to migrate them to use Slug as this primary key, to keep slug value in database as a reference.
What will be the correct way to do that?
Thinking that this might be some multi-step migration. But having many tables that reference to AAA would like to avoid blocking whole db for much time or any other issues in production.
from django.db import models
from django_extensions.db.fields import AutoSlugField
from model_utils.models import UUIDModel
# Django models example
class AAA(models.Model):
id = UUIDField(primary_key=True, version=4, editable=False)
title = models.CharField(max_length=255, unique=True)
slug = AutoSlugField(populate_from='title', primary_key=False)
class BBB(models.Model):
aaa = models.ForeignKey(AAA, on_delete=models.CASCADE)
# ... other fields here ...
class profiles(models.model):
customer_ID = models.IntegerField().primary_key
Is this the correct way of making a primary key in django??
The correct syntax for primary key is-:
class profiles(models.model):
customer_ID = models.IntegerField(primary_key=True)
No, That is not the correct way of making a primary key in Django, in fact you don't have to specify a Primary key for your model, because django will automatically add a field to hold the primary key for you.
In your settings.py file, you will find a line with:
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
which will automatically creates an 'id' field in all of your models by default. The BigAutoField is a 64bit integer that automatically increments according to available ids from 1 to 9223372036854775807.
class Profile(models.Model):
customer_username = models.CharField(max_length=100)
customer_email = models.EmailField()
the Profile model will have three fields: id, customer_username, customer_email
but, in case you want to overide the primary key, let's say for instane by using UUIDs instead of regular ids, you can overide it as follows:
import uuid
class Profile(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4,editable=False)
customer_username = models.CharField(max_length=100)
customer_email = models.EmailField()
for more details, please refer to the django documentation: https://docs.djangoproject.com/en/4.0/ref/models/fields/#primary-key
Is this the correct way of making a primary key in django??
No. You use an AutoField [Django-doc] for a primary key, since then the values are dispatched by the database, so:
class profiles(models.model):
customer_ID = models.AutoField(primary_key=True, editable=False)
But you do not have to specify a primary key: if you do not specify one yourself, Django will add one with the name id to the model automatically.
I have the following model
from django.db import models
class Todo(models.Model):
content = models.CharField(max_length=100)
created_at_one: models.DateField(auto_now_add=True)
finished_at: models.DateField(null=True)
is_completed: models.BooleanField(default=False)
list = models.ForeignKey(
"TodoList", related_name="todos", on_delete=models.CASCADE)
class TodoList(models.Model):
title: models.CharField(max_length=20)
created_at: models.DateField(auto_now_add=True)
Then when I run python manage.py makemigrations and python3 manage.py migrate, there is no error. But when I check the tables created, some columns are missing.
I run .schema app_todo to check the tables of Todo
CREATE TABLE IF NOT EXISTS "app_todo" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "content" varchar(100) NOT NULL, "list_id" bigint NOT NULL REFERENCES "app_todolist" ("id") DEFERRABLE INITIALLY DEFERRED);
CREATE INDEX "app_todo_list_id_c59d99ef" ON "app_todo" ("list_id");
Only id, content and list_id are created and three columns missing.
For TodoList:
CREATE TABLE IF NOT EXISTS "app_todolist" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT);
title and create_at are missing.
Please let me know if there is additional information that I should provide.
Thanks a lot!
You probably made a typo write writing your model. You must not use : but = when declaring your fields. It should be :
from django.db import models
class Todo(models.Model):
content = models.CharField(max_length=100)
created_at_one = models.DateField(auto_now_add=True)
finished_at = models.DateField(null=True)
is_completed = models.BooleanField(default=False)
list = models.ForeignKey(
"TodoList", related_name="todos", on_delete=models.CASCADE)
class TodoList(models.Model):
title = models.CharField(max_length=20)
created_at = models.DateField(auto_now_add=True)
When using : you may create some class attributes but that are not considered by Django for building database models.
I am trying to get unique IDs for my Django objects. In Django 1.8 they have the UUIDField. I am unsure how to use this field in order to generate unique IDs for each object in my model.
Here is what I have for the UUIDField
import uuid
from django.db import models
class MyUUIDModel(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
class Person(models.Model):
...
unique_id = MyUUIDModel()
I can reproduce the id for the UUID model, but everytime I do I get the exact same id. For Example:
person = Person.objects.get(some_field = some_thing)
id = person.unique_id.id
id then gives me the same id every time. What is wrong, how do I fix this?
I'm not sure why you've created a UUID model. You can add the uuid field directly to the Person model.
class Person(models.Model):
unique_id = models.UUIDField(default=uuid.uuid4, editable=False, unique=True)
Each person should then have a unique id. If you wanted the uuid to be the primary key, you would do:
class Person(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
Your current code hasn't added a field to the person. It has created a MyUUIDModel instance when you do MyUUIDModel(), and saved it as a class attribute. It doesn't make sense to do that, the MyUUIDModel will be created each time the models.py loads. If you really wanted to use the MyUUIDModel, you could use a ForeignKey. Then each person would link to a different MyUUIDModel instance.
class Person(models.Model):
...
unique_id = models.ForeignKey(MyUUIDModel, unique=True)
However, as I said earlier, the easiest approach is to add the UUID field directly to the person.
You need to use the class you created as a subclass when declaring your Person model like this:
import uuid
from django.db import models
class MyUUIDModel(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
class Person(MyUUIDModel):
...
This way Person becomes a subclass of MyUUIDModel and will inherit its id field definition.
EDIT: Actually I was wrong. It's not possible yet to implement it as DEFAULT_AUTO_FIELD as it has to inherit from IntegerField. Here's the ticket in the django project with feature request to make it possible. Once it's resolved I'll update my answer.
As of Django 3.2, if you want to use uuid as a pk for all your models on a project-wide level, you don't need a generic abstract model anymore. Just define DEFAULT_AUTO_FIELD setting
default value
DEFAULT_AUTO_FIELD = 'django.db.models.AutoField'
so something like this should work
DEFAULT_AUTO_FIELD = 'django.db.models.UUIDField'
Or even better, create your own field.
DEFAULT_AUTO_FIELD = 'project.common.models.CustomUUIDField'
Where you also define uuid type etc.
As seen in the docs, it can also be applied on an app level.
class MyAppConfig(AppConfig):
default_auto_field = 'project.common.models.CustomUUIDField'
You can directly add the id field as a UUIDField in the Person model. There is no need for a separate MyUUIDModel.
I think you have confused it with the MyUUIDModel used in the UUIDField example where the id is a UUIDField. You can just use the below code and it will use UUIDs for id.
import uuid
from django.db import models
class Person(models.Model):
...
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
To use UUID in Django for a new model see Django Docs.
However, if you want to use it for the existing model (with unique=True) having data corresponding to it, you will not be able to do it directly by the above documentation. It will create migration errors.
To do it without losing the data follow all the steps carefully of this Django Documentation.
in model import uuid:
import uuid
in class model use:
class Article(TimeStampedModel):
uuid = models.UUIDField(editable=False, default=uuid.uuid4, unique=True)
user = models.ForeignKey(User, on_delete=models.SET_NULL, related_name='articles', null=True)
categories = models.ManyToManyField(ArticleCategory, blank=True)
title = models.CharField(max_length=500, null=True, blank=True)
body = RichTextUploadingField(config_name='portal_lobar_config')
image = models.ImageField(upload_to='article_images/', null=True, blank=True)
headline = models.BooleanField(default=True)
tags = models.ManyToManyField(ArticleTag, blank=True)
slug = AutoSlugField(max_length=500, populate_from='title', unique_with='created__month', null=True)
published = models.BooleanField(default=False)
published_at = models.DateTimeField(null=True, blank=True)
def __str__(self):
return self.title
class Meta:
ordering = ['-created']
Here is the model
class MyModel(models.Model):
id = models.CharField(max_length=10, primary_key=True)
password = models.CharField(max_length=25)
area = models.CharField(max_length=100, primary_key=True)
def __unicode__(self):
return "%s from %s" % (self.id, self.area)
class Meta:
unique_together = (("id", "area"),)
I am trying to generate a unique key using Django's built-in Id functionality without making Id as a primary key.
Possible?
I do not think you can have a primary key based on multiple column (cf. django doc : https://code.djangoproject.com/wiki/MultipleColumnPrimaryKeys).
Only unique_together will still work.
In case what you want is an auto incremented field which is not a primary key :
AutoField¶
class AutoField(**options)¶ An IntegerField that automatically
increments according to available IDs. You usually won’t need to use
this directly; a primary key field will automatically be added to your
model if you don’t specify otherwise. See Automatic primary key
fields.