简体   繁体   中英

Django: Add new foreign key to existing model with default value as another foreign key from the same model

I recently started using Django, so please be patient. I have a model with 2 foreign keys

class Application(models.Model): assessment_owner = models.ForeignKey(User, related_name='assessment_owner') creator = models.ForeignKey(User, related_name='creator')

I am trying to add new foreign key called tech_lead to the same model, and default value for tech_lead should be assessment_owner. Later on, I can update the value for tech_lead using data load, but initially it should be assessment owner.

With following code snippet, Django asks for a default value while making migrations and assigns the same tech_lead everywhere. I would like to define default value for tech_lead through code, and simple default attribute doesn't work. I have tried using signals pre_save and post_save with no luck.

class Application(models.Model):
    assessment_owner = models.ForeignKey(User, related_name='assessment_owner')
    creator = models.ForeignKey(User, related_name='creator')
    tech_lead = models.ForeignKey(User, related_name='tech_lead')

I am using Django 1.11.3 and postgreSQL.

Migration was successful with one-off default value.

Error Stack -

Env details

error

error

Thanks in advance.

tech_lead = models.ForeignKey(User, related_name='tech_lead')

breaks integrity because your database is already populated with Application instances. If you want to add a not nullable FK to your scheme, you should specify default value. Otherwise, if you can't provide default value, you should consider allowing tech_lead to be NULL, ie:

tech_lead = models.ForeignKey(User, related_name='tech_lead', null=True)

then using data migration to populate field with values you want:

from django.db import migrations

def populate_tech_lead(apps, schema_editor):
    Application = apps.get_model('yourappname', 'Application')
    for application in Application.objects.all():
        application.tech_lead = application.assessment_owner
        application.save()

class Migration(migrations.Migration):

    dependencies = [
        ('yourappname', '0001_initial'),
    ]

    operations = [
        migrations.RunPython(populate_tech_lead),
    ]

and then removing null=True from the field:

tech_lead = models.ForeignKey(User, related_name='tech_lead')

Step 1. add null=True to the tech_lead field as

class Application(models.Model):
    assessment_owner = models.ForeignKey(User, related_name='assessment_owner')
    creator = models.ForeignKey(User, related_name='creator')
    tech_lead = models.ForeignKey(User, related_name='tech_lead', )

Step 2. create migration file by python manage.py makemigrations

Step 3. migrate the db python manage.py migrate

Step 4. open django shell, python manage.py shell

Step 5. run the following script

from your_app.models import Application
from django.db.models.expressions import F

Application.objects.filter(tech_lead__isnull=True).update(tech_lead=F('assessment_owner'))

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