Добавление SearchVectorField в модель в Django

Поэтому я пытаюсь добавить SearchVectorField к модели в Django:

class JobPosting(models.Model):
    ...
    ...
    search_vector = SearchVectorField()

Я понимаю, что он должен быть либо nullable, либо иметь значение по умолчанию, чтобы можно было выполнить миграцию, поэтому я удалил все записи в таблице, чтобы предотвратить эту проблему.

Однако при запуске makemigrations я получаю следующую ошибку:

You are trying to add a non-`nullable` field 'search_vector' to jobposting without a default;
we can't do that (the database needs something to populate existing rows).
Please select a fix:
   1) Provide a one-off default now
      (will be set on all existing rows with a null value for this column)
   2) Quit, and let me add a default in models.py
Select an option:

Почему он говорит это, если стол пуст? Я не хочу делать столбец обнуляемым, и я бы предпочел не иметь значения по умолчанию, если я могу этого избежать.

Мой вопрос в том, есть ли способ принудительно makemigrations и migrate, так как я не понимаю проблемы, если таблица пуста. У меня есть другие таблицы с данными, которые я не хочу удалять, поэтому не могу удалить всю информацию в базе данных.

В качестве альтернативы, если вариант 1) является решением, как мне отформатировать значение по умолчанию для этого типа поля? Я предполагаю, что это не обычное текстовое поле?

Спасибо за любую помощь.


person BWrites    schedule 06.04.2017    source источник


Ответы (2)


Я не совсем уверен, почему вы не хотите иметь значение по умолчанию, но я буду считать это заданным.

Мой вопрос в том, есть ли способ принудительно выполнить миграцию и миграцию, поскольку я не понимаю проблемы, если таблица пуста.

Ваша текущая таблица базы данных может быть пустой, но предполагается, что миграция может повторяться в других экземплярах базы данных. Поэтому Django не может предположить, что то же самое верно для любой другой базы данных.

Обходной путь может состоять в том, чтобы определить миграцию, которая создает поле как обнуляемое, индексирует все записи, а затем обновляет его, чтобы оно не обнулялось.

# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.contrib.postgres.search import SearchVector, SearchVectorField      
from django.db import migrations


def index_entries(apps, schema_editor):
    Entry = apps.get_model("mymodel", "Entry")
    Entry.objects.update(search_vector=SearchVector('body_text'))


class Migration(migrations.Migration):

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

    operations = [
        migrations.AddField(
            model_name='entry',
            name='search_vector',
            field=SearchVectorField(null=True),
        ),

        migrations.RunPython(index_entries),

        migrations.AlterField(
            model_name='entry',
            name='search_vector',
            field=SearchVectorField(null=False),
        ),
    ]
person Stefan Kögl    schedule 23.06.2017
comment
Отличный ответ на этот вопрос, особенно в случае существующих данных в таблицах, чтобы данные не были потеряны. Этот ответ заслуживает многих +1 - person Farley; 14.12.2020

Я бы просто сделал поле обнуляемым (и, вероятно, нередактируемым, поскольку вы не собираетесь изменять его ни в интерфейсе администратора, ни через формы):

class JobPosting(models.Model):
    ...
    ...
    search_vector = SearchVectorField(null=True, editable=False)

И проблем с миграцией не будет.

Позже вы можете сделать это поле необнуляемым, но нет никакой реальной причины делать это, потому что вы все равно будете обновлять его программно.

person Igor Pomaranskiy    schedule 14.01.2018