migrate遇到的一个错误
之前在项目中遇到这样一个问题
- 在数据库删除两张表
- 在models中注释掉那两张表对应的类
python manage.py makemigrations
python manage.py migrate
执行上述步骤之后报错了,因为注释掉类,django orm会去数据库帮我们删表,但是此时表已经不存在了。
解决方式如下:python manage.py migrate --fake
加上--fake
的意思是告诉ORM不要去数据库删表,同步一下删除状态,表示已删除数据库表
创建表
在说明下面内容之前,给出一个建议:使用 ManyToManyField
和ForeignKey
应该加上related_name
参数。
考虑相亲情况,简易模型设计如下:
from django.db import models
class User(models.Model):
name = models.CharField(max_length=32)
def __str__(self):
return self.name
class Love(models.Model):
boy = models.ForeignKey(User)
girl = models.ForeignKey(User)
def __str__(self):
return str(self.id)
上述模型建表会报错,因为ForeignKey
不加related_name
参数反向查找用表名_set,在这里是love_set。
这里假设有一个User对象obj, obj.love_set.all() 本质是做以下事情:拿到obj的id,拿到这个id去Love表去匹配,
因为外键管理的是同一张表,所以ORM不知道这里的这个User对象obj的id对应的是girl还是boy设置的外键,加了related_name
参数如下:
from django.db import models
class User(models.Model):
name = models.CharField(max_length=32)
def __str__(self):
return self.name
class Love(models.Model):
boy = models.ForeignKey(User, related_name='g')
girl = models.ForeignKey(User, related_name='b')
def __str__(self):
return str(self.id)
obj.b.all() 做的事就是表示obj的id对应的是girl的外键,这样做了严格区分。
看下面一种情况就不需要加related_name
参数
from django.db import models
class Boy(models.Model):
name = models.CharField(max_length=32)
def __str__(self):
return self.name
class Girl(models.Model):
name = models.CharField(max_length=32)
def __str__(self):
return self.name
class Love(models.Model):
boy = models.ForeignKey(Boy)
girl = models.ForeignKey(Girl)
def __str__(self):
return str(self.id)
拿到一个Boy对象obj,obj.love_set.all() 拿到Boy对象obj.id, 这个id对应boy对应的外键,因为boy外键关联的是Boy类,这个就是
和前面外键对应同一张表的不同。
其实,思考这个问题,应该在脑海里绘制几张表,然后连线。
用上述思维思考,得到的结论是在一张表设置外键关联本身或者设置 ManyToManyField
都不需要加related_name
from django.db import models
# Create your models here.
class UserInfo(models.Model):
name = models.CharField(max_length=32)
class News(models.Model):
title = models.CharField(max_length=32)
class Comment(models.Model):
content = models.CharField(max_length=32)
user_info = models.ForeignKey('UserInfo')
news = models.ForeignKey('News')
parent = models.ForeignKey("self",related_name='o',null=True)
ctime = models.DateTimeField(auto_now_add=True,null=True)
from django.db import models
class User(models.Model):
name = models.CharField(max_length=32)
love = models.ManyToManyField("User")
def __str__(self):
return self.name
尽管如此,为了规范,建议以后还是加上