Django:使用OneToOneField的两个模型与单个模型

时间:2015-12-25 13:54:15

标签: django database-design django-models

让我们想象一下,我有一个简单的模型食谱:

class Recipe(models.Model):
    name = models.CharField(max_length=constants.NAME_MAX_LENGTH)
    preparation_time = models.DurationField()
    thumbnail = models.ImageField(default=constants.RECIPE_DEFAULT_THUMBNAIL, upload_to=constants.RECIPE_CUSTOM_THUMBNAIL_LOCATION)
    ingredients = models.TextField()
    description = models.TextField()

我想创建一个列出所有可用配方的视图,其中只使用name,thumbnail,prepare_time和前100个描述字符。此外,我将有一个专门的视图来呈现单个食谱的所有剩余细节。

从效率的角度来看,由于描述可能是一个长文本,将额外信息存储在一个单独的模型中是否有意义,让我们说'RecipeDetails'不会在列表视图中提取但只在一个模型中提取详细视图(可能使用prefetch_related方法)?我正在考虑一些事情:

class Recipe(models.Model):
    name = models.CharField(max_length=constants.NAME_MAX_LENGTH)
    preparation_time = models.DurationField()
    thumbnail = models.ImageField(default=constants.DEFAULT_THUMBNAIL, upload_to=constants.CUSTOM_THUMBNAIL_LOCATION)
    description_preview = models.CharField(max_length=100)

class RecipeDetails(models.Model):
    recipe = models.OneToOneField(Recipe, related_name="details", primary_key=True)        
    ingredients = models.TextField()
    description = models.TextField()

在我最近的在线搜索中,人们似乎建议OneToOneField应仅用于两个目的:1。继承和2.扩展现有模型。在其他情况下,两个模型应合并为一个。这可能表明我在这里遗漏了一些东西。这是OneToOneField的合理使用还是只会增加整体设计的复杂性?

3 个答案:

答案 0 :(得分:1)

  

继承

不要这样做,因为只有拥有基类/子类关系时,继承才有用。经典的例子是动物和猫/狗,其中猫/狗都有一些可以提取的基本属性,但是你的RecipeRecipeDetail没有。

  

从效率的角度来看,由于描述可能很长   文本,将额外信息存储在一个单独的文本中是否有意义   模型

在单独的模型中存储额外信息不会提高效率。下划线数据库将创建类似ForeignKey字段和加unique=True的内容,以确保唯一性。就我而言,OneToOneField仅在您的原始模型难以更改时才有用,例如,它来自第三方软件包或其他一些尴尬的情况。否则我仍然会考虑将它们添加到Recipe模型中。在这种情况下,您可以轻松管理模型,同时避免进行一些额外的查询,例如recipe.recipedetail.description,您只需执行recipe.description

答案 1 :(得分:0)

不,分割你的食谱是不合理的。首先,您的模型应该包含作为“食谱”的所有属性(并且没有成分的食谱根本不是食谱)。其次,如果您想提高性能,请使用Django's Cache Framework(它是为改善性能问题而创建的)。第三,保持简单,不要过度设计开发周期。你现在真的需要提高性能吗?

希望它有所帮助!

答案 2 :(得分:0)

开发中的第一个错误是,在第一个版本运行之前,您正在考虑效率。

尝试现在拥有第一个版本,然后运行,之后您可以根据第一个版本的用例更快地考虑。在此之后,您可以检查模型和关系,或模型中的新字段或使用Django Cache for views是否可以完成工作。

您在效率方面的首要考虑是“对数据库进行”规范化“btw”,当完成完整描述的模型中的一次更新时,您需要使用“description-preview”字段启动对模型的一次更新。触发数据库级别?应用程序级别更新的python代码?代码设计中的噩梦...在代码运行之前。