chronox
chronox

Reputation: 117

Converting UUIDField to CharField

This is currently what I have in my models.py:

class Campaign(models.Model):
    campaign_id = UUIDField(auto=True)
    name = models.CharField("Campaign Name", max_length=255)

class CampaignResponse(models.Model):
    campaign = models.ForeignKey(Campaign)
    user = models.EmailField("Email", max_length=200)
    response = models.TextField()

Recently I was thinking of changing the campaign_id in the Campaign model from UUIDField to CharField instead, but when I tried to do so, I noticed the data for campaign_id is being altered (e.g. the data was "7182c679f72844ca83c9648a120bb066" when UUIDField is being used, but it now becomes "7182c679-f728-44ca-83c9-648a120bb066" after converting it to CharField).

Is there some steps I have to follow where I can convert that UUIDField to CharField without changing the data and ensure the relationship between Campaign and CampaignResponse is not broken?

Upvotes: 1

Views: 1397

Answers (2)

Vaibhav Vishal
Vaibhav Vishal

Reputation: 7118

campaign_id is not the primary key for model Campaign. But probably it's for the best because now your relations can't break when you convert UUID to CharField.

First make campaign_id CharField

campaign_id = models.CharField(max_length=36, ) # add other stuff too which you want like unique etc.

About converting from uuid to str, open shell py manage.py shell and run this:

from myApp.models import Campaign
for c in Campaign.objects.all():
    c.campaign_id = str(c.campaign_id).replace('-', '')

Check your database to make sure it worked. Now you can decrease the max_length of CharField to 32 since all the extra dash (-) from campaign_id are gone.

Just because a Field is UUID doesn't means it's the primary key. To make a field primary key you need to pass primary_key=True. You can make primary key like this

id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)

Upvotes: 2

Dougyfresh
Dougyfresh

Reputation: 616

The two commenters are correct, the UUID is not your primary key here. Any foreign keys relating to your campaign are holding the primary key (PK), which is just an auto-incrementing integer here.

Unfortunately it can sometimes be a pain to change primary keys for exactly the reason you're worried about. I've gone through this before, here's what I suggest:

Leave your primary keys as they are. It will ensure that you won't have any problems with relations. If you want a UUID field to be able to look up objects or pass around the reference without the potential issues caused by integer PKs. An example of such an issue would be if you're using a REST API, it would look weird if someone saw this link: GET /campaigns/6 <-- because they would know to just try GET /campaigns/7 and maybe they'd see something they weren't meant to see.

clearly GET /campaigns/7182c679-f728-44ca-83c9-648a120bb066 is better.

You can add unique=True to your UUID field to ensure django creates an index for it, then the performance wouldn't differ.

Does this answer you question?

Upvotes: 2

Related Questions