简体   繁体   中英

default value as callable is only called once during django migration

I've created the following basic django model :

import string
import random

from django.db import models

def create_short_url():
    size = 6
    chars = string.ascii_uppercase + string.digits
    url = ''.join(random.choice(chars) for _ in range(size))
    print("\nSHORT_URL:%s\n" % url)
    return url

class ShortURL(models.Model):
    url = models.CharField(max_length=220, )
    shortcode = models.CharField(max_length=15, unique=True, default=create_short_url)

    def __str__(self):
        return str(self.url)

First I only coded the url field. Then I added the shortcode field and provided a function to be called to create default unique values. Django's documentation says

If callable it will be called every time a new object is created.

Unfortunately, when running the migration, I see only one short url generated and the following exception :

$ python manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, sessions, shortener
Running migrations:
  Applying shortener.0002_auto_20161107_1529...
SHORT_URL:43AY7G

Traceback (most recent call last):
  File "/home/user/django1.10/py3/lib/python3.5/site-packages/django/db/backends/utils.py", line 64, in execute
    return self.cursor.execute(sql, params)
  File "/home/user/django1.10/py3/lib/python3.5/site-packages/django/db/backends/sqlite3/base.py", line 337, in execute
    return Database.Cursor.execute(self, query, params)
sqlite3.IntegrityError: UNIQUE constraint failed: shortener_shorturl.shortcode

What is missing to call that function for each entry being migrated?

Initially, you will need to defer the unique constraint on the shortcode field and permit null values and then re-create and run your migration.(don't forget to remove the migration that fails)

class ShortURL(models.Model):
    url = models.CharField(max_length=220, )
    shortcode = models.CharField(max_length=15, null=True)

    def __str__(self):
        return str(self.url)

After that, 1) create a new empty migration and add a RunPython operation that leverages your create_short_url(). 2)change your model to your original definition and create a new auto migration and run it.

Refer here for more information: Migrations that add unique fields

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM