我正在使用Django构建服务台,我希望允许客户端在提交工单时上传多个文件。
我正在尝试通过使用表单集来做到这一点。
我发现了许多与类似问题有关的问题,但是我仍然无法使我的表格正常工作。我会感激朝正确方向的指针。
我在下面发布了相关代码:
# models.py
class Ticket(models.Model):
PRIORITY_CHOICES = (
(1, 'Critical'),
(2, 'High'),
(3, 'Normal'),
(4, 'Low'),
(5, 'Very Low'),
)
STATUS_CHOICES = (
(1, 'Open'),
(2, 'Reopened'),
(3, 'Resolved'),
(4, 'Closed'),
(5, 'Duplicate'),
)
ticket_number = models.CharField(max_length=50, blank=True,
null=True, unique=True)
client = models.ForeignKey(settings.AUTH_USER_MODEL,
editable=True, on_delete=models.CASCADE,
related_name="tickets")
title = models.CharField("Summary",
max_length=200,
help_text='Provide a brief description of your request.')
description = models.TextField(blank=True,
help_text='Provide as much detail as possible to help us resolve this ticket as quickly as possible.')
due_date = models.DateField(blank=True, null=True)
assigned_to = models.ForeignKey(settings.AUTH_USER_MODEL,
related_name="assigned",
blank=True, null=True,
on_delete=models.CASCADE)
priority = models.IntegerField(choices=PRIORITY_CHOICES,
editable=True, default=3,
help_text='Please select a priority carefully. If unsure, leave it as "Normal".',
blank=True, null=True)
status = models.IntegerField(choices=STATUS_CHOICES,
editable=True,
default=1, blank=True, null=True)
closing_date = models.DateField(blank=True, null=True)
closing_notes = models.TextField(blank=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
upload = models.FileField(upload_to='uploads/%Y/%m/%d/', blank=True, null=True)
def get_absolute_url(self):
return reverse('tickets:ticket-detail', args=[str(self.id)])
def __str__(self):
return str(self.ticket_number)
class TicketFile(models.Model):
attachment = models.FileField(upload_to='attachments/%Y/%m/%d', blank=True, null=True)
ticket = models.ForeignKey(Ticket, editable=True, on_delete=models.CASCADE)
description = models.CharField(max_length=200, blank=True)
def get_image_filename(self):
if self.docfile:
return media_url + str(self.docfile)
def __str__(self):
return str(self.attachment)
# forms.py
class TicketFormIsStaff(ModelForm):
class Meta:
model = Ticket
exclude = ()
class TicketFileForm(forms.ModelForm):
attachment = forms.FileField(label='Attachment')
class Meta:
model = TicketFile
fields = ('attachment', )
TicketAttachmentFormset = modelformset_factory(Ticket,
form=TicketFileForm, extra=2)
# views.py
class TicketCreateView(CreateView):
model = Ticket
fields = ['ticket_number', 'client', 'title', 'description', 'status']
def get_context_data(self, **kwargs):
data = super(TicketCreateView, self).get_context_data(**kwargs)
if self.request.POST:
data['ticketfiles'] = TicketAttachmentFormset(self.request.POST)
print("data 1 ", data['ticketfiles'] )
else:
data['ticketfiles'] = TicketAttachmentFormset()
print("data 2 ", data)
return data
def form_valid(self, form):
context = self.get_context_data()
ticketfiles = context['ticketfiles']
with transaction.atomic():
self.object = form.save()
print("CONTEXT:::: ", ticketfiles)
if ticketfiles.is_valid():
ticketfiles.instance = self.object
ticketfiles.save()
return super(TicketCreateView, self).form_valid(form)
# ticket_form.html
<form action="" method="post" enctype="multipart/form-data">{% csrf_token %}
{{ form.as_p }}
<table class="table">
{{ ticketfiles.management_form }}
{% for form in ticketfiles.forms %}
{% if forloop.first %}
<thead>
<tr>
{% for field in form.visible_fields %}
<th>{{ field.label|capfirst }}</th>
{% endfor %}
</tr>
</thead>
{% endif %}
<tr class="{% cycle row1 row2 %} formset_row">
{% for field in form.visible_fields %}
<td>
{# Include the hidden fields in the form #}
{% if forloop.first %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% endif %}
{{ field.errors.as_ul }}
{{ field }}
</td>
{% endfor %}
</tr>
{% endfor %}
</table>
<input type="submit" value="Save" />
</form>
与票证模型相关的所有数据均正确上载,但与票证文件模型相关的文件未上载。如果我尝试在管理界面中上传数据,则一切运行正常。我认为这意味着所有媒体设置都是正确的。
如果我将描述字段添加到表单集中,则可以正确保存该字段。不过该文件未保存。
答案 0 :(得分:0)
我通过更改TicketCreateView中的代码从以下位置解决了文件上传问题:
data['ticketfiles'] = TicketAttachmentFormset(self.request.POST)
收件人:
data['ticketfiles'] = TicketAttachmentFormset(self.request.POST, self.request.FILES, instance=form.instance))