用Django自带MySQL ORM操作外键前的正确修改方式

在给网站数据库优化的过程中,需要给几张表增加外键限制,方便管理员界面的联表操作。

调研发现,网上提供的几种models的配置都不能让我的插入程序成功运行,在经过尝试之后总结出了一个终极解决方案。

我的环境:Django==2.1.7,Python==3.6.1

我建表一般先过Navicat这种可视化软件来生成mysql数据库,所以我们直接在建表之后使用下面语句直接生成。

python manage.py inspectdb > app/models.py
// 'app' 是我项目名称

生成的models.py部分代码:

class InfoUpload(models.Model):
    # 子表
    upload_id = models.AutoField(primary_key=True)
    contact_email = models.ForeignKey('InfoUser', model.DO_NOTHING, db_column='contact_email')

    class Meta:
        managed = False
        db_table = 'info_upload'


class InfoUser(models.Model):
     # 主表
    user_id = models.AutoField(primary_key=True)
    contact_email = models.CharField(max_length=255)

    class Meta:
        managed = False
        db_table = 'info_user'
        unique_together = (('user_id', 'contact_email'),)

可以看到在子表(有外键的表)中,外键contact_email生成了三个设置字段,'InfoUser'表示参照的表, model.DO_NOTHING是插入时的动作(感觉这个字段是个bug,我们一会要用级联来替代它), db_column='contact_email'表中列名。

在主表中,contact_email只有一个最大长度字段。

在插入之后我们遇到了以下的报错:

// 报错 1
// 说我没有设置级联
django.db.utils.IntegrityError: (1452, 'Cannot add or update a child row: a foreign key constraint fails (`corpusdatabase`.`info_upload`, CONSTRAINT `upload_email` FOREIGN KEY
 (`contact_email`) REFERENCES `info_user` (`contact_email`) ON DELETE CASCADE ON UPDATE CASCADE)')

// 报错 2
// 说我没有设置主键唯一
ERRORS:
pageContent.InfoUpload.contact_email: (fields.E311) 'InfoUser.contact_email' must set unique=True because it is referenced by a foreign key.

推测原因是inspectdb指令生成的models并不是完整状态的,对于我这种懒人并不是很友好,还需要自己再加入一些设置。

不断试错之后得到最终版本如下:

class InfoUpload(models.Model):
    upload_id = models.AutoField(primary_key=True)
    upload_date = models.DateTimeField(blank=True, null=True)
    contact_email = models.ForeignKey('InfoUser', on_delete='CASECADE', db_column='contact_email', to_field='contact_email', related_name="upload_name")
    # models.DO+_NOTHING 改为 on_delete='CASECADE', 设置级联操作
    # 加入 to_field='contact_email',指出参考表中哪一列
    # 加入 related_name="upload_name", 方便之后的联表查询

    class Meta:
        managed = False
        db_table = 'info_upload'


class InfoUser(models.Model):
    user_id = models.AutoField(primary_key=True)
    contact_email = models.CharField(max_length=255, unique=True)
    # 增加字段unique=True,设置这个键的值是唯一的

    class Meta:
        managed = False
        db_table = 'info_user'
        unique_together = (('user_id', 'contact_email'),)

应该就能解决了。

综上,这个故事告诉我们,不能太依赖inspectdb这条语句,对于生成的models还需要进一步的修改。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
DjangoORM是一个Python对象关系映射工具,它可以让开发者使用Python语言进行数据库操作,而不需要手写SQL语句。 使用DjangoORM进行数据库操作的步骤如下: 1. 定义模型类:在Django应用的models.py文件中定义模型类,其中每个模型类对应一个数据库表。 2. 进行迁移:运行python manage.py makemigrations命令生成数据库迁移文件,再运行python manage.py migrate命令将模型类映射到数据库表。 3. 进行CRUD操作:使用模型类提供的方法进行数据库的增删改查操作,如: - 创建对象:使用模型类的save()方法或create()方法创建新的数据库记录。 - 查询对象:使用模型类的objects属性进行查询,可以使用filter()、get()、all()等方法进行过滤和排序。 - 更新对象:使用模型类的save()方法或update()方法更新数据库记录。 - 删除对象:使用模型类的delete()方法删除数据库记录。 示例代码: ```python # 定义模型类 from django.db import models class Book(models.Model): title = models.CharField(max_length=100) author = models.CharField(max_length=50) price = models.DecimalField(max_digits=5, decimal_places=2) pub_date = models.DateField() is_published = models.BooleanField(default=True) # 创建对象 book = Book(title='Python入门', author='张三', price=29.99, pub_date='2022-01-01') book.save() # 查询对象 books = Book.objects.filter(author='张三').order_by('-price') for book in books: print(book.title, book.price) # 更新对象 book.price = 39.99 book.save() # 删除对象 book.delete() ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值