Multi select checkbox не работает при создании объекта в django

У меня есть приложение, в котором люди могут объявлять вещи, в decla они могут сказать, кто присутствовал, поэтому они должны платить, только оно не работает. Функция редактирования работает, а fileDecla - нет. Часть, которая не работает, это присутствующие люди. Когда я печатаю присутствующих (через print(request.POST)) перед сохранением декларации, она выдает всех выбранных людей, но потом не сохраняет их, а когда я печатаю(decla.present), я получаю --> None. (должны быть все присутствующие.

).

Кто-то знает решение этой проблемы?

models.py

class Decla(models.Model):
    owner = models.ForeignKey(Lid, on_delete=models.CASCADE)
    event = models.ForeignKey(Event, on_delete=models.SET_NULL, null=True, blank=True)
    content = models.TextField(max_length=50)
    total = models.FloatField()
    present = models.ManyToManyField(Lid, related_name="present_leden")
    receipt = models.ImageField(
        upload_to="declas/", null=True, blank=True
    )  ## this will need to be put back to nothing when it ends
    verwerkt = models.BooleanField(default=False)

views.py


@login_required(login_url="login")
def fileDecla(request):
    form = DeclaForm()
    if request.method == "POST":
        print(1, request.POST)
        form = DeclaForm(request.POST, request.FILES)
        if form.is_valid():
            # print(form)
            decla = form.save(commit=False)
            decla.owner = request.user.lid
            # i tried this line bellow but it didnt work
            # decla.present.set(request.POST["present"])
            decla.save()
            messages.info(request, "Decla was created")
            return redirect("agenda")
    context = {
        "form": form,
        "stand": Stand.objects.get(owner_id=request.user.lid.id).amount,
    }
    return render(request, "finance/decla_form.html", context)


@login_required(login_url="login")
def editDecla(request, pk):
    decla = Decla.objects.get(id=pk)
    form = DeclaForm(instance=decla)
    if request.method == "POST":
        print(request.POST)

        form = DeclaForm(request.POST, request.FILES, instance=decla)
        if form.is_valid():
            decla = form.save()
            messages.info(request, "Decla was edited")
            return redirect(request.GET["next"] if "next" in request.GET else "agenda")
    context = {
        "form": form,
        "stand": Stand.objects.get(owner_id=request.user.lid.id).amount,
    }
    return render(request, "finance/decla_form.html", context)

forms.py

from django import forms
from django.forms import ModelForm
from django.forms.widgets import NumberInput, CheckboxSelectMultiple
from .models import Decla


class DeclaForm(ModelForm):
    class Meta:
        model = Decla
        fields = "__all__"
        exclude = ["owner", "id"]
        widgets = {
            "present": CheckboxSelectMultiple(),
        }

    def __init__(self, *args, **kwargs):
        super(DeclaForm, self).__init__(*args, **kwargs)
        for name, field in self.fields.items():
            if not name in ["verwerkt", "present"]:
                field.widget.attrs.update({"class": "input"})
            # also tried this
            # elif name == "present":
            #     field.widget.attrs.update({"class": "CheckboxSelectMultiple"})
            else:
                field.widget.attrs.update({"class": "checkbox"})

Вот кое-что из документов:

Другой побочный эффект использования commit=False проявляется, когда ваша модель имеет отношение отношение "многие-ко-многим" с другой моделью. Если ваша модель имеет многие-ко-многим и вы указываете commit=False при сохранении форму, Django не может немедленно сохранить данные формы для отношения "многие-ко-многим". Это происходит потому, что невозможно сохранить данные отношения "многие-ко-многим" для экземпляра, пока этот экземпляр не существует в базе данных.

Чтобы обойти эту проблему, каждый раз, когда вы сохраняете форму, используя commit=False, Django добавляет метод save_m2m() в ваш ModelForm подкласса ModelForm. После того, как вы вручную сохранили экземпляр, созданный формы, вы можете вызвать save_m2m(), чтобы сохранить данные формы "многие ко многим".

.

Согласно этому, добавление save_m2m() после вызова decla.save() решит вашу проблему:

@login_required(login_url="login")
def fileDecla(request):
    form = DeclaForm()
    if request.method == "POST":
        print(1, request.POST)
        form = DeclaForm(request.POST, request.FILES)
        if form.is_valid():
            # print(form)
            decla = form.save(commit=False)
            decla.owner = request.user.lid
            # i tried this line bellow but it didnt work
            # decla.present.set(request.POST["present"])
            decla.save()
            form.save_m2m()
            messages.info(request, "Decla was created")
            return redirect("agenda")
    context = {
        "form": form,
        "stand": Stand.objects.get(owner_id=request.user.lid.id).amount,
    }
    return render(request, "finance/decla_form.html", context)

Однако это кажется беспорядочным решением. Более подробную информацию смотрите в this antipattern.

Мое предложение состоит в следующем:

@login_required(login_url="login")
def fileDecla(request):
    form = DeclaForm()
    if request.method == "POST":
        print(1, request.POST)
        form = DeclaForm(request.POST, request.FILES)
        if form.is_valid():
            # This seems like a much cleaner solution and it should resolve your problem
            form.instance.owner = request.user.lid
            decla = form.save()
            messages.info(request, "Decla was created")
            return redirect("agenda")
    context = {
        "form": form,
        "stand": Stand.objects.get(owner_id=request.user.lid.id).amount,
    }
    return render(request, "finance/decla_form.html", context)

Отказ от ответственности: код не проверен. Дайте мне знать, если у вас есть какие-либо ошибки.

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