双向导航多对多关系

时间:2019-05-09 19:48:57

标签: django

我试图了解Django如何从外键返回列,特别是m2m情况,这在SQL中很容易,但是我试图进入Django。

在此示例中,我有3个模型,Sample的平方米为Container

LocationContainer一对一。

方案1a:从“样品”表中获取样品所在的容器(返回sample_number和container_name)。

方案1b:从容器中获取相关的样本(返回container_number和sample_number)。

方案2a:从位置模型中获取容器(location_name和container_names)。

方案2b:从容器模型中获取位置(容器名称和位置名称)。

希望这将为其他人提供一个很好的整体参考。

# models.py
class Location(models.Model):
    location_id = models.AutoField(primary_key=True)
    location_name = models.CharField(max_length=100, blank=True, null=True)

class Sample(models.Model):
    sample_id = models.AutoField(primary_key=True)
    sample_number = models.IntegerField()

class Container(models.Model): #like a friend
    container_id = models.AutoField(primary_key=True)
    container_name = models.CharField(max_length=50, blank=True, null=True)
    location_id = models.ForeignKey(Location, db_column='location_id', on_delete = models.PROTECT, related_name = 'location')
    samples = models.ManyToManyField('Sample', through='ContainerSamples', related_name='containers')

# views.py - Implements a filter
def detailcontainer(request, container_id):
    container = get_object_or_404(Container, pk=container_id)
    samples = container.samples.all()
    container_contents = container.samples.all()
    unassigned_samples = Sample.objects.all()

    qs = Sample.objects.all()

    context = {
        'queryset': qs,
        'container':container,
        'container_contents': container_contents,
        'unassigned_samples': unassigned_samples,
    }
    return render(request, 'container/detailcontainer.html', context)

# templates

{% for unassigned in unassigned_samples %}

# 1a [solved]
{% for unassigned in unassigned_samples %}
  {{ unassigned.sample_number }}
  {% for container in unassigned.containers.all %}
    {{ container.location_id }}.{{ container.container_name }}
  {% endfor %}
{% endfor %}

# 1b
{{ unassigned.____________ }} # the container_name
{{ unassigned.____________ }} # the related samples (sample_number)

# 2a
{{ unassigned.____________ }} # the location_name
{{ unassigned.____________ }} # the related container names (container_name)

# 2b
{{ unassigned.____________ }} # the container_name
{{ unassigned.____________ }} # the location_name

{% endfor %}

1 个答案:

答案 0 :(得分:0)

  

方案1a:从“样品”表中获取样品所在的容器(返回sample_number和container_name)。

container_set = sample.containers.all()
for container in container_set:
    print([container.container_name, sample.sample_name])

方案1b:从容器中获取相关的样本(返回container_number和sample_number)。

sample_set = container.samples.all()
for sample in sample_set:
    print([sample.sample_number, container.container_number])
  

方案2a:从位置模型中获取容器(location_name和container_names)。

container_set = location.location.all() # You have Container.location_id.related_name = 'location', I don't know why.
for container in container_set:
    print([location.location_name, container.container_name])
  

方案2b:从容器模型中获取位置(容器名称和位置名称)。

print([container.container_name, container.location_id.location_name])

您的模型也应编写如下:

# models.py
class Location(models.Model):
    name = models.CharField(max_length=100, blank=True, null=True)

class Sample(models.Model):
    number = models.IntegerField()

class Container(models.Model): #like a friend
    container = models.AutoField(primary_key=True)
    name = models.CharField(max_length=50, blank=True, null=True)
    location = models.ForeignKey(Location, on_delete = models.PROTECT, related_name='containers')
    samples = models.ManyToManyField(Sample, through='ContainerSamples', related_name='containers')

如果对模型上的自动字段使用相同的定义,则无需添加它。在模型上定义属性(例如名称)时,不应在模型名称前添加前缀。应该理解,这是模型的名称。最后,related_name是参考模型上的字段,该关系可以遍历回当前模型。