forked from sshwsfc/xadmin
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy patheditable.py
More file actions
160 lines (135 loc) · 6.58 KB
/
editable.py
File metadata and controls
160 lines (135 loc) · 6.58 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
from django import template
from django.core.exceptions import PermissionDenied, ObjectDoesNotExist
from django.db import models, transaction
from django.forms.models import modelform_factory
from django.http import Http404, HttpResponse
from django.utils.encoding import force_unicode, smart_unicode
from django.utils.html import escape, conditional_escape
from django.utils.safestring import mark_safe
from django.utils.translation import ugettext as _
from xadmin.plugins.ajax import JsonErrorDict
from xadmin.sites import site
from xadmin.util import lookup_field, display_for_field, label_for_field, unquote, boolean_icon
from xadmin.views import BaseAdminPlugin, ModelFormAdminView, ListAdminView
from xadmin.views.base import csrf_protect_m, filter_hook
from xadmin.views.edit import ModelFormAdminUtil
from xadmin.views.list import EMPTY_CHANGELIST_VALUE
from xadmin.layout import FormHelper
class EditablePlugin(BaseAdminPlugin):
list_editable = []
def __init__(self, admin_view):
super(EditablePlugin, self).__init__(admin_view)
self.editable_need_fields = {}
def init_request(self, *args, **kwargs):
active = bool(self.request.method == 'GET' and self.admin_view.has_change_permission() and self.list_editable)
if active:
self.model_form = self.get_model_view(ModelFormAdminUtil, self.model).form_obj
return active
def result_item(self, item, obj, field_name, row):
if self.list_editable and item.field and item.field.editable and (field_name in self.list_editable):
pk = getattr(obj, obj._meta.pk.attname)
field_label = label_for_field(field_name, obj,
model_admin=self.admin_view,
return_attr=False
)
item.wraps.insert(0, '<span class="editable-field">%s</span>')
item.btns.append((
'<a class="editable-handler" title="%s" data-editable-field="%s" data-editable-loadurl="%s">' +
'<i class="fa fa-edit"></i></a>') %
(_(u"Enter %s") % field_label, field_name, self.admin_view.model_admin_url('patch', pk) + '?fields=' + field_name))
if field_name not in self.editable_need_fields:
self.editable_need_fields[field_name] = item.field
return item
# Media
def get_media(self, media):
if self.editable_need_fields:
media = media + self.model_form.media + \
self.vendor(
'xadmin.plugin.editable.js', 'xadmin.widget.editable.css')
return media
class EditPatchView(ModelFormAdminView, ListAdminView):
def init_request(self, object_id, *args, **kwargs):
self.org_obj = self.get_object(unquote(object_id))
# For list view get new field display html
self.pk_attname = self.opts.pk.attname
if not self.has_change_permission(self.org_obj):
raise PermissionDenied
if self.org_obj is None:
raise Http404(_('%(name)s object with primary key %(key)r does not exist.') %
{'name': force_unicode(self.opts.verbose_name), 'key': escape(object_id)})
def get_new_field_html(self, f):
result = self.result_item(self.org_obj, f, {'is_display_first':
False, 'object': self.org_obj})
return mark_safe(result.text) if result.allow_tags else conditional_escape(result.text)
def _get_new_field_html(self, field_name):
try:
f, attr, value = lookup_field(field_name, self.org_obj, self)
except (AttributeError, ObjectDoesNotExist):
return EMPTY_CHANGELIST_VALUE
else:
allow_tags = False
if f is None:
allow_tags = getattr(attr, 'allow_tags', False)
boolean = getattr(attr, 'boolean', False)
if boolean:
allow_tags = True
text = boolean_icon(value)
else:
text = smart_unicode(value)
else:
if isinstance(f.rel, models.ManyToOneRel):
field_val = getattr(self.org_obj, f.name)
if field_val is None:
text = EMPTY_CHANGELIST_VALUE
else:
text = field_val
else:
text = display_for_field(value, f)
return mark_safe(text) if allow_tags else conditional_escape(text)
@filter_hook
def get(self, request, object_id):
model_fields = [f.name for f in self.opts.fields]
fields = [f for f in request.GET['fields'].split(',') if f in model_fields]
defaults = {
"form": self.form,
"fields": fields,
"formfield_callback": self.formfield_for_dbfield,
}
form_class = modelform_factory(self.model, **defaults)
form = form_class(instance=self.org_obj)
helper = FormHelper()
helper.form_tag = False
helper.include_media = False
form.helper = helper
s = '{% load i18n crispy_forms_tags %}<form method="post" action="{{action_url}}">{% crispy form %}' + \
'<button type="submit" class="btn btn-success btn-block btn-sm">{% trans "Apply" %}</button></form>'
t = template.Template(s)
c = template.Context({'form': form, 'action_url': self.model_admin_url('patch', self.org_obj.pk)})
return HttpResponse(t.render(c))
@filter_hook
@csrf_protect_m
@transaction.atomic
def post(self, request, object_id):
model_fields = [f.name for f in self.opts.fields]
fields = [f for f in request.POST.keys() if f in model_fields]
defaults = {
"form": self.form,
"fields": fields,
"formfield_callback": self.formfield_for_dbfield,
}
form_class = modelform_factory(self.model, **defaults)
form = form_class(
instance=self.org_obj, data=request.POST, files=request.FILES)
result = {}
if form.is_valid():
form.save(commit=True)
result['result'] = 'success'
result['new_data'] = form.cleaned_data
result['new_html'] = dict(
[(f, self.get_new_field_html(f)) for f in fields])
else:
result['result'] = 'error'
result['errors'] = JsonErrorDict(form.errors, form).as_json()
return self.render_response(result)
site.register_plugin(EditablePlugin, ListAdminView)
site.register_modelview(r'^(.+)/patch/$', EditPatchView, name='%s_%s_patch')