gpt4 book ai didi

Django 管理员自定义 ArrayField 小部件

转载 作者:行者123 更新时间:2023-12-03 21:44:31 24 4
gpt4 key购买 nike

ArrayField 的当前管理小部件是一个字段,以逗号作为分隔符,如下所示(文本列表):

Current admin ArrayField widget

这并不理想,因为我会有更长的文本(甚至 20 个单词)并包含逗号。我可以 change the delimiter to be something else但这仍然无助于管理员中不可读的内容。

我想要的是有一个字段列表,我可以在管理员中更改。类似于下图的东西

Wanted admin ArrayField widget

我可以使用另一个表来解决这个问题,但我想知道是否可以通过这种方式解决它。

最佳答案

不幸的是,Django 没有为ArrayField 提供方便的小部件。 s 还。我建议你创建自己的。这是 的示例Django>=1.11 :

class DynamicArrayWidget(forms.TextInput):

template_name = 'myapp/forms/widgets/dynamic_array.html'

def get_context(self, name, value, attrs):
value = value or ['']
context = super().get_context(name, value, attrs)
final_attrs = context['widget']['attrs']
id_ = context['widget']['attrs'].get('id')

subwidgets = []
for index, item in enumerate(context['widget']['value']):
widget_attrs = final_attrs.copy()
if id_:
widget_attrs['id'] = '%s_%s' % (id_, index)
widget = forms.TextInput()
widget.is_required = self.is_required
subwidgets.append(widget.get_context(name, item, widget_attrs)['widget'])

context['widget']['subwidgets'] = subwidgets
return context

def value_from_datadict(self, data, files, name):
try:
getter = data.getlist
except AttributeError:
getter = data.get
return getter(name)

def format_value(self, value):
return value or []

这是小部件模板:
{% spaceless %}
<div class="dynamic-array-widget">
<ul>
{% for widget in widget.subwidgets %}
<li class="array-item">{% include widget.template_name %}</li>
{% endfor %}
</ul>
<div><button type="button" class="add-array-item">Add another</button></div>
</div>
{% endspaceless %}

一些javascript(为方便起见使用jQuery):
$('.dynamic-array-widget').each(function() {
$(this).find('.add-array-item').click((function($last) {
return function() {
var $new = $last.clone()
var id_parts = $new.find('input').attr('id').split('_');
var id = id_parts.slice(0, -1).join('_') + '_' + String(parseInt(id_parts.slice(-1)[0]) + 1)
$new.find('input').attr('id', id);
$new.find('input').prop('value', '');
$new.insertAfter($last);
};
})($(this).find('.array-item').last()));
});

您还必须创建自己的表单域:
from itertools import chain

from django import forms
from django.contrib.postgres.utils import prefix_validation_error

class DynamicArrayField(forms.Field):

default_error_messages = {
'item_invalid': 'Item %(nth)s in the array did not validate: ',
}

def __init__(self, base_field, **kwargs):
self.base_field = base_field
self.max_length = kwargs.pop('max_length', None)
kwargs.setdefault('widget', DynamicArrayWidget)
super().__init__(**kwargs)

def clean(self, value):
cleaned_data = []
errors = []
value = filter(None, value)
for index, item in enumerate(value):
try:
cleaned_data.append(self.base_field.clean(item))
except forms.ValidationError as error:
errors.append(prefix_validation_error(
error, self.error_messages['item_invalid'],
code='item_invalid', params={'nth': index},
))
if errors:
raise forms.ValidationError(list(chain.from_iterable(errors)))
if cleaned_data and self.required:
raise forms.ValidationError(self.error_messages['required'])
return cleaned_data

最后,在您的表单上明确设置它:
class MyModelForm(forms.ModelForm):

class Meta:
model = MyModel
fields = ['foo', 'bar', 'the_array_field']
field_classes = {
'the_array_field': DynamicArrayField,
}

关于Django 管理员自定义 ArrayField 小部件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49323361/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com