You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django表单上传多文件时提示DeliveryCreateView无object属性如何解决

问题根本原因

你遇到的AttributeError: 'DeliveryCreateView' object has no attribute 'object'报错,以及多文件上传逻辑的问题,核心有5个错误:

    1. 重写post方法后,调用form_valid之前没有为视图的object属性赋值:CreateView的form_valid方法默认会保存表单生成实例并赋值给self.object,你自定义的post逻辑跳过了这个步骤,导致后续get_success_url读取self.object.pk时找不到属性。
    1. 字段名拼写错误:获取上传文件时写的是request.FILES.getlist("decument"),实际字段名是document,拼写错误会导致拿不到上传的文件列表。
    1. 模型调用错误:self.Delivery.objects.create写法错误,视图实例本身没有Delivery属性,应该直接调用模型类Delivery.objects.create,或者用视图绑定的self.model.objects.create。
    1. 模型设计不符合多文件上传需求:当前的Delivery模型只有一个FileField,一个实例只能关联一个文件,你循环创建多个Delivery实例的逻辑不符合业务需求,相当于每传一个文件就生成一个重复的配送单,其他必填字段(用户、地址、时间)都会缺失。
    1. 类继承冗余:CreateView本身已经继承了FormView,不需要重复继承。

解决方案

1. 先修正模型,增加多文件关联表

# 原Delivery模型保留,删除原来的document字段,新增独立的文件表
class Delivery(models.Model):
    user = models.ForeignKey(
        Client, on_delete=models.CASCADE, verbose_name=_("Client"), related_name="delivery_user"
    )
    pickup_address = models.ForeignKey(Address, on_delete=models.CASCADE, related_name="pickup_address")
    destination_address = models.ForeignKey(Address, on_delete=models.CASCADE, related_name="destination_address")
    operation_date = models.DateField(
        _("desired pickup date"), auto_now=False, auto_now_add=False, blank=False, null=False
    )
    operation_time = models.TimeField(
        _("desired pickup time"), auto_now=False, auto_now_add=False, blank=False, null=False
    )

    class Meta:
        ordering = ("-created_at",)
        verbose_name = _("Delivery")
        verbose_name_plural = _("Deliveries")

    def get_absolute_url(self):
        return reverse("delivery:unconf-delivery-details", args=[self.id])

# 新增配送文件表,一个配送单对应多个文件
class DeliveryDocument(models.Model):
    delivery = models.ForeignKey(Delivery, on_delete=models.CASCADE, related_name="documents")
    document = models.FileField(
        help_text=_("Delivery Documents"),
        verbose_name=_("Delivery Certificates"),
        upload_to="documents/deliveries_documents/",
    )

注意:related_name不要加翻译函数_(),它是代码中调用的属性,不需要国际化

2. 修正表单

class UserDeliveryForm(forms.ModelForm):
    # 新增多文件上传字段,不绑定到Delivery模型
    documents = forms.FileField(widget=forms.ClearableFileInput(attrs={"multiple": True}), required=False)
    class Meta:
        model = Delivery
        fields = [
            "user",
            "pickup_address",
            "destination_address",
            "operation_date",
            "operation_time",
        ]
        widgets = {
            "operation_date": forms.DateInput(
                format=("%d %B %Y"),
                attrs={"class": "form-control mb-2 delivery-form", "placeholder": "JJ-MM-AAAA"},
            ),
            "operation_time": forms.TimeInput(
                attrs={"type": "time", "class": "form-control mb-2 delivery-form"},
            ),
            "user": forms.Select(),
            "pickup_address": forms.Select(),
            "destination_address": forms.Select(),
        }

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields["user"].widget.attrs.update({"class": "form-control mb-2 delivery-form", "placeholder": "Client "})
        self.fields["pickup_address"].widget.attrs.update(
            {"class": "form-control mb-2 dropdown delivery-form", "placeholder": "Addresse de ramassage "}
        )
        self.fields["destination_address"].widget.attrs.update(
            {"class": "form-control mb-2 delivery-form", "placeholder": "Addresse de destination"}
        )

3. 修正视图逻辑

# 去掉冗余的FormView继承
class DeliveryCreateView(LoginRequiredMixin, UserPassesTestMixin, CreateView):
    model = Delivery
    form_class = UserDeliveryForm
    template_name = "deliveries/customer/edit_deliveries.html"

    def get_success_url(self):
        return reverse("delivery:operation-form", kwargs={"pk": self.object.pk})

    def test_func(self):
        return self.request.user.is_active

    def form_valid(self, form):
        # 先保存配送单主实例,赋值给self.object
        self.object = form.save()
        # 获取上传的所有文件
        files = self.request.FILES.getlist("documents")
        for file in files:
            # 为每个文件创建关联的配送文件记录
            DeliveryDocument.objects.create(delivery=self.object, document=file)
        return super().form_valid(form)

不需要重写整个post方法,直接重写form_valid即可,原有逻辑更加简洁,也不会丢失CreateView的默认处理逻辑


内容的提问来源于stack exchange,提问作者E.Mohammed

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 13:36:04