Django Manytomany доступ к соответствующей колонке - PullRequest
0 голосов
/ 20 февраля 2019

Я пытаюсь понять, как Django понимает отношения m2m, в SQL вы просто добавляете несколько объединений через промежуточную таблицу.

У меня есть контейнер, который содержит различные примеры.Образец можно распределить по различным контейнерам.

Поэтому в свой контейнер я добавляю поле m2m псевдонимов образцов (по сути, это закладка для другой таблицы).

Что я могу сделать, так это получитьодин контейнер и отображение информации о форме, я хотел бы добавить столбцы сэмпла в форму, если я делаю это для поля m2m сэмплов, он возвращает мультиполе, но как мне получить доступ к другим связанным полям через m2m sample_id> =

class Container(models.Model):
    container_id = models.AutoField(primary_key=True)
    samples = models.ManyToManyField(Sample, through='JoinSampleContainer', through_fields=('container_id', 'sample_id'), related_name='container')
    location_id = models.ForeignKey(Location, db_column='location_id', on_delete = models.PROTECT)
    icon_desc = models.ForeignKey(Icon, db_column='icon_desc', null=True, blank=True, default='Box',on_delete = models.PROTECT)
    container_name = models.CharField(max_length=50, blank=True, null=True)
    container_type = models.CharField(max_length=50, blank=True, null=True)

В своей таблице Sample я добавляю псевдоним контейнеров, чтобы он служил закладкой для другой таблицы

class Sample(models.Model):
    sample_id = models.AutoField(primary_key=True)
    containers = models.ManyToManyField(Container, through='JoinSampleContainer', through_fields=('sample_id', 'container_id'), related_name='sample')
    sample_number = models.IntegerField()
    material_type = models.CharField(max_length=200, default='', blank=True, null=True, choices = MATERIALS)
    weight = models.DecimalField(max_digits=6, decimal_places=2)
    description = models.CharField(max_length=500, default='', blank=True, null=True)
    recovery_method = models.CharField(max_length=200, default='', blank=True, null=True, choices = RECOVERY_METHODS)
    comments = models.CharField(max_length=1000, default='', blank=True, null=True)

В этом случае я управляю сквозной таблицей:

class JoinSampleContainer(models.Model):
    id = models.AutoField(primary_key=True)
    container_id = models.ForeignKey(Container, db_column='container_id', on_delete = models.PROTECT)
    sample_id = models.ForeignKey(Sample, db_column='sample_id', on_delete = models.PROTECT)

Итак, теперь я хочу отобразить содержимое одного контейнера через форму.У меня есть настройки URL для передачи container_id.

# views.py
def containercontents(request, pk):
    post = get_object_or_404(Container, pk=pk)
    # objects = Container.samples.all()
    if request.method == "POST":
        form = ContainerContentsForm(request.POST, instance=post)
        if form.is_valid():
            post = form.save(commit=False)
            #post.user = request.user
            #post.datetime = datetime.datetime.now()
            post.save()
            return redirect('allcontainer')
            #, pk=post.pk)
    else:
        form = ContainerContentsForm(instance=post)
    return render(request, 'container/containercontents.html', {'form': form})

Форма

# form.py
class ContainerContentsForm(forms.ModelForm):
    class Meta:
        model = Container
        fields = (
        'location_id',
        'container_name',
        'container_type',
        'icon_desc',
        'samples',
        )

NB. Образцы, кажется, перечисляют все, независимо от контейнера.

Тогдаhtml

# html
<a href="{% url 'containercontents' pk=container.pk %}" class="btn btn-primary" role="button">contents</a>

, который переходит к:

# html
<div class="">
  {{ form }}
</div>    

1 Ответ

0 голосов
/ 20 февраля 2019

Ваши модели определены неправильно: вы не должны определять ManyToManyField на обеих моделях, только на одной из них.Поэтому удалите поле containers на Sample и оставьте его только на Container.Установите related_name в «контейнеры» (во множественном числе).Таким образом, отношение Container -> Sample равно container.samples.all(), а обратное - sample.containers.all().

Теперь цель формы - позволить вам выбрать, какие Sample вы хотитеассоциировать с Container.Таким образом, по умолчанию поле будет представлено ModelMultipleChoiceField.Уже связанные Sample s должны быть предварительно выбраны, когда вы инициализируете форму с экземпляром Container.

Вы можете сузить выборки для выбора, указав queryset для поля, переопределив поле по умолчанию в форме:

class ContainerContentsForm(forms.ModelForm):
    class Meta:
        # same code here

    samples = forms.ModelMultipleChoiceField(
        queryset = Sample.objects.filter(...)
    )

Вы говорите, что хотите «отобразитьсодержимое Container через форму ", если вы просто хотите отобразить, зачем использовать форму?Чтобы просто отобразить содержимое, прокрутите соответствующие образцы и отобразите их:

{% for sample in form.instance.samples.all %}
    {{ sample.sample_id }}
{% endfor %} 

Примечание. Вы должны переименовать свои идентификаторы в id.sample.sample_id плохой стиль программирования.Но я уже говорил вам это.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...