Jak dodać dane do pola ManyToMany?

83

Nie mogę go nigdzie znaleźć, więc twoja pomoc będzie dla mnie miła :) Oto pole:

categories = models.ManyToManyField(fragmentCategory)

Kategoria fragmentu:

class fragmentCategory(models.Model):

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

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

Oto formularz do wysłania:

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

Próbowałem czegoś takiego:

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

Lub:

categories = [1,2]
IProblemFactory
źródło

Odpowiedzi:

144

Jest cała strona dokumentacji Django poświęcone temu , dobrze indeksowane od strony treści.

Jak stwierdza ta strona, musisz zrobić:

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

lub

my_obj.categories.create(name='val1')
Daniel Roseman
źródło
15
Czy musisz wtedy zadzwonić, my_obj.save()aby zapisać aktualizację, czy dzieje się to automatycznie?
CpILL
4
@CpILL Wydaje się, że dzieje się to automatycznie. Wypróbuj to python manage.py shell.
Rikki
1
jak ten dokument, którego potrzebujesz, zadzwoń. też zapisz
mehdi
4
@mehdi Wystarczy wywołać save za pierwszym razem, gdy tworzysz obiekt z polem wiele do wielu, aby uzyskać klucz podstawowy. Po tym zachowanie jest takie, że możesz dodawać bez zapisywania.
YungGun
5

Na wypadek, gdyby ktoś inny skończył tutaj, walcząc z dostosowaniem formularza administratora Many2Many zachowania oszczędzającego, nie możesz wywołać self.instance.my_m2m.add(obj)swojego ModelForm.saveoverride, ponieważ ModelForm.savepóźniej zapełnia twój m2m, z self.cleaned_data['my_m2m']którego nadpisuje twoje zmiany. Zamiast tego zadzwoń:

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

(Dobrze jest przekonwertować przychodzące QuerySet na listę - i ManyToManyFieldtak to robi.)

Chris
źródło