Как сохранить несколько значений из выпадающего списка с внешним ключом

Я хочу сохранить несколько идентификаторов магазинов в таблице Test в столбце store_id. Как лучше всего спроектировать модель для сохранения идентификаторов нескольких магазинов в таблице Test models.py

class Store(models.Model):
      store_name = models.CharField(max_length=100, verbose_name="store")
      def __unicode__(self):
         return '%s' %(self.name)
      def __str__(self):
         return self.name
class Test(models.Model):
      store_id = models.ForeignKey(Store, on_delete=models.CASCADE, db_column='store_id')
      def __unicode__(self):
         return '%s' %(self.id)

Forms.py

class TestForm(ModelForm):
     def __init__(self, *args, **kwargs):
        self.fields['store_id'] = ModelChoiceField(queryset=Store.objects.all(), widget=SelectMultiple(attrs={'class':'form-control'})
      class Meta:
           model = Test
           fields = ('store_id',)

Я хочу сохранить несколько идентификаторов магазинов в таблице Test в столбце store_id.

Нельзя. Это поле, которое по сути имитирует столбец первичного ключа Store, поэтому оно может содержать только одно такое значение.

A ManyToManyField [Django-doc], this will create a junction table [wiki] in between that wil link to a Store and a Test, so:

class Store(models.Model):
    name = models.CharField(max_length=100, verbose_name='store')

    def __str__(self):
        return self.name


class Test(models.Model):
    stores = models.ManyToManyField(Store)

    def __str__(self):
        return f'{self.id}'

В форме это будет работать с ModelMultipleChoiceField [Django-doc]:

class TestForm(ModelForm):
     def __init__(self, *args, **kwargs):
        self.fields['stores'].widget.attrs.update(class='form-control')
      class Meta:
           model = Test
           fields = ('stores',)

Примечание: Обычно не добавляют суффикс …_id к полю ForeignKey, так как Django автоматически добавит поле-"близнец" с суффиксом …_id. Поэтому он должен быть store, вместо store_id.

Чтобы сохранить несколько идентификаторов магазинов в таблице Test из выпадающего списка, необходимо переключить поле store_id в модели Test на использование ManyToManyField вместо ForeignKey.

Обновите свой models.py следующим образом:

from django.db import models

class Store(models.Model):
    store_name = models.CharField(max_length=100, verbose_name="store")

    def __str__(self):
        return self.store_name

class Test(models.Model):
    store_id = models.ManyToManyField(Store)

    def __str__(self):
        return f'Test {self.id}'

Затем обновите свой forms.py следующим образом:

from django.forms import ModelForm, ModelMultipleChoiceField, SelectMultiple
from .models import Test, Store

class TestForm(ModelForm):
    def __init__(self, *args, **kwargs):
        super(TestForm, self).__init__(*args, **kwargs)
        self.fields['store_id'] = ModelMultipleChoiceField(
            queryset=Store.objects.all(), 
            widget=SelectMultiple(attrs={'class':'form-control'})
        )

    class Meta:
        model = Test
        fields = ('store_id',)

Вы использовали оба метода __str__ и __unicode__ в своих моделях, что не является необходимым, в Python 3 и версиях Django, поддерживающих Python 3, вы должны определить только метод __str__ для своих моделей. Метод __unicode__ использовался в Python 2 для обеспечения корректного представления символов non-ASCII. Поскольку Python 3 по умолчанию использует Unicode для строк, __unicode__ больше не нужен.

Вернуться на верх