-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathREADME
206 lines (144 loc) · 6.75 KB
/
README
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
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
django-inline-edit makes it easy to create inline-editable content.
The default is to use the same criteria as Django's admin app to
determine which users can edit (ie those that have editing permissions
on the model in question), but it is easy to override this decision criteria.
#Usage
Here's an example of how it works:
Given these models:
class Author(models.Model):
name = models.CharField(max_length=100)
class Book(models.Model):
author = models.ForeignKey(Author)
title = models.CharField(max_length=100)
creating an inline editable view is simple:
InlineUpdateView.as_view(model=Author)
By default, this will look for a template at "books/publisher_inline_form.html"
##Templates
This template could look like this:
{% if form %}
To toggle edit mode, click
<a href="#my_editable_content" class="iedit_button">here</a>
{% endif %}
<div id="my_editable_content">
<div class="iedit_content">
<h2>{{ object.title }}</h2>
{{ object.body }}
</div>
{% if form %}
<form action="" method="post" class="iedit_form">
{{ form }}
<input type="submit" value="Save" />
</form>
{% endif %}
</div>
The magic lies in the class names (iedit_button, iedit_content and iedit_form):
elements with class `iedit_form` are shown when in edit mode
elements with class `iedit_content` are shown when in view mode
An element with class `iedit_button` acts as a toggle between edit and view modes for its specified editable section. On page load, we are in view mode: all content is shown and forms are hidden. In the example above, when the the link is clicked, form and content sections within the `my_editable_content` div have their visibility toggled. For more complex setups (toggling multiple editable sections; using elements other than links as buttons; different on and off buttons), see below.
To sumarize:
- on page load, any edit-mode element is hidden; view-mode elements are visible.
- when an element with the `iedit_button` class is clicked, the forms are shown and content is hidden. Its data-edit-selector (or href) attribute is used to locate the
### Multiple toggle areas and other more complex setups
`data-edit-selector`
If the edit button is a link, it toggles visibility of form and content sections within the element specified by the button's `href` attribute, but more complicated setups are often needed. In these cases, the data-iedit-selector attribute can be used to specify a CSS selector to specify content area(s). This makes it easy to customize the behaviour.
For example, to have seperate edit-mode on and off buttons:
{% if form %}
<div class="editable">
<div class="iedit_content iedit_button" data-iedit-selector=".editable">
Edit the page
</div>
<div class="iedit_form iedit_button" data-iedit-selector=".editable">
View the page
</div>
</div><!-- end of class="editable" -->
{% endif %}
<div class="editable">
<div class="iedit_content">
<h2>{{ object.title }}</h2>
{{ object.body }}
</div>
{% if form %}
<form action="" method="post" class="iedit_form">
{{ form }}
<input type="submit" value="Save" />
</form>
{% endif %}
</div>
Note: If a link has a `data-edit-selector` attribute, that will be used rather than the `href`, thus allowing links to arbitrary content for those viewers with javascript disabled.
For the curious: yes, this `data-` attribute is valid markup (see [John Resig's blog post for details](http://ejohn.org/blog/html-5-data-attributes/). Why, then, employ the `href` element attribute at all? [For its semantic value -- pointing to a single element is `href`'s _raison d'etre_.](http://www.danwebb.net/2010/1/27/put-that-data-attribute-away-son-you-might-hurt-someone)
TODO
Additionally,
edit_mode_off
edit_mode_on
##Animation
To use jQuery's slide animation, add `data-edit-slide="duration"` onto the button tag.
#Custom dispatch criteria
books.change_author
urls.py:
def can_edit_author(request, *args, **kwargs):
""" Crowdsource updates to Jimmy Wales' author profile """
author = get_object_or_404(Author, slug=kwargs['slug'])
crowdsourced = author.name == 'Jimmy Wales'
# this is the same check that InlineUpdate normally does
user_is_editor = request.user.has_perm('books.change_author')
return user_is_editor or crowd_sourced
urlpatterns = patterns('',
url(r'^(?P<slug>\w+)*/$',
InlineUpdateView.as_view(model=Author, condition_func=can_edit_author),
name='author_view'
),
)
#Embedded Inline Forms
django-inline-edit also has an implementation of ModelForm that allows
the inclusion of inline formsets within it.
from django.forms.models import inlineformset_factory
from embedded_inline_form import ModelForm
class AuthorBooksForm(ModelForm):
class Meta:
model = Author
class Forms:
inlines = {
'books': inlineformset_factory(Author, Book),
}
class AuthorUpdateView(UpdateView):
form_class = AuthorBooksForm
model = Author
AuthorUpdateView().as_view()
The embedded formsets can then be accessed in the template:
{{ form.inlineformsets.books.management_form }}
{{ form.inlineformsets.books.non_form_errors }}
<table>
{{ form.inlineformsets.books }}
</table>
#How form submission works
uses jquery.form
<script src="http://github.com/malsup/form/raw/master/jquery.form.js?v2.43"></script>
<script src="{{ STATIC_URL }}inline_edit/inline_edit.js"></script>
django-inline-edit captures submit events generated within the form and processes them with ajax, disabling the form until the submission is complete.
capture submit events for forms either contained within or containing the editable section
When it finishes, all editable blocks are updated with the new contents from the returned page.
If the blocks can't be found, then we assume the whole page has changed, and display the new page in its entirety (by replacing the body element).
Also, if you don't want to do ajax-based submission, set data-iedit-submit="noajax" on the containing element.
#ConditionalDispatchView
InlineUpdateView is implemented using ConditionalDispatchView, which
can be used on its own. For example:
class ArticleView(ConditionalDispatchView):
"""
Dispatches a DetailView or a RedirectView, if the Article body is a link
Usage (in urls.py): ArticleView().as_view(model=NewsArticle)
"""
template_name_suffix = '_article'
class Meta:
class true_view_class(RedirectView, DetailView):
def get_redirect_url(self, **kwargs):
model = self.get_queryset().model
article = get_object_or_404(model, pk=kwargs['pk'])
return strip_link(article.body)
false_view_class = DetailView
@staticmethod
def condition_func_factory(true_model, false_model):
model = false_model
def condition_func(request, *args, **kwargs):
article = get_object_or_404(model, pk=kwargs['pk'])
return is_link(article.body)
return condition_func