8

I've added GIN index to my db

ALTER TABLE mtn_order
ADD COLUMN textsearchable_index_col tsvector
GENERATED ALWAYS AS (to_tsvector('english', coalesce(descr, '') || ' ' || coalesce(descrrep, ''))) STORED;
CREATE INDEX textsearch_idx ON mtn_order USING GIN (textsearchable_index_col);

and textsearchable_index_col = SearchVectorField(null=True) to my model and now when i'm trying to save new instance i get:

ProgrammingError at /order/create/
cannot insert into column "textsearchable_index_col"
DETAIL:  Column "textsearchable_index_col" is a generated column.

How to stop Django trying to write None to that field

Viktor
  • 325
  • 2
  • 10

2 Answers2

5

You won't be able to add it as a field to your model, because Django will try to write values back to it.

You could annotate it on when you need to:

MyModel.objects.annotate(
    index_col=RawSQL('textsearchable_index_col', 
                     [], 
                     output_field=SearchVectorField()
)
Matthew Schinckel
  • 35,041
  • 6
  • 86
  • 121
  • 1
    For those of you wishing to track generated columns without having to resort to rawsql calls, follow this django project ticket: https://code.djangoproject.com/ticket/30511 – jorf.brunning Jun 11 '21 at 14:36
  • That ticket looks like it’s limited to generated as identity columns? – Matthew Schinckel Jun 12 '21 at 23:27
  • I'd also thought that, but the django community closes tickets and marks them as duplicates for any `GENERATED AS` functionality and points back to the ticket I previously linked. Examples: https://code.djangoproject.com/ticket/31565 and https://code.djangoproject.com/ticket/31300 – jorf.brunning Jun 14 '21 at 17:38
  • I think the suggestion is that the infrastructure and functionality for any GENERATED AS columns would be resolved by #30511. – Matthew Schinckel Jun 16 '21 at 10:26
0

Override the _do_insert and _do_update methods on the model:

class MTNOrder:

    def _do_insert(self, manager, using, fields, update_pk, raw):
        fields = [
            f for f in fields if f.attname not in ['textsearchable_index_col']
        ]
        return super()._do_insert(manager, using, fields, update_pk, raw)

    def _do_update(self, base_qs, using, pk_val, values, update_fields, forced_update):
        values = [
            value for value in values if value[0].attname not in ['textsearchable_index_col']
        ]
        return super()._do_update(base_qs, using, pk_val, values, update_fields, forced_update)

Reference: make django not insert certain fields

kloddant
  • 1,026
  • 12
  • 19