多选择的复选框无法在Django中创建对象

发布于 2025-02-02 21:13:51 字数 3090 浏览 0 评论 0原文

我有一个应用程序,人们可以在其中宣告事情,在声明中他们可以说是谁在场,所以他们必须付款,只能付款。编辑功能有效,但FileDecla却没有。 行不通的部分是目前的人。当我打印出席的人(通过print(request.post))在保存声明之前,它会给所有选择的人,但后来却没有保存他们,当我打印(decla.present)时,我会得到 - >没有

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)


@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)

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"})

I have a app where people can declare things, within a decla they can say who was present so they have to pay, only its not working. The edit function works but the fileDecla doesn't.
The part that doensn't work is the present people. When i print the people present (via print(request.POST))before i save the decla it gives all the people selected but then it doesnt save them, and when i print(decla.present) i get --> None.(it should be all the people present.

Does someone know a solution to this?

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"})

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

小忆控 2025-02-09 21:13:51

这是 docs :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

使用commit = false的另一个副作用在您的模型具有
与另一个模型的多一关系。如果您的模型有一个
多一关系的关系,您在保存一个时指定commit = false
表单,Django无法立即保存表单数据
多一的关系。这是因为不可能保存
一个实例的多一数据数据,直到实例存在于
数据库。

要解决此问题,每次您使用
commit = false,django添加了一个save_m2m()方法
子类。手动保存了由
表单,您可以调用save_m2m()来保存多一对多的表单数据。

据此,添加save_m2m()在调用exta.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)

但是,这似乎是一个混乱的解决方案。参见 Antpattern 有关更多信息。

我的建议是这样做:

@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)

免责声明:未经测试的代码。让我知道您是否有错误。

Here is something from the docs:

Another side effect of using commit=False is seen when your model has
a many-to-many relation with another model. If your model has a
many-to-many relation and you specify commit=False when you save a
form, Django cannot immediately save the form data for the
many-to-many relation. This is because it isn’t possible to save
many-to-many data for an instance until the instance exists in the
database.

To work around this problem, every time you save a form using
commit=False, Django adds a save_m2m() method to your ModelForm
subclass. After you’ve manually saved the instance produced by the
form, you can invoke save_m2m() to save the many-to-many form data.

According to this, adding save_m2m() after calling decla.save() would resolve your issue:

@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)

However, this seems like a messy solution. See this antipattern for more info.

My suggestion is to do this:

@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)

Disclaimer: the code is untested. Let me know if you have any bugs.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文