Advertisement
kastielspb

Custome pg ArrayField dispaying

Dec 12th, 2018
169
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 3.81 KB | None | 0 0
  1. # forms.py
  2. from shared.admin.fields import DynamicArrayField
  3. class ExampleAdminForm(forms.ModelForm):
  4.     class Meta:
  5.         model = Realty
  6.         fields = '__all__'
  7.         field_classes = {
  8.             'prices': DynamicArrayField,
  9.         }
  10.  
  11. # fields.py
  12. from itertools import chain
  13.  
  14. from django import forms
  15. from django.contrib.postgres.utils import prefix_validation_error
  16.  
  17. from .widgets import DynamicArrayFieldWidget
  18.  
  19. __all__ = ('DynamicArrayField')
  20.  
  21. class DynamicArrayField(forms.Field):
  22.     default_error_messages = {
  23.         'item_invalid': 'Item %(nth)s in the array did not validate: ',
  24.     }
  25.  
  26.     def __init__(self, base_field, **kwargs):
  27.         self.base_field = base_field
  28.         self.max_length = kwargs.pop('max_length', None)
  29.         kwargs.setdefault('widget', DynamicArrayFieldWidget)
  30.         super().__init__(**kwargs)
  31.  
  32.     def clean(self, value):
  33.         cleaned_data = []
  34.         errors = []
  35.         value = filter(None, value)
  36.         for index, item in enumerate(value):
  37.             try:
  38.                 cleaned_data.append(self.base_field.clean(item))
  39.             except forms.ValidationError as error:
  40.                 errors.append(prefix_validation_error(
  41.                     error, self.error_messages['item_invalid'],
  42.                     code='item_invalid', params={'nth': index},
  43.                 ))
  44.         if errors:
  45.             raise forms.ValidationError(list(chain.from_iterable(errors)))
  46.         return cleaned_data
  47.  
  48. # widgets.py
  49. from django import forms
  50.  
  51. __all__ = (
  52.     'DynamicArrayFieldWidget',
  53. )
  54.  
  55. class DynamicArrayFieldWidget(forms.TextInput):
  56.     template_name = 'admin/forms/widgets/dynamic_array.html'
  57.  
  58.     def get_context(self, name, value, attrs):
  59.         value = value or ['']
  60.         context = super().get_context(name, value, attrs)
  61.         final_attrs = context['widget']['attrs']
  62.         id_ = context['widget']['attrs'].get('id')
  63.  
  64.         subwidgets = []
  65.         for index, item in enumerate(context['widget']['value']):
  66.             widget_attrs = final_attrs.copy()
  67.             if id_:
  68.                 widget_attrs['id'] = f'{id_}_{index}'
  69.             widget = forms.TextInput()
  70.             widget.is_required = self.is_required
  71.             subwidgets.append(widget.get_context(name, item, widget_attrs)['widget'])
  72.         context['widget']['subwidgets'] = subwidgets
  73.         return context
  74.  
  75.     def value_from_datadict(self, data, files, name):
  76.         try:
  77.             getter = data.getlist
  78.         except AttributeError:
  79.             getter = data.get
  80.         return getter(name)
  81.  
  82.     def format_value(self, value):
  83.         return value or []
  84.  
  85. # dynamic_array.html
  86. {% load i18n %}
  87. {% spaceless %}
  88. <div class="dynamic-array-widget" style="width: 100%">
  89.   <ul id="array-items">
  90.     {% for widget in widget.subwidgets %}
  91.       <li class="array-item">
  92.         {% include widget.template_name %}
  93.         <img class="del-array-item" style="margin: 0 5px;" src="/static/admin/img/icon-deletelink.svg" alt="Delete">
  94.       </li>
  95.     {% endfor %}
  96.   </ul>
  97.   <div class="add-row">
  98.     <button type="button" class="add-array-item">{% blocktrans %}Add another{% endblocktrans %}</button>
  99.   </div>
  100. </div>
  101. {% endspaceless %}
  102.  
  103. <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
  104. <script>
  105. var $clone = $('.array-item').last()
  106. $('.dynamic-array-widget').on("click", '.add-array-item', function() {
  107.   var $new = $clone.clone()
  108.   var id_parts = $new.find('input').attr('id').split('_')
  109.   var id = id_parts.slice(0, -1).join('_') + '_' + String(parseInt(id_parts.slice(-1)[0]) + 1)
  110.   $new.find('input').attr('id', id)
  111.   $new.find('input').prop('value', '')
  112.   $new.appendTo('#array-items')
  113. });
  114.  
  115. $('.dynamic-array-widget').on("click", '.del-array-item', function() {
  116.   $(this).parent('li').remove();
  117. });
  118. </script>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement