¿Cómo agregar datos al campo ManyToMany?

83

No puedo encontrarlo en ningún lado, por lo que su ayuda será buena para mí :) Aquí está ese campo:

categories = models.ManyToManyField(fragmentCategory)

Fragmento Categoría:

class fragmentCategory(models.Model):

        CATEGORY_CHOICES = (
                        ('val1', 'value1'),
                        ('val2', 'value2'),
                        ('val3', 'value3'),
                        )

        name = models.CharField(max_length=20, choices=CATEGORY_CHOICES)

Aquí está el formulario para enviar:

<input type="checkbox" name="val1" />
<input type="checkbox" name="val2" />
<input type="checkbox" name="val3" />

Intenté algo como esto:

categories = fragmentCategory.objects.get(id=1),

O:

categories = [1,2]
IProblemFactory
fuente

Respuestas:

141

Hay una página completa de la documentación de Django dedicada a esto , bien indexada desde la página de contenido.

Como dice esa página, debe hacer:

my_obj.categories.add(fragmentCategory.objects.get(id=1))

o

my_obj.categories.create(name='val1')
Daniel Roseman
fuente
14
¿Necesita llamar my_obj.save()para guardar la actualización o se hace automáticamente?
CpILL
4
@CpILL Parece que se hace automáticamente. Pruébelo en python manage.py shell.
Rikki
1
como este documento, necesita llamar .save también: docs.djangoproject.com/en/2.2/topics/db/examples/many_to_many/…
mehdi
3
@mehdi Solo necesita llamar a save la primera vez que crea el objeto con el campo de muchos a muchos para que obtenga una clave principal. Después de eso, el comportamiento es que puede agregar sin guardar.
YungGun
5

En caso de que alguien más termine aquí luchando por personalizar el comportamiento de ahorro de Many2Many del formulario de administración, no puede llamar self.instance.my_m2m.add(obj)a su ModelForm.saveanulación, ya que ModelForm.saveluego rellena su m2m desde el self.cleaned_data['my_m2m']cual sobrescribe sus cambios. En su lugar llame a:

my_m2ms = list(self.cleaned_data['my_m2ms'])
my_m2ms.extend(my_custom_new_m2ms)
self.cleaned_data['my_m2ms'] = my_m2ms

(Está bien convertir el QuerySet entrante en una lista, lo ManyToManyFieldhace de todos modos).

Chris
fuente