Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Django模型需要两个相关字段中的每一个:我应该使用oneToOneField吗?_Django_Database Design_Django Models_Django Templates - Fatal编程技术网

Django模型需要两个相关字段中的每一个:我应该使用oneToOneField吗?

Django模型需要两个相关字段中的每一个:我应该使用oneToOneField吗?,django,database-design,django-models,django-templates,Django,Database Design,Django Models,Django Templates,我正在Django写一个科学的网络应用程序,处理抗体Fab片段的氨基酸序列,每个片段正好由一条重链和一条轻链组成。每一条链都由一系列氨基酸残基组成 晶圆厂1 轻链 残基1 残基2 ... 重链 残基1 残基2 ... 晶圆厂2 等 My models.py本质上是这样的: from django.db.models import * class Fab(Model): name = CharField(max_length=30) ... def __unicode__

我正在Django写一个科学的网络应用程序,处理抗体Fab片段的氨基酸序列,每个片段正好由一条重链和一条轻链组成。每一条链都由一系列氨基酸残基组成

晶圆厂1 轻链 残基1 残基2 ... 重链 残基1 残基2 ... 晶圆厂2 等 My models.py本质上是这样的:

from django.db.models import *

class Fab(Model):
    name = CharField(max_length=30)
    ...
    def __unicode__(self):
        return self.name

class Chain(Model):
    fab = ForeignKey(Fab)
    TYPE_CHOICES = (
        ('L', 'light'),
        ('H', 'heavy'),
    )
    type = CharField(max_length=5)
    ...

class Residue(Model):
    ch = ForeignKey(Chain)
    ...
因此,在将一个Fab输入数据库的过程中,我创建了两个链,为每个链分配一个类型和一个Fab外键。然后,为了在模板中使用它们,我使用以下视图,将每个链作为一个对象,并将其传递给模板,而不依赖于其Fab父对象,这并不理想

def fab_detail(request, fab_id):

    f = get_object_or_404(Fab, pk=fab_id)
    h = get_object_or_404(Chain, fab=f, type='H')
    l = get_object_or_404(Chain, fab=f, type='L')

    return render_to_response('antibodies/fab_detail.html', {
        'fab': f,
        'light': l,
        'heavy': h,
    }, context_instance=RequestContext(request))
不过,我想:

有更好的方法引用模板中的轻链或重链,例如,使用{fab.Light_Chain.residence_set.all%}中的r%循环链的剩余部分。 确保每个工厂只有一条轻链和一条重链 我曾考虑过对Chain进行子类化,但不确定如何实现类似的结果。我想到了以下几点:

class Chain(Model):
    # same as before, but without the fab ForeignKey field
    ...

class LightChain(Chain):
    pass

class HeavyChain(Chain):
    pass

class Fab(Model):
    name = CharField(max_length=30)
    light_chain = OneToOneField(LightChain)
    heavy_chain = OneToOneField(HeavyChain)
    ...

class Residue(Model):
    ???
我遇到的主要问题是如何让LightChain和HeavyChain字段包含剩余数据。具体地说,我应该用什么替换剩余类中的ch=ForeignKeyChain


如果您有任何建议或参考,我们将不胜感激。

首先,您可以使用一个元类,使字段在类型和链类型的组合中唯一

class Chain(Model):
    fab = ForeignKey(Fab)
    TYPE_CHOICES = (
        ('L', 'light'),
        ('H', 'heavy'),
    )
    type = CharField(max_length=5, choices=TYPE_CHOICES)

    class Meta:
        unique_together = (
            ('type', 'fab'),
        )
这样,您就不能再添加2个,因为您只有两个选择

class Residue(Model):
    ch = ForeignKey(Chain)

看起来和上面使用的一样好。

凯尼的解决方案就是我要写的

但是,我不认为choices=TYPE_choices约束在任何级别都是强制的,它只是告诉Django在表单和管理中使用选择菜单。所以理论上你可以有type='R','W'或任何类型。顺便说一句,我想你jared的意思是最大长度=1

另一种解决方案是简单地使用多表继承,而不是抽象基类,这是两种不同的继承形式。在这种情况下,您可以简单地使用ch=ForeignKeyChain。但这可能会带来太多的开销:将创建三个表,一个用于链,一个用于轻,一个用于重,后两个表引用第一个表,一个表基本上不包含任何其他内容。如果您需要存储轻链或重链的特定信息,这可能会很有趣

第三种解决方案是:

class Fab(Model):
name = CharField(max_length=30)
light = OneToOneField(Chain, related_name="fab_as_light")
heavy = OneToOneField(Chain, related_name="fab_as_heavy")
通过这种方式,您可以非常轻松地制作fab.light和fab.heavy,并且实现了独特性。我敢肯定,在同一型号上使用两个一通电场是合法的。如果不是,您仍然可以使用外键并将其设置为唯一。 我认为第三个是你的解决方案

为了完整性,您需要:

class Residue(Model):
ch = ForeignKey(Chain)

在尝试了一些不同的东西并且不能使用“my_Chain.fab_as_light/heavy”语法之后,我当前的解决方案是使用@Arthur的解决方案的一个变体,在这个变体中,我在链模型中生成了一对名为“type”和“fab”的属性,根据Fab对象的相关_name值计算。例如,在对链对象执行操作但不关心它是哪种类型的链的函数中,这些将非常有用:my_Chain.fab返回轻链或重链的fab对象

class Chain(Model):

    # determine the type based on Fab related_name
    def _get_type(self):
        try:
            if self.fab_as_light:
                return 'L'
        except:
            try:
                if self.fab_as_heavy:
                    return 'H'
            except:
                return None
    type = property(_get_type)

    # consolidate fab_as_light and fab_as_heavy into one property
    def _get_fab(self):
        try:
            return self.fab_as_light
        except:
            try:
                return self.fab_as_heavy
            except:
                return None
    fab = property(_get_fab)

    def __unicode__(self):
        return "%s_%s" % (self.fab.name, self.type)

class Fab(Model):
    name = CharField(max_length=30)
    light = OneToOneField(Chain, related_name='fab_as_light')
    heavy = OneToOneField(Chain, related_name='fab_as_heavy')
这可能不是最好的路线,也不太优雅!,但它对我有用,所以我现在就用它


感谢大家的支持。

您可能希望做的另一件事是在剩余类中不要使用ch=ForeignKeyChain,而是使用ManyToManyField来链接。我不是在这里回答你的问题,而是分享一个想法。我可能对什么是残基有完全错误的理解,但如果它是一个分子片段,可以在不同的地方找到,比如在不同的晶圆厂,那可能是有道理的。除此之外,它还可以让你回答这样一个问题,即残留物出现在哪个晶圆厂?如果这对这个@Arthur有意义的话。在简单尝试之后,看起来您的第三个解决方案将是一个很好的选择,在我完成所有工作后,我需要做什么。但是,我无法从Chain对象访问“fab”反向关系。e、 g.f=Fab。。。;l=链;f、 光=l;将l.fab_打印为_灯光引发DoesNotExist:fab匹配查询不存在异常。在这个工作流程中,我有什么遗漏吗?而且,自从你在生物学中提出它以来,氨基酸只是构成蛋白质一部分的一个组成部分。如果蛋白质由一列表示,那么每个残基都是一列火车车厢。使一种蛋白质与另一种不同的是这些残基的序列。你可能说我应该在这里有一个ManyToManyField,但我可能会称之为ResidueTypes。这里,我用残数来表示一个ins
“在蛋白质链中某个给定位置的剩余类型的实例。@jared在尝试l.fab_as_light之前,你做过f.save吗?”?实际上,你也得做l.save。好吧,只是我好像找不到法语的翻译。我想我们只是谈谈氨基酸。关于M2M领域,你当然可以随心所欲。如果沿着M2M路线走,您可以在M2M字段中添加一个直通参数,该参数引用您自己的M2M表,例如,您可以在其中添加链中剩余部分的位置。通过这种方式,您可以将链中剩余类型的信息与剩余类型的信息分开。再说一次,你想怎么做就怎么做!第一个属性确实不是很优雅。也许您可以将该类型存储在链模型中,您也可以在第二个属性中使用该模型