views:

592

answers:

2

Hello

I am not sure if title describes what i want accurately. What i want is to achieve something like that: http://stackoverflow.com/questions/1405587/django-add-remove-form-without-multiple-submit/1406819#1406819.

But i have not list of items i have formset and forms. The form of this formset does contain information i could use for creating link like that {% url 'item_edit' item.id %}. The problem is that it is a value of an hidden field. Here (http://docs.djangoproject.com/en/dev/topics/forms/#looping-over-the-form-s-fields) you have a list of options how to use fields of a form in a template, but none of them is {{ field.value }}. If i tried that, then it just failed silently.

Anyway. to the code. What i have in template is:

 <form enctype="multipart/form-data" method="post" action="/list/edit/{{ list.id }}/">
  <table>
  {{ form.as_table }}
  {{ formset.management_form }}
  {% for form in formset.forms %}
   {% if forloop.first %}
    <tr>
    {% for field in form.visible_fields %}
     <td>{{ field.label }}</td>
    {% endfor %}
    </tr>
   {% endif %}
   <tr>
    {% for field in form.visible_fields %}
     {% if not forloop.last %}
      <td>{{ field }}</td>
     {% else %}
      <td>{{ field }}
     {% endif %}
    {% endfor %}
    {% for field in form.hidden_fields %}
     {% if not forloop.last %}
      {{ field }}
     {% else %}
      {{ field }}</td>
     {% endif %}
    {% endfor %}
   </tr>
  {% endfor %}
  <tr><td><input type="submit" value="Submit"></td><td colspan="4">&nbsp;</td></tr>
  </table>
 </form>

And this gives me inline form rows like this:

<tr>
    <td><input type="text" maxlength="200" value="test2" name="shoppinglistitem_set-0-itemname" id="id_shoppinglistitem_set-0-itemname"/></td>
    <td><input type="text" maxlength="200" value="http://www.xxx.ee" name="shoppinglistitem_set-0-link" id="id_shoppinglistitem_set-0-link"/></td>
    <td><input type="text" maxlength="100" value="eepöäsdöäfsdfd" name="shoppinglistitem_set-0-store" id="id_shoppinglistitem_set-0-store"/></td>
    <td><input type="text" id="id_shoppinglistitem_set-0-price" value="22134" name="shoppinglistitem_set-0-price"/></td>
    <td><input type="checkbox" id="id_shoppinglistitem_set-0-DELETE" name="shoppinglistitem_set-0-DELETE"/><input type="hidden" id="id_shoppinglistitem_set-0-list" value="1" name="shoppinglistitem_set-0-list"/><input type="hidden" id="id_shoppinglistitem_set-0-listitem_ptr" value="5" name="shoppinglistitem_set-0-listitem_ptr"/></td>
</tr>

and i am looking for some way to add link like this

<a href={% url 'remove_list_item' item.id %}>REmove</a>

or just

<a href="http://localhost/list/removeitem/{{ id }}">REmove</a>

Urlconf for this view is:

url(r'^removeitem/(?P<lisitem_id>\d+)/$', 'remove_list_item', name='remove_list_item')

So is there some easy way to get that id of the item(object) from the form? Do i have to create some kind of widget for that remove link instead?

Alan.

A: 

Hello Alan

The for loop you are using in the template can also handle lists of lists or tuples as well as simple lists so the solution I use to this problem, mixing display and formset elements, is to create a list of tuples in my view. Each tuple is (form, data)

I then pass this mixed list of forms and data to the template rather than simply the formset

The outer for loop in your template then becomes

{% for form, data in forms_and_data_list % }
{% endfor %}

you can then display the data part, in your case the edit url, just as you would normally.

Andy
Zayatzz
+1  A: 

First of all, you shouldn't use links (GET requests) to trigger actions that edit or delete data, you should use POST requests.

You can still use a link to delete data by creating one via JavaScript and using their click-Event to make an Ajax POST request. With JavaScript you can also easily read the id from the hidden field. If your form should be usable without JavaScript (and it should), then you should create another form for deleting items (probably just a delete button).

You should use a form for deleting, because for Djangos CSRF-Middleware to work you need forms. And CSRF-Middleware should be in your middleware stack.

If you initialize a Django Form with an object, as you probably have, the fields of the objects are stored in a dictionary called initial. You might be able to access it via form.initial["id"] or in template speak {{ form.initial.id }}, though I am not sure if it works or if it's a good idea.

stefanw
Thank you! i will eventually use ajax to delete rows, i just wanted to know if there is an easyer way to get the id of the object, because i dont want to write javascript for this.{{ form.initial.id }} worked just fine!The whole idea is to have this form working both with and without javascript. I want to rid IE(6) users of ajax, so they would have more reason for upgrading :)Writing about CSRF here made me look up wtf it is. Thanks :). I'll read more about this now.
Zayatzz
I'm quite sure {{ form.instance.pk }} works and is a more 'proper' way to do it.( cannot verify directly right now, so sorry if I remembered incorrectly )
Béres Botond