django - GORM 的“有很多”关联没有创建外键?
问题描述
按照 GORM 文档 ( http://gorm.io/docs/has_many.html#Has-Many ) 中的示例,我尝试使用一对多关系创建User
和模型:CreditCard
package main
import (
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/sqlite"
"github.com/sirupsen/logrus"
)
type User struct {
gorm.Model
CreditCards []CreditCard
}
type CreditCard struct {
gorm.Model
Number string
UserID uint
}
func main() {
db, err := gorm.Open("sqlite3", "examplegorm.db")
if err != nil {
logrus.Fatalf("open db: %v", err)
}
defer db.Close()
db.LogMode(true)
db.AutoMigrate(&User{})
db.AutoMigrate(&CreditCard{})
}
但是,在生成的记录 SQL 语句中,我看不到类似
CREATE TABLE credit_cards(
...
FOREIGN KEY(user_id) REFERENCES users(id)
)
正如我对 SQLite 文档( https://www.sqlite.org/foreignkeys.html)所期望的那样。我看到的是
> go run gorm_has_many.go
(/Users/kurt/Documents/Scratch/gorm_has_many.go:28)
[2020-01-06 09:05:58] [0.82ms] CREATE TABLE "users" ("id" integer primary key autoincrement,"created_at" datetime,"updated_at" datetime,"deleted_at" datetime )
[0 rows affected or returned ]
(/Users/kurt/Documents/Scratch/gorm_has_many.go:28)
[2020-01-06 09:05:58] [0.55ms] CREATE INDEX idx_users_deleted_at ON "users"(deleted_at)
[0 rows affected or returned ]
(/Users/kurt/Documents/Scratch/gorm_has_many.go:29)
[2020-01-06 09:05:58] [0.52ms] CREATE TABLE "credit_cards" ("id" integer primary key autoincrement,"created_at" datetime,"updated_at" datetime,"deleted_at" datetime,"number" varchar(255),"user_id" integer )
[0 rows affected or returned ]
(/Users/kurt/Documents/Scratch/gorm_has_many.go:29)
[2020-01-06 09:05:58] [0.50ms] CREATE INDEX idx_credit_cards_deleted_at ON "credit_cards"(deleted_at)
[0 rows affected or returned ]
相比之下,在djangoapp
应用程序中的示例 Django 项目中,如果我有以下内容models.py
:
from django.db import models
class User(models.Model):
name = models.CharField(max_length=255)
age = models.PositiveIntegerField()
class CreditCard(models.Model):
number = models.CharField(max_length=255)
user = models.ForeignKey('djangoapp.User', on_delete=models.CASCADE)
我检查了与CreditCard
模型创建相对应的 SQL 语句,我确实看到了一个外键引用:
kurt@Kurts-MacBook-Pro-13 ~/D/S/djangoproject> python manage.py sqlmigrate djangoapp 0002_creditcard
(0.000)
SELECT name, type FROM sqlite_master
WHERE type in ('table', 'view') AND NOT name='sqlite_sequence'
ORDER BY name; args=None
(0.000) SELECT "django_migrations"."id", "django_migrations"."app", "django_migrations"."name", "django_migrations"."applied" FROM "django_migrations"; args=()
(0.000) PRAGMA foreign_keys = OFF; args=None
(0.000) PRAGMA foreign_keys; args=None
(0.000) BEGIN; args=None
CREATE TABLE "djangoapp_creditcard" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "number" varchar(255) NOT NULL, "user_id" integer NOT NULL REFERENCES "djangoapp_user" ("id") DEFERRABLE INITIALLY DEFERRED); (params None)
(0.000) PRAGMA foreign_key_check; args=None
CREATE INDEX "djangoapp_creditcard_user_id_eca64c45" ON "djangoapp_creditcard" ("user_id"); (params ())
(0.000) PRAGMA foreign_keys = ON; args=None
BEGIN;
--
-- Create model CreditCard
--
CREATE TABLE "djangoapp_creditcard" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "number" varchar(255) NOT NULL, "user_id" integer NOT NULL REFERENCES "djangoapp_user" ("id") DEFERRABLE INITIALLY DEFERRED);
CREATE INDEX "djangoapp_creditcard_user_id_eca64c45" ON "djangoapp_creditcard" ("user_id");
COMMIT;
为什么没有使用Django 应用程序中的子句user_id
生成列?REFERENCES
(似乎 GORM 有一个addForeignKey()
方法(https://github.com/jinzhu/gorm/blob/79a77d771dee4e4b60e9c543e8663bbc80466670/scope.go#L1229-L1238)但在这个例子中没有被调用)。
更新
因为看起来 GORM 的AddForeignKey()
方法实际上并没有在 GORM 本身中被调用,所以我添加了以下行:
db.Model(&CreditCard{}).AddForeignKey("user_id", "users(id)", "CASCADE", "CASCADE")
但是,重新运行脚本然后似乎显示语法错误:
(/Users/kurt/Documents/Scratch/gorm_has_many.go:30)
[2020-01-06 09:36:29] near "CONSTRAINT": syntax error
(/Users/kurt/Documents/Scratch/gorm_has_many.go:30)
[2020-01-06 09:36:29] [0.06ms] ALTER TABLE "credit_cards" ADD CONSTRAINT credit_cards_user_id_users_id_foreign FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE ON UPDATE CASCADE;
[0 rows affected or returned ]
解决方案
Gorm 在自动迁移时不会添加外键。你必须手动完成。
SQLite 不支持在创建表后添加约束。这就是您遇到错误的原因。检查此资源:如何将外键添加到现有 SQLite 表?
推荐阅读
- javascript - 在 React 中反映状态变化时避免无限的 useEffect 循环
- regex - 正则表达式替换为空行
- java - RecylerView 项目的 maxWidth 因大量元素而变化
- scala - 如何在 scala for collatz 链中提高 tailrec 函数的执行时间
- javascript - 为什么最后一项计数没有在删除时过滤?
- wordpress - 如何使用 AMP 循环播放一系列视频?
- laravel - Laravel - what does the manual paginations 'option' query parameter do?
- ajax - Ajax Call with URL
- data-visualization - How to exclude weekend (Sunday only) to DATEDIFF in Tableau?
- asp.net-core - ASP.NET Core IIS return DefaultAppPool instead of window user name