Here's the way I'm doing it:
{{ formset.management_form }}
<table>
{% for form in formset.forms %}
{{ form }}
{% endfor %}
</table>
Add Form
And here's the JS:
var form_count = {{formset.total_form_count}};
$('#add_form').click(function() {
form_count++;
var form = '{{formset.empty_form|escapejs}}'.replace(/__prefix__/g, form_count);
$('#forms').append(form)
$('#id_form-TOTAL_FORMS').val(form_count);
});
What specifically bothers me is that I had to write that escapejs template tag myself. It just strips all newlines and escapes any single quotes so that it doesn't mess up my string. But what exactly did the Django makers expect us to do in this situation? And why do they have this TOTAL_FORMS hidden field, when they could have just used an array like <input name="my_form_field[0]" /> and then counted its length instead?
There are a few places in Django where "the reason why" is because that's how it was implemented for the Django admin app, and I believe this is one of them. Thus the answer is they expect you to implement your own javascript.
See this SO question Dynamically adding a form... for some more javascript ideas.
There are also two pluggable apps available, django-dynamic-formset and django-dinamyc-form which I hadn't seen until just now when looking up the first one.
This question is a bit old, but it took me a while to figure this out as well.
I suggest rendering formset.empty_form in your template as a hidden field, and referencing this field in your javascript.
Here's a complicated dynamic formset example from the django admin site:
(but note that it has not been updated to use empty_form....)
[js]
http://code.djangoproject.com/browser/django/trunk/django/contrib/admin/media/js/inlines.js
[html template]
http://code.djangoproject.com/browser/django/trunk/django/contrib/admin/templates/admin/edit_inline/tabular.html
It's because formset have been created to work without javascript, using only the usual HTTP workflow.
Django is javascript agnostic.
If you want to add some javascript to the mix, you can use the dedicated jquery plugin.
in my case. i used the plugin django-dynamic-formset (https://code.google.com/p/django-dynamic-formset/wiki/Usage)
and modified the option "added" and worked good.
$('#formset-table tbody tr').formset({
prefix: '{{ formset.prefix }}',
formCssClass: '{{ formset.prefix }}-inlineformset',
added: function(obj_tr){
var form = $(obj_tr).html().replace(/\-(\w+)\-(\w+)(fix__)\-/g, '-');
$(obj_tr).html(form);
},
this regular expression replace the string [prefix]-prefix peer '-'
maybe isn't the best solution, but worked.
There are some cases of possible XSS when using formset.empty_form as a string, replacing '__prefix__' to actual formset form index. My pluggable application converts formset.empty_form into Knockout.js template which is then cloned via custom Knockout.js bindings. Also Knockout.js automatically re-calculates form field id indexes, when newly added formset form is dynamically deleted before the whole form with inlineformsets was submitted. Here is the documentation:
https://django-jinja-knockout.readthedocs.org/en/latest/forms.html#dynamically-adding-new-related-formset-forms
Knockout.js binding also prevents XSS when loading custom fields with inline Javascript.
Related
I have a screen built with a several stacks of ng-includes. The last one, in special, I build the screen based on user configuration.
Sometimes, I have to show a Form in one of this included templates. And when my user click on save button, I have to validate if all fields in the form are valid.
In the meantime, when a try to access form object, to check for $valid, my form is undefined.
After a day fighting against it, I've discovered that ng-include process is not accepting my form object to be created.
I've created this plunker to see if it's really happening on a simple project, making a working form and not working one:
http://plnkr.co/edit/4oMZYLgaYHJPoSZdSctI?p=preview
Basically, created a form, like this, with demanded angular attributes:
<form name="sampleForm">
<input type="text" name="aws" required ng-model="myValue">
<br/>myValue: "{{ myValue }}"
<br/>
<input type="text" name="aws" required ng-model="myValue">
<br/>myValue: "{{ myValue }}"
</form>
And trying to access form object like this:
$scope.sampleForm.aws.$valid
And the result is:
$scope.sampleForm === undefined
Someone know how to solve this problem?
Since ng-include creates a new scope, $scope.sampleForm will be undefined from within the included page.
The solution should be getting the ng-controller="formController" declaration inside of the included HTML page itself, which I think is also a better design, since I can't see a scenario where it's not "controlling" the form.
The other non-included form obviously works as you might expect.
Plunker
I want to display user typed html (from WYSIWYG).
But I have some problems with removing js from html.
Here is my view:
def bad_view(request):
# in real project we got it from user
bad_html = '<p onclick="alert(0)">:((</p><script>alert(0);</script>'
return render(request, 'template.html', {'bad_html': bad_html})
Here code in my template:
{{ bad_html|safe }}
bad_html should be like this <p onclick="">:((</p>
What is best way to remove ALL js from this html?
For removing <script> I can use regex, but what about onclick handler(and other js handlers)?
Thanks for your advices!
I recommend using the bleach python library, it is designed to handle all sorts of special cases and be a complete solution for your problem
http://bleach.readthedocs.org/en/latest/index.html
Might I suggest a prebuilt solution for django https://www.djangopackages.com/grids/g/forms/
Most have some form of filter examples included. I am actually looking into TinyMCE myself.
More info is here Using safe filter in Django for rich text fields
I want to know if it is a good practice to use razor in JavaScript code. For example:
<script type="text/javascript">
var variable = #some.Id
</script>
Or it's better to create hidden value and then take it with JavaScript, like this?
<input type="hidden" id="someId" value"#some.Id" />
<script type="text/javascript">
var variable = $('#someId').val();
</script>
EDIT:
#{
var formVariables = serializer.Serialize(new
{
id = Model.Id,
name = Model.Name,
age = Model.Age
});
<input type="hidden" id="header_variables" value="#formVariables"/>
<script type="text/javascript" src = "/Scipts/..."></script>
}
Is this good solution?
I personally would go with an extension of the 2nd option and create a seperate .js file. The reason being, if you delegate work out to a 3rd party to take care of the jquery/javascript parts of the UI, then they need not have any sight of the backend functionality.
There are a variety of ways to use html5 attributes (i.e. data-attribute='foo') on the inputs which would allow you to 'decorate' your inputs with a cargo of properties which could be parsed inside the external .js file.
A very brief example:
in your view:
<input type='text' id='myId' data-action='#Url.Action("MyAction")' class='myClass' />
in your .js file:
var targetAction = $('#myId').attr('data-action');
this gives complete separation between the .js and the views. It does require a degree of planning of course.
Hope this helps
Razor will be parsed at server-side and replaced by relevant output. Therefore, in my opinion it is totally indifferent, if you place it in Javascript or HTML - at client side only the output value will be visible. Thus, in the above example I would choose the first option (place it directly in JS), since you will not have the otherwise unnecessary hidden input field.
I don't think there is a correct answer to this question; only pros and cons.
Pros of using Razor in Javascript
Script is bound to your view model; so model changes will get picked up automatically, and errors will get caught at compile time.
Cons
Script is mixed with markup, contrary to web design best practices (put script at the bottom so that it will never break your page).
Script cannot be compiled/minified, because, again, it's mixed in with your markup.
I'm very new to web development and I know this might be stupid approach but cannot think of a better way of doing this. In the views.py a method returns a dictionary named sniffer_aps to the template in following format:
sniffer_aps = {device1:[ap1, ap2], device2:[ap3, ap4, ap5], ......}
In the template I have a dropdown list that lists all devices(device1, device2, ......).
In another field I list all aps belong to the device selected in the dropdown list. I want to dynamically adjust the field according to the device I selected, but it doesn't really work.
The dropdown list code is:
<select onchange="refresh(this.value)" id="sniffer_list">
{% for sniffer_ap in sniffer_aps %}
<option value={{ sniffer_ap }}>{{ sniffer_ap.plug_ip }}</option>
{% endfor %}
</select>
My question is that how can I loop though the value in the field that shows aps based on the option selected in the dropdown list?
Right now my approach is to use javascript to detect the "onchange" event of the dropdown list, and change the value the field that list all aps accordingly, then just get the value of the field and treat it as the key of the dictionary.
function refresh(key) {
$('.router').attr('value') = key;
}
For the field that lists aps, it is where the problem is. I'm trying to achieve something like this:
<select multiple="multiple" size="6">
{% for router in sniffer_aps[this.value] %}
<option class="router" value="">{{ router }}</option>
{% endfor %}
</select>
Please correct my approach, or if somebody can provide a better way. Thanks very much.
You're running into trouble here because you're confusing server-side code (Django's templating engine) with client-side code (the Javascript code you're using for the onchange handler). Your server-side code will have run on the server before the resulting HTML is ever delivered to the client, so you can't have any interactions between client-side Javascript and the template logic.
You're right to use Javascript and the onchange event to update the values in the field that lists apps - you could do this on the server, by submitting the form and changing the HTML with Django when the new request is returned, but this takes a new webpage load and isn't nearly as fast or user-friendly as doing it with Javascript.
I would approach this by:
Converting the dictionary to JSON in your Django view class:
import json
...
sniffer_app_json = json.dumps(sniffer_apps)
Outputing the JSON as a JavaScript object in your template code:
var snifferApps = {{ sniffer_apps_json }};
Using JavaScript to update the apps field, using this data. There are many questions addressing this on StackOverflow - you might consider using jQuery, as it makes this sort of manipulation much easier.
Is there a specific reason that most everyone implements edit-in-place as a shown 'display' div and a hidden 'edit' div that are toggled on and off when somebody clicks on the associated 'edit' button like so?
<div id="title">
<div class="display">
<h1>
My Title
</h1>
</div>
<div class="edit">
<input type="text" value="My Title" />
<span class="save_edit_button"></span>
Cancel
</div>
</div>
Everywhere I look, I see edit-in-place basically handled like this. This approach certainly makes sense when you are rendering all views on the server side and delivering them to the client. However, with pure AJAX apps and frameworks like backbone.js, it seems that we could make our code much more DRY by rendering edit-in-place form elements on the fly as necessary, possibly even making a factory method that determines which form element to render. e.g.
an H1 element with class "title" is replaced by <input type="text" />
a span with class "year_founded" is replaced by <input type="number" min="1900" max="2050" />
a span with class "price" is replaced by an input with the appropriate mask to only allow prices to be input.
Is this practice of rendering all edit-in-place form elements a historical legacy leftover from when pages were rendered on the server-side?
Given the flexibility and power we have with client-side MVC frameworks like Backbone.js, is there a reason for not creating and inserting the form elements on the fly when necessary using a factory method? Something like this:
HTML
<div id="description">
Lorem ipsum dolar set amit...
</div>
<span class="edit_button"></span>
Backbone.js View
events: {
"click .edit_button": "renderEditInPlaceForm",
},
renderEditInPlaceForm: function:(e) {
var el = $(e.currentTarget).previous();
var id = el.attr('id');
var value = el.text();
var tagName = el.tagName();
var view = new editInPlaceForm({
id: id,
type: tagName,
value: value
});
$("#id").html(view.render().el)
},
Where editInPlaceForm is a factory that returns the appropriate edit-in-place form element type based on tagName. This factory view also controls all its own logic for saving an edit, canceling an edit, making requests to the server and rerendering the appropriate original element that was replaced with the .html() function?
It seems to me that if we use this approach then we could also render the <span class="edit_button"></span> buttons on the fly based on a user's editing rights like so:
<h1 id="title">
<%= document.get("title") %>
</h1>
<% if (user.allowedToEdit( document, title )) { %>
<span class="edit_glyph"></span>
<% } %>
where the allowedToEdit function on the user model accepts a model and attribute as its arguments.
It's an interesting idea. The devil is in the detail.
While your simple example is easily rendered as an editable form on the fly, things quickly get trickier when dealing with other data types.
For example - suppose my edit form requires the user to choose a value from a select list. On the display form I can simply display the user's choice, but for the edit form I am going to need those other available choices. Where do I hide them on the display? Similar issues exist for checkboxes, radio lists...
So, perhaps we should consider rendering the edit form, and then deriving our display-view from that?
After 5 Backbone apps I came to same thoughts.
When things are complicated you have forms to show relations between user data,
but in simple cases you just need input, select, checkbox over h1, div or span
Now I am searching for jQuery plugin to make simple in place editing without ajax.
jQuery but not Backbone becuase I don't want to be tight coupled with Backbone for such small thing.
Likely to wright my own jQuery + Synapse plugin http://bruth.github.com/synapse/docs/.
Synapse for binding with model and jQuery for input placing