无法使用 PostgreSQL 在 Django 全文搜索中保存新对象



我关注这篇关于如何将全文功能添加到Django应用程序的文章。我有以下型号:

class CustomUser(AbstractUser):
email = models.EmailField(_('email address'), unique=True)
class Author(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL,on_delete = models.CASCADE)
name = models.CharField(max_length = 250)
alternative_names = ArrayField(models.CharField(max_length = 250),blank=True,null=True)
name_norm = models.CharField(max_length = 250,blank=True,null = True)
slug = models.CharField(max_length = 250,unique = True)
photo = models.ImageField(upload_to = 'imgs/users/%Y/%m/%d',blank = True)
search_vector = SearchVectorField(null=True)
def save(self, *args, **kwargs):
self.search_vector = (SearchVector('name', weight='A') )
super().save(*args, **kwargs)`enter code here`

当我试图用save来保存一个新作者时:

autor = Author(user = utilizador,name = author_name,alternative_names = alternative_names,name_norm = name_norm,slug = slug)
autor.save()

我得到错误:

Traceback (most recent call last):
File "populate_v2.py", line 140, in <module>
autor.save()
File "/home/mwon/NewArquivoOpiniao/webapp/colunadeopiniao/accounts/models.py", line 57, in save
super().save(*args, **kwargs)
File "/home/mwon/NewArquivoOpiniao/env3.8/lib/python3.8/site-packages/django/db/models/base.py", line 748, in save
self.save_base(using=using, force_insert=force_insert,
File "/home/mwon/NewArquivoOpiniao/env3.8/lib/python3.8/site-packages/django/db/models/base.py", line 785, in save_base
updated = self._save_table(
File "/home/mwon/NewArquivoOpiniao/env3.8/lib/python3.8/site-packages/django/db/models/base.py", line 890, in _save_table
results = self._do_insert(cls._base_manager, using, fields, returning_fields, raw)
File "/home/mwon/NewArquivoOpiniao/env3.8/lib/python3.8/site-packages/django/db/models/base.py", line 927, in _do_insert
return manager._insert(
File "/home/mwon/NewArquivoOpiniao/env3.8/lib/python3.8/site-packages/django/db/models/manager.py", line 82, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/home/mwon/NewArquivoOpiniao/env3.8/lib/python3.8/site-packages/django/db/models/query.py", line 1204, in _insert
return query.get_compiler(using=using).execute_sql(returning_fields)
File "/home/mwon/NewArquivoOpiniao/env3.8/lib/python3.8/site-packages/django/db/models/sql/compiler.py", line 1393, in execute_sql
for sql, params in self.as_sql():
File "/home/mwon/NewArquivoOpiniao/env3.8/lib/python3.8/site-packages/django/db/models/sql/compiler.py", line 1336, in as_sql
value_rows = [
File "/home/mwon/NewArquivoOpiniao/env3.8/lib/python3.8/site-packages/django/db/models/sql/compiler.py", line 1337, in <listcomp>
[self.prepare_value(field, self.pre_save_val(field, obj)) for field in fields]
File "/home/mwon/NewArquivoOpiniao/env3.8/lib/python3.8/site-packages/django/db/models/sql/compiler.py", line 1337, in <listcomp>
[self.prepare_value(field, self.pre_save_val(field, obj)) for field in fields]
File "/home/mwon/NewArquivoOpiniao/env3.8/lib/python3.8/site-packages/django/db/models/sql/compiler.py", line 1263, in prepare_value
raise ValueError(
ValueError: Failed to insert expression "SearchVector(Col(accounts_author, accounts.Author.name), weight=A)" on accounts.Author.search_vector. F() expressions can only be used to update, not to insert.

Django版本:3.0.11

F((表达式只能用于更新,而不能用于插入。

我不是VectorField方面的专家,但可能是weight='A'导致了F()的表达式。如您参考的教程所示,它在没有weight的情况下工作吗?

否则,请尝试更新:

Author.objects.all().update(search_vector=SearchVector('name', weight='A'))

错误消息表示,在创建Author的新对象时,您正试图在search_vector字段中插入一个值,但SearchVector类只支持更新现有对象,而不支持创建新对象。为了解决这个问题,您可以更改save方法的实现,以便在创建对象后更新search_vector字段:

def save(self, *args, **kwargs):
super().save(*args, **kwargs)
Author.objects.filter(pk=self.pk).update(search_vector=SearchVector('name', weight='A'))

这样,可以先创建对象,然后更新向量。

错误是说F((表达式只能用于更新因此您必须在保存对象后使用它就像在这样的postrongave信号上,你肯定会在对象保存后调用它

from django.db.models.signals import post_save
from django.dispatch import receiver
@receiver(post_save, sender=Product)
def compute_search_vector_signal(sender, instance, **kwargs):
instance.search_vector = (SearchVector('name', weight='A') )

最新更新