PostgreSQL 字段中的 Django ProgrammingError
Django ProgrammingError in Fields on PostgreSQL
models.py
class Stop(models.Model):
idn = models.PositiveIntegerField(primary_key=True, unique=True)
label = models.CharField(null=False, blank=False, max_length=512)
coor_x = models.FloatField()
coor_y = models.FloatField()
buses = models.ManyToManyField(Bus)
latest_query_datetime = models.DateTimeField(default=datetime(2000, 1, 1, 0, 0, 0))
latest_query_data = JSONField(default={})
class Meta:
ordering = ["label"]
def __str__(self):
return self.label
当我运行:
python3 manage.py makemigrations && python3 manage.py migrate
它引发了一个 ProgrammingError
说 jsonb 数据类型不存在:
Migrations for 'rest':
0007_auto_20160612_1301.py:
- Alter field latest_query_data on stop
Operations to perform:
Apply all migrations: contenttypes, rest, auth, sessions, admin
Running migrations:
Rendering model states... DONE
Applying rest.0005_auto_20160612_1237...Traceback (most recent call last):
File "/home/erayerdin/.venv/eshot-api/lib/python3.5/site-packages/django/db/backends/utils.py", line 64, in execute
return self.cursor.execute(sql, params)
psycopg2.ProgrammingError: type "jsonb" does not exist
LINE 1: ... TABLE "rest_stop" ADD COLUMN "latest_query_data" jsonb DEFA...
^
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "manage.py", line 10, in <module>
execute_from_command_line(sys.argv)
File "/home/erayerdin/.venv/eshot-api/lib/python3.5/site-packages/django/core/management/__init__.py", line 353, in execute_from_command_line
utility.execute()
File "/home/erayerdin/.venv/eshot-api/lib/python3.5/site-packages/django/core/management/__init__.py", line 345, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/home/erayerdin/.venv/eshot-api/lib/python3.5/site-packages/django/core/management/base.py", line 348, in run_from_argv
self.execute(*args, **cmd_options)
File "/home/erayerdin/.venv/eshot-api/lib/python3.5/site-packages/django/core/management/base.py", line 399, in execute
output = self.handle(*args, **options)
File "/home/erayerdin/.venv/eshot-api/lib/python3.5/site-packages/django/core/management/commands/migrate.py", line 200, in handle
executor.migrate(targets, plan, fake=fake, fake_initial=fake_initial)
File "/home/erayerdin/.venv/eshot-api/lib/python3.5/site-packages/django/db/migrations/executor.py", line 92, in migrate
self._migrate_all_forwards(plan, full_plan, fake=fake, fake_initial=fake_initial)
File "/home/erayerdin/.venv/eshot-api/lib/python3.5/site-packages/django/db/migrations/executor.py", line 121, in _migrate_all_forwards
state = self.apply_migration(state, migration, fake=fake, fake_initial=fake_initial)
File "/home/erayerdin/.venv/eshot-api/lib/python3.5/site-packages/django/db/migrations/executor.py", line 198, in apply_migration
state = migration.apply(state, schema_editor)
File "/home/erayerdin/.venv/eshot-api/lib/python3.5/site-packages/django/db/migrations/migration.py", line 123, in apply
operation.database_forwards(self.app_label, schema_editor, old_state, project_state)
File "/home/erayerdin/.venv/eshot-api/lib/python3.5/site-packages/django/db/migrations/operations/fields.py", line 62, in database_forwards
field,
File "/home/erayerdin/.venv/eshot-api/lib/python3.5/site-packages/django/db/backends/base/schema.py", line 396, in add_field
self.execute(sql, params)
File "/home/erayerdin/.venv/eshot-api/lib/python3.5/site-packages/django/db/backends/base/schema.py", line 110, in execute
cursor.execute(sql, params)
File "/home/erayerdin/.venv/eshot-api/lib/python3.5/site-packages/django/db/backends/utils.py", line 79, in execute
return super(CursorDebugWrapper, self).execute(sql, params)
File "/home/erayerdin/.venv/eshot-api/lib/python3.5/site-packages/django/db/backends/utils.py", line 64, in execute
return self.cursor.execute(sql, params)
File "/home/erayerdin/.venv/eshot-api/lib/python3.5/site-packages/django/db/utils.py", line 95, in __exit__
six.reraise(dj_exc_type, dj_exc_value, traceback)
File "/home/erayerdin/.venv/eshot-api/lib/python3.5/site-packages/django/utils/six.py", line 685, in reraise
raise value.with_traceback(tb)
File "/home/erayerdin/.venv/eshot-api/lib/python3.5/site-packages/django/db/backends/utils.py", line 64, in execute
return self.cursor.execute(sql, params)
django.db.utils.ProgrammingError: type "jsonb" does not exist
LINE 1: ... TABLE "rest_stop" ADD COLUMN "latest_query_data" jsonb DEFA...
我使用 PostgreSQL 来使用 JSONField 并在用户请求视图时更新它。如果我不使用 default={}
,它会告诉我制作一个。
进一步分析
我将 latest_query_data
字段更改为 TextField
以便我可以存储为字符串并在需要时转换为 dict
。但是,这也引发了同样的错误。
环境
- django 1.9.6
- 心理战 2.6.1
所以,这似乎是 psycopg2 或 django 上的一个错误,我将 post 两个存储库上的一个问题。这就是我解决(至少 ProgrammingError
)问题的方法。
将 JSONField
更改为 TextField
。
刷新你的数据库。
Beware! This operation will erase all the data but the structure in your database.
删除所有应用程序中的所有 migrations
文件夹。
运行 python3 manage.py makemigrations && python3 manage.py migrate
在您的所有应用中。
运行 python manage.py makemigrations <appname> && python3 manage.py migrate <appname>
对于您拥有的每个应用程序。
使用内置的json
模块在str
和dict
之间进行转换。
但是,请记住,如果您想过滤 QuerySet
模型,此解决方案需要付出很大的努力。我不推荐它,但没有其他解决方案可以消除这个错误,我需要做的就是保存数据并表示它。
! This answer will be accepted as default if there will not occur any other better solution in 48 hours.
根据 Django 文档,JSONField 要求 PostgreSQL ≥ 9.4 和 Psycopg2 ≥ 2.5.4
您使用的是哪个 PostgreSQL 版本?
Ubuntu 14.04 存储库仅包含 9.3 版本。您可以查看 this 来升级您的版本。
根据匿名评论,我发现以下方法有效:
from django.contrib.postgres import fields
class OldJSONField(fields.JSONField):
def db_type(self, connection):
return 'json'
class Stop(models.Model):
...
latest_query_data = OldJSONField(default=dict)
...
如果您收到此错误并且您安装了 Postgres > 9.4,那么我会检查您是否没有连接到您的实例上也安装的旧版本的 Postgres。
要确认您从 Django 连接到什么,您可以使用 shell:
中的 psycopg2
import psycopg2
conn = psycopg2.connect("dbname=<your database> user=<your user> password=<your password>")
cur = conn.cursor()
cur.execute("SELECT Version();")
cur.fetchone()
确保这里的版本> 9.4。如果不是,您可能安装了几个版本并且您的服务配置指向另一个版本。
对于旧版本的 PostgreSQL,例如“PostgreSQL9.2.x”,
我们可以使用替代方法
from jsonfield import JSONField
而不是:
from django.contrib.postgres.fields import JSONField
例如:
from django.db import models
from jsonfield import JSONField
class MyModel(models.Model):
json = JSONField()
可以安装为:
pip install jsonfield
看看这个:
Add support for PostgreSQL 9.2+'s native json type. #32
此解决方案特别适用于某些限量版。例如,
在默认支持 postgresql9.2 的 VPS 和 Cpanel 上
更多详情!,see"rpkilby-jsonfield"
models.py
class Stop(models.Model):
idn = models.PositiveIntegerField(primary_key=True, unique=True)
label = models.CharField(null=False, blank=False, max_length=512)
coor_x = models.FloatField()
coor_y = models.FloatField()
buses = models.ManyToManyField(Bus)
latest_query_datetime = models.DateTimeField(default=datetime(2000, 1, 1, 0, 0, 0))
latest_query_data = JSONField(default={})
class Meta:
ordering = ["label"]
def __str__(self):
return self.label
当我运行:
python3 manage.py makemigrations && python3 manage.py migrate
它引发了一个 ProgrammingError
说 jsonb 数据类型不存在:
Migrations for 'rest':
0007_auto_20160612_1301.py:
- Alter field latest_query_data on stop
Operations to perform:
Apply all migrations: contenttypes, rest, auth, sessions, admin
Running migrations:
Rendering model states... DONE
Applying rest.0005_auto_20160612_1237...Traceback (most recent call last):
File "/home/erayerdin/.venv/eshot-api/lib/python3.5/site-packages/django/db/backends/utils.py", line 64, in execute
return self.cursor.execute(sql, params)
psycopg2.ProgrammingError: type "jsonb" does not exist
LINE 1: ... TABLE "rest_stop" ADD COLUMN "latest_query_data" jsonb DEFA...
^
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "manage.py", line 10, in <module>
execute_from_command_line(sys.argv)
File "/home/erayerdin/.venv/eshot-api/lib/python3.5/site-packages/django/core/management/__init__.py", line 353, in execute_from_command_line
utility.execute()
File "/home/erayerdin/.venv/eshot-api/lib/python3.5/site-packages/django/core/management/__init__.py", line 345, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/home/erayerdin/.venv/eshot-api/lib/python3.5/site-packages/django/core/management/base.py", line 348, in run_from_argv
self.execute(*args, **cmd_options)
File "/home/erayerdin/.venv/eshot-api/lib/python3.5/site-packages/django/core/management/base.py", line 399, in execute
output = self.handle(*args, **options)
File "/home/erayerdin/.venv/eshot-api/lib/python3.5/site-packages/django/core/management/commands/migrate.py", line 200, in handle
executor.migrate(targets, plan, fake=fake, fake_initial=fake_initial)
File "/home/erayerdin/.venv/eshot-api/lib/python3.5/site-packages/django/db/migrations/executor.py", line 92, in migrate
self._migrate_all_forwards(plan, full_plan, fake=fake, fake_initial=fake_initial)
File "/home/erayerdin/.venv/eshot-api/lib/python3.5/site-packages/django/db/migrations/executor.py", line 121, in _migrate_all_forwards
state = self.apply_migration(state, migration, fake=fake, fake_initial=fake_initial)
File "/home/erayerdin/.venv/eshot-api/lib/python3.5/site-packages/django/db/migrations/executor.py", line 198, in apply_migration
state = migration.apply(state, schema_editor)
File "/home/erayerdin/.venv/eshot-api/lib/python3.5/site-packages/django/db/migrations/migration.py", line 123, in apply
operation.database_forwards(self.app_label, schema_editor, old_state, project_state)
File "/home/erayerdin/.venv/eshot-api/lib/python3.5/site-packages/django/db/migrations/operations/fields.py", line 62, in database_forwards
field,
File "/home/erayerdin/.venv/eshot-api/lib/python3.5/site-packages/django/db/backends/base/schema.py", line 396, in add_field
self.execute(sql, params)
File "/home/erayerdin/.venv/eshot-api/lib/python3.5/site-packages/django/db/backends/base/schema.py", line 110, in execute
cursor.execute(sql, params)
File "/home/erayerdin/.venv/eshot-api/lib/python3.5/site-packages/django/db/backends/utils.py", line 79, in execute
return super(CursorDebugWrapper, self).execute(sql, params)
File "/home/erayerdin/.venv/eshot-api/lib/python3.5/site-packages/django/db/backends/utils.py", line 64, in execute
return self.cursor.execute(sql, params)
File "/home/erayerdin/.venv/eshot-api/lib/python3.5/site-packages/django/db/utils.py", line 95, in __exit__
six.reraise(dj_exc_type, dj_exc_value, traceback)
File "/home/erayerdin/.venv/eshot-api/lib/python3.5/site-packages/django/utils/six.py", line 685, in reraise
raise value.with_traceback(tb)
File "/home/erayerdin/.venv/eshot-api/lib/python3.5/site-packages/django/db/backends/utils.py", line 64, in execute
return self.cursor.execute(sql, params)
django.db.utils.ProgrammingError: type "jsonb" does not exist
LINE 1: ... TABLE "rest_stop" ADD COLUMN "latest_query_data" jsonb DEFA...
我使用 PostgreSQL 来使用 JSONField 并在用户请求视图时更新它。如果我不使用 default={}
,它会告诉我制作一个。
进一步分析
我将 latest_query_data
字段更改为 TextField
以便我可以存储为字符串并在需要时转换为 dict
。但是,这也引发了同样的错误。
环境
- django 1.9.6
- 心理战 2.6.1
所以,这似乎是 psycopg2 或 django 上的一个错误,我将 post 两个存储库上的一个问题。这就是我解决(至少 ProgrammingError
)问题的方法。
将
JSONField
更改为TextField
。刷新你的数据库。
Beware! This operation will erase all the data but the structure in your database.
删除所有应用程序中的所有
migrations
文件夹。运行
python3 manage.py makemigrations && python3 manage.py migrate
在您的所有应用中。运行
python manage.py makemigrations <appname> && python3 manage.py migrate <appname>
对于您拥有的每个应用程序。使用内置的
json
模块在str
和dict
之间进行转换。
但是,请记住,如果您想过滤 QuerySet
模型,此解决方案需要付出很大的努力。我不推荐它,但没有其他解决方案可以消除这个错误,我需要做的就是保存数据并表示它。
! This answer will be accepted as default if there will not occur any other better solution in 48 hours.
根据 Django 文档,JSONField 要求 PostgreSQL ≥ 9.4 和 Psycopg2 ≥ 2.5.4
您使用的是哪个 PostgreSQL 版本?
Ubuntu 14.04 存储库仅包含 9.3 版本。您可以查看 this 来升级您的版本。
根据匿名评论,我发现以下方法有效:
from django.contrib.postgres import fields
class OldJSONField(fields.JSONField):
def db_type(self, connection):
return 'json'
class Stop(models.Model):
...
latest_query_data = OldJSONField(default=dict)
...
如果您收到此错误并且您安装了 Postgres > 9.4,那么我会检查您是否没有连接到您的实例上也安装的旧版本的 Postgres。
要确认您从 Django 连接到什么,您可以使用 shell:
中的 psycopg2import psycopg2
conn = psycopg2.connect("dbname=<your database> user=<your user> password=<your password>")
cur = conn.cursor()
cur.execute("SELECT Version();")
cur.fetchone()
确保这里的版本> 9.4。如果不是,您可能安装了几个版本并且您的服务配置指向另一个版本。
对于旧版本的 PostgreSQL,例如“PostgreSQL9.2.x”,
我们可以使用替代方法
from jsonfield import JSONField
而不是:
from django.contrib.postgres.fields import JSONField
例如:
from django.db import models
from jsonfield import JSONField
class MyModel(models.Model):
json = JSONField()
可以安装为:
pip install jsonfield
看看这个: Add support for PostgreSQL 9.2+'s native json type. #32
此解决方案特别适用于某些限量版。例如, 在默认支持 postgresql9.2 的 VPS 和 Cpanel 上
更多详情!,see"rpkilby-jsonfield"