我在SPA的POST数据中收到最多N uuid4值的数组。我当时应该进入一个删除指定对象实例的视图:
<QueryDict: {'uuids[]' : [
'a1a241bd-147f-4672-86d7-1a6225b8080e'
'791db3f0-5134-4927-b328-347c7261d7f6'
'b8087a1b-710e-47b4-af5a-bae4d5e30532'
'6d1a96b2-1b99-4707-a8e3-376a0d596d95'
...
]}>
据我所知,MultiValueField
处理此数据的目的可能并非如此,因为我不想&#34;压缩&#34;它。什么是django处理这样的表单数据的方式?我是否应该手动尝试自己处理request.POST
并通过表单运行每个uuid来验证它?或覆盖form.clean()
?
答案 0 :(得分:0)
在这种情况下,你可能最适合编写一个可以包含在其他地方的小型模型:
class UUIDItem(models.Model):
request = models.PositiveIntegerField()
uuid = models.UUID()
你可以很容易地与另一个模型相关:
class UUIDContainer(models.Model):
request = AutoField()
@classmethod
def add(self, uuid):
if isinstance(uuid, list):
for id in uuids:
UUIDItem.objects.filter(request=self.request, uuid=id).create()
else:
UUIDItem.objects.filter(request=self.request, uuid=uuid).create()
uuids = models.ForeignKey(
UUIDRequest,
on_delete=model.CASCADE,
limit_choices_to={'request': self.request})
通过这种抽象级别,您可以轻松地列出,修改和添加UUID到现有请求,或创建不同的“存储”
l = UUIDList()
l.add(your_uuids)
l.id # will print some id
UUIDItem.objects.filter(request=l.request).all()
瞧瞧瞧。处理您的UUID列表。
答案 1 :(得分:0)
我决定使用自定义字段并覆盖post()。如果有更好的方式,我们会感谢评论/编辑。
import uuid
from django.core.exceptions import ValidationError
MAX_UUIDS = 10
class UUIDArrayField(forms.Field):
""" Custom field representing an array of up to MAX_UUIDS uuid4 strings """
def clean(self, value):
if type(value) != type([]):
raise ValidationError(self.error_messages['not_a_list'])
if len(value) > MAX_UUIDS:
raise ValidationError(self.error_messages['too_many_values'])
try:
for v in value:
print(v)
uuid.UUID(v, version=4) # ValueError if not a valid uuid4
return value
except:
raise ValidationError(self.error_messages['invalid_uuid'])
class ObjectMultiDeleteForm(forms.Form):
""" form to delete multiple products """
uuids = UUIDArrayField(
error_messages = {
'not_a_list': _("A data type other than list was supplied."),
'too_many_values': _("The list of values exceeds the maximum allowed."),
'invalid_uuid': _("An invalid identifier was specified."),
})
from django.shortcuts import redirect
class ObjectMultiDelete(FormView):
""" Deletes object instances from a list of their uuids """
http_method_names = ['post',] #only accept POST requests
success_url = reverse_lazy("objectlist")
success_message = "%(message)s"
form_class = ProductMultiDeleteForm
def dispatch(self, request, *args, **kwargs):
#access control goes here
return super(ObjectMultiDelete, self).dispatch(request, *args, **kwargs)
def get_success_message(self, cleaned_data):
return self.success_message % dict(
message = _("The specified objects were successfully deleted."),
)
def post(self, request, *args, **kwargs):
post_data = request.POST.copy() #request.POST is immutable
#because you can't name a form field 'uuids[]', but that's what you get when posting an array
post_data['uuids'] = post_data.pop('uuids[]')
form = ObjectMultiDeleteForm()
form.data = post_data #bind form
form.is_bound = True
if form.is_valid():
objects = Object.objects.filter(access_control_here)\
.filter(uuid__in=form.cleaned_data['uuids'])
objects.delete()
return redirect(self.success_url)
else:
#handle invalid form how you want