Django ManyToMany no guarda

Resuelto Ryan Thomas asked hace 10 meses • 1 respuestas

Tengo un ModelMultipleChoiceField que intento guardar como relaciones ManyToMany y probé casi todas las soluciones en Internet, pero por alguna razón no puedo guardar la mía. No recibo ningún error y el resto del formulario se envía simplemente no ManyToMany.

    Models.py

    class Game(models.Model):
        players = models.ManyToManyField(Student, blank=True)

        other fields...

    class Student(models.Model):
        user_name = models.CharField(max_length=150, null=False, blank=False)
    Forms.py

    class Game(forms.ModelForm):

        players = forms.ModelMultipleChoiceField(widget=forms.CheckboxSelectMultiple(),                                                   
                                                 queryset=Student.objects.all(), 
                                                 label="Players", required=False)
    Views.py

    def creategame(request):

        if request.method == "POST":
            form = Game(request.POST)
            if form.is_valid():
                form.save()
                return redirect(reverse('management'))

        else:
            ...

Probé varias soluciones como esta, pero ninguna funcionó.

    Views.py

    def creategame(request):

        if request.method == "POST":
            form = Game(request.POST)
            if form.is_valid():
                new_game = form.save(commit=False)
                new_game.save()
                form.save_m2m()

                return redirect(reverse('management'))

        else:
            ...
Ryan Thomas avatar Feb 16 '24 18:02 Ryan Thomas
Aceptado

Probablemente el campo no esté incluido en el Metaformulario, de ahí el problema. Podemos solucionar esto con:

class GameForm(forms.ModelForm):
    class Meta:
        model = Game
        fields = ['players']
        widgets = {'players': forms.CheckboxSelectMultiple()}
        labels = {'players': 'Players'}

Entonces esto debería funcionar con la vista:

def creategame(request):
    if request.method == 'POST':
        form = GameForm(request.POST, request.FILES)
        if form.is_valid():
            form.save()
            return redirect('management')
    else:
        form = GameForm()
    return render(request, 'some-template.html', {'form': form})

Sin embargo , una idea podría ser trabajar con un [Django-doc] basado en clases :CreateView 

from django.urls import reverse_lazy
from django.views.generic.edit import CreateView


class GameCreateView(CreateView):
    form_class = GameForm
    template_name = 'some-template.html'
    success_url = reverse_lazy('management')

y registrar esto en el urls.pycomo:

path('/game/create', GameCreateView.as_view(), 'name-of-view'),

Nota : Normalmente a Formo a ModelFormterminan con un …Formsufijo, para evitar colisiones con el nombre del modelo y dejar claro que estamos trabajando con un formulario . Por lo tanto, podría ser mejor utilizarlo GameFormen lugar de Game.


Nota : Si bien la mayoría de los formularios no procesan archivos multimedia, probablemente sea mejor pasar [Django-doc] al formulario de todos modos, de modo que si luego agrega un campo multimedia adicional, todas las vistas que usan el formulario manejarán los archivos correctamente. .request.FILES 

willeM_ Van Onsem avatar Feb 16 '2024 12:02 willeM_ Van Onsem