python - Django ForeignKey 接受两种模型
问题描述
我正在使用 Django 进行这个大项目,我必须更新数据库。我必须添加另一个表,稍后将替换另一个表。
所以我想在一个模型中添加一个可能有一个字段,在那里我可以拥有旧模型或新模型。
这是旧模型的代码:
class Harvests(models.Model):
ident_culture = models.IntegerField(primary_key=True)
intitule_culture = models.CharField(max_length=50, blank=True)
nom_fertiweb = models.CharField(max_length=50, blank=True, null = True)
affichage_quintaux_tonne = models.CharField(max_length=1,
choices=RENDEMENT_CHOICES, default = 'T')
type_culture = models.ForeignKey("TypeCulture", null=True)
slug = models.SlugField(null=True, blank=True)
image = models.ImageField(upload_to = 'images_doc_culture/',
null=True, blank = True)
affichage = models.BooleanField(default = True)
class Meta:
verbose_name = "Liste - Culture"
verbose_name_plural = "Liste - Cultures"
ordering = ['intitule_culture']
def __str__(self):
return self.intitule_culture
def label(self):
return self.intitule_culture or ''
@classmethod
def get_choices(cls):
choices = [('', corp.EMPTY_CHOICE_LBL)]
c_category_lbl, c_category = '', []
for item in cls.objects.all():
choices.append((item.pk, item.intitule_culture))
return choices
还有我创建的新代码:
class Crops(models.Model):
intitule_culture = models.CharField(max_length=75, blank=True)
affichage_quintaux_tonne = models.CharField(max_length=2,
choices=RENDEMENT_CHOICES, default = 'T')
type_culture = models.ForeignKey("TypeCulture", null=True)
ident_culture = models.IntegerField(primary_key=True)
affichage = models.BooleanField(default = True)
id_marle = models.IntegerField(null=True)
class Meta:
verbose_name = "Liste - Culture 2019"
verbose_name_plural = "Liste - Cultures 2019"
ordering = ['intitule_culture']
def __str__(self):
return self.intitule_culture
def label(self):
return self.intitule_culture or ''
@classmethod
def get_choices(cls):
choices = [('', corp.EMPTY_CHOICE_LBL)]
c_category_lbl, c_category = '', []
for item in cls.objects.all():
choices.append((item.pk, item.intitule_culture))
return choices
我想culture
在这个模型中接受这两个模型:
class CompanyHarvest(models.Model):
company = models.ForeignKey('corp.Company', verbose_name='Exploitation',
related_name ='cultures')
culture = models.ForeignKey(Harvests, verbose_name ='Culture')
precision = models.CharField(max_length=255, blank=True)
saison_culture = models.CharField(max_length=1, choices=SAISON_CHOICES,
default = 'P')
class Meta:
verbose_name = "Expl. - Culture"
verbose_name_plural = "Expl. - Cultures"
unique_together = ('company', 'culture', 'precision', 'saison_culture')
def __str__(self):
return str(self.culture) + ' ' + self.precision + \
' ' + str(self.get_saison_culture_display() )
@property
def slug(self):
return "_".join([slugify(str(self.culture or '')),
slugify(str(self.precision or ''))]
)
我是 Django 新手,有人可以帮我吗?(^-^)
解决方案
这是不可能的——至少不是这样。这不是 Django 的限制,而是 SQL 的限制,外键不能引用一个表或另一个表。
这里一个可能且简单明显的解决方案是在 CompanyHarvest 中有两个外键 - 一个用于旧模型和新模型中的每个 - 每个都带有blank=True
et default=None
,但它很快就会弄乱所有客户端代码(所有代码都使用CompanyHarvest
)。
更好的解决方案是要么只保留现有模型(向其中添加任何新字段/功能并最终隐藏过时的),要么将所有旧模型记录迁移到新模型(这可以与天真的“两个外键”结合使用)解决方案,以便您可以在必要时将旧表和记录保留为档案)。
另外 - 完全不相关,但是 -,这个:
@classmethod
def get_choices(cls):
choices = [('', corp.EMPTY_CHOICE_LBL)]
c_category_lbl, c_category = '', []
for item in cls.objects.all():
choices.append((item.pk, item.intitule_culture))
return choices
1/ 应该在管理器上定义(参见https://docs.djangoproject.com/en/2.1/topics/db/managers/#adding-extra-manager-methods)
2/ 应该使用.values()
queryset 编写(这将节省 db 查询和构建完整的实例,没有充分的理由):
for item in cls.objects.values("pk", "intitule_culture"):
choices.append(item)
3/ 并且很可能(我必须看看它是如何使用的)ModelChoiceField
在调用代码中被替换为 a 。
哦,是的:如果您允许文本字段使用空格,您很可能希望将空字符串强制为默认值,因此NULL
当没有给出值时,您不会出现两种可能(且不兼容)的情况(sql 和空字符串)。
推荐阅读
- php - 对 PDO 的正常查询
- javascript - 我需要帮助为我的 Beg 命令添加每个用户的冷却时间
- python - 创建一个新帐户并登录到一个帐户
- c++ - Code::Blocks 20.03 + MinGW 错误?“入口点无法位于动态链接库中”,但目标是 exe 控制台应用程序
- autodesk-forge - 使用 BIM 360 Forge API 检索项目并使用按名称过滤
- c# - 将 C# 或 vb.net 中的 PDF 文档发送到 whatsapp?
- google-chrome - 在 Google Chrome 和 Microsoft Edge 上下载动态生成的 PDF 的问题
- javascript - 使用 CSS 在 Mobile Chrome Android 中设置打印纸张大小(即更改纸张大小)
- c# - 在 NpgSQL 中打开多个 conn 是否可行?
- javascript - 输入范围实例变量返回初始值而不是修改