使用Django进行多对多数据库设计

时间:2016-07-27 17:06:33

标签: python django database database-design

单一药物通常会有很多“昵称”,这会让人感到困惑。所以,我正在尝试构建一个小型Django应用程序来帮助我解决这个问题。

它应该做的是将药物实际名称(non_proprietary_name)引用到其“昵称”(proprietary_name),反之亦然。

例如,“Aspirin”和“ASS”是“乙酰水杨酸”的专有名称。

为了进一步复杂化,我决定添加一个小的Wiki页面和类别(同样,一种药物可以分为许多不同的类别)。

可悲的是,我对数据库设计不是很熟悉,所以我需要一些帮助。

到目前为止我得到了什么:

from django.db import models

# Create your models here.

class Proprietary_name(models.Model):
    proprietary_name = models.CharField(max_length = 100, unique = True) #nick name

    def __str__(self):
        return self.proprietary_name

class Category(models.Model):
    category = models.CharField(max_length = 100, unique = True)

    def __str__(self):
        return self.category

class Mediwiki(models.Model):
    proprietary_name = models.ManyToManyField(Proprietary_name)
    non_proprietary_name = models.CharField(max_length = 100, unique = True) # actual name
    category = models.ManyToManyField(Category)
    wiki_page = models.TextField()

    def __str__(self):
        return self.non_proprietary_name

~

所以,如果我有priv_name,我可以与non_proprietary_name:

相关
>>> Mediwiki.objects.get(proprietary_name__proprietary_name='Aspirin')
<Mediwiki: acetylsalicylic acid>

但是,当我输入专有的名称时,我无法获得所有非专有名称。这是我的数据库的问题还是我错过了其他的东西?

编辑:

基于评论的新models.py:

from django.db import models

# Create your models here.

class Category(models.Model):
    category = models.CharField(max_length = 100, unique = True)

    def __str__(self):
        return self.category

class Mediwiki(models.Model):
    non_proprietary_name = models.CharField(max_length = 100, unique = True)
    category = models.ManyToManyField(Category)
    wiki_page = models.TextField()

    def __str__(self):
        return self.non_proprietary_name

class ProprietaryName(models.Model):
    proprietary_name = models.CharField(max_length = 100, unique = True)
    non_proprietary_name = models.ForeignKey(Mediwiki)

    def __str__(self):
        return self.proprietary_name

所以,它有效!但我不太清楚为什么......这是最好的方法吗?那么,那些类别呢?他们应该改变外国钥匙吗?

>>> Mediwiki.objects.get(proprietaryname__proprietary_name="Aspirin")
<Mediwiki: acetylsalicylic acid>
>>>

>>> ProprietaryName.objects.get(proprietary_name="Aspirin").non_proprietary_name
<Mediwiki: acetylsalicylic acid> # Works also, what's preferable? 

>>>ProprietaryName.objects.filter(non_proprietary_name__non_proprietary_name="acetylsalicylic acid")
        [<ProprietaryName: Aspirin>, <ProprietaryName: ASS>]
        >>>

2 个答案:

答案 0 :(得分:1)

首先,您的模型名称Mediwiki并不简单,因为每个条目只记录有关Drug的所有信息。所以只需将其更改为Drug就会更有意义。

在您当前的设计中,您使用的是m2m字段,表示可以在多种药物上使用一个proprietary_name。如果您希望在输入Drug时返回所有proprietary_name个非专有名称,请执行以下操作:

Drug.objects.filter(proprietary_name__proprietary_name='Aspirin') \
            .values_list('non_proprietary_name', flat=True).distinct()

检查django doc values_list

但是,如果一个proprietary_name只能描述一种药物,那么您应该将Drug作为模型Proprietary_name上的外键来表示一对多的关系:

class Proprietary_name(models.Model):
    proprietary_name = models.CharField(max_length=100, unique=True)
    drug = models.ForeignKey(Drug)

答案 1 :(得分:1)

可以有许多专有名称,但不能将相同的专有名称分配给多种非专有(通用)药物,因此您需要将您的关系从多对多更改为一对多( nb。在类名中使用CamelCase,而不是下划线):

class Mediwiki(models.Model):
    non_proprietary_name = models.CharField(max_length = 100, unique = True) # actual name
    category = models.ManyToManyField(Category)
    wiki_page = models.TextField()

class ProprietaryName(models.Model):
    proprietary_name = models.CharField(max_length = 100, unique = True) #nick name
    non_proprietary_name = models.ForeignKey(Mediawiki)

然后,您可以使用Mediawiki的{​​{1}}属性获取非专有名称的所有专利药物,并使用proprietaryname_set的{​​{1}}属性获取其他查找。有关详情,请参阅documentation