Commits

Dmitri Lebedev  committed 7390bce

simplified forms: id is passed in form, but not taken when form is saved

  • Participants
  • Parent commits 2c2f857

Comments (0)

Files changed (5)

File example/django_inline/templates/inline-editable.html

-<span class="jeditable" href="{{ url }}" id="{% editable_id obj field %}">{{ inner }}</span>
+<span class="jeditable" href="{% url django_inline_widget %}" id="{% editable_id obj field_name %}">{{ inner }}</span>

File example/django_inline/templates/inline-form.html

 {% load i18n %}
-<form action="{{ url }}" method="POST" class="django_inline">
+<form action="{% url django_inline_update %}" method="POST" class="django_inline">
 	{% csrf_token %}
 	{{ form.id }}
 	{{ form.value }}

File example/django_inline/templatetags/inline.py

     def render(self, context):
         inner_content = self.nodelist.render(context)
         obj = self.obj.resolve(context)
-        field = self.field.resolve(context)
+        field_name = self.field.resolve(context)
         class_name = obj.__class__.__name__
         if not context['user'].has_perm('%s.can_edit' % class_name, obj):
             return inner_content
         
         return loader.render_to_string(templates_list('inline-editable.html', obj), {
             'obj': obj,
-            'field': field,
+            'field_name': field_name,
             'inner': inner_content,
         })
 

File example/django_inline/urls.py

 from django.conf.urls.defaults import patterns, url
 
-id_signature = '(?P<app_label>\w+)/(?P<model>\w+)/(?P<pk>\w+)/(?P<field_name>\w+)/$'
+id_signature = '(?P<app_label>\w+)/(?P<model_name>\w+)/(?P<pk>\w+)/(?P<field_name>\w+)/$'
 
 urlpatterns = patterns('django_inline.views',
-    url(r'^widget/' + id_signature, 'widget', name='django_inline_widget'),
-    url(r'^update/' + id_signature, 'update', name='django_inline_update'),
+    url(r'^widget/$', 'widget', name='django_inline_widget'),
+    url(r'^update/$', 'update', name='django_inline_update'),
 )

File example/django_inline/views.py

 from functools import wraps
 
-from django.forms.models import modelform_factory
+from django import forms
 from django.conf import settings
-from django.core.urlresolvers import reverse
 from django.db.models import get_model
 from django.http import Http404
 from django.shortcuts import render_to_response, get_object_or_404
     request object. Gracefully raises 404 errors if the id is wrong.
     """
     @wraps(func)
-    def decorated(request, app_label, model_name, pk, field_name):
+    def decorated(request):
         # the id can be in get, post or put method
         # this has to be de-hard-coded
-
-        model = get_model(app_label, model_name)
-
+        for method in ('GET', 'POST', 'PUT'):
+            id = getattr(request, method, {}).get('id')
+            if id:
+                break
+        
+        try:
+            app_label, class_name, pk, field_name = id.split('-')
+        except ValueError:  # if the number of items in the string is wrong
+            _raise_error(id)
+        
+        model = get_model(app_label, class_name)
         obj = get_object_or_404(model, pk=int(pk))
-        FormClass = modelform_factory(obj.__class__, ['id', field_name])
-        return func(request, app_label, obj, field_name, FormClass)
+        
+        class FormClass(forms.ModelForm):
+            class Meta:
+                model = obj.__class__
+                fields = (field_name,)
+        
+        return func(request, app_label, obj, field_name, id, FormClass)
 
     return decorated
 
 
 @get_params
-def widget(request, app_label, obj, field_name, FormClass):
+def widget(request, app_label, obj, field_name, id, FormClass):
     """
     Creates a form on the fly and renders it in a template.
 
 
     You can override the template with your own. It has to be named 'inline-form.html', and can be put in templates/%app_name%/%model_name%, templates/%app_name% or templates folder (folders are searched in the given order).
     """
+    class NewFormClass(FormClass):
+        id = forms.CharField(widget=forms.HiddenInput())
+        value = FormClass.base_fields[field_name]
     
+    form = NewFormClass(initial={'id': id, 'value': getattr(obj, field_name)})
     
     return render_to_response(templates_list('inline-form.html', obj), {
-        'url': reverse('django_inline_update', args=[app_label, obj.__class__.__name__, obj.pk, field_name]),
-        'form': FormClass(initial={'id': id, 'value': getattr(obj, field_name)}),
+        'form': form,
         'obj': obj,
-        'field': field_name,
+        'field_name': field_name,
     }, context_instance=RequestContext(request))
 
 
 @get_params
-def update(request, app_label, obj, field_name, FormClass):
+def update(request, app_label, obj, field_name, id, FormClass):
     """
     Checks user permissions and saves the data in the model.
     """
     if request.user.has_perm('%s.can_edit' % obj.__class__.__name__, obj):
-        form = FormClass(data={'id': obj.id, field_name: request.POST['value']})
+        
+        form = FormClass(data={field_name: request.POST['value']}, instance=obj)
         form.save()
 
     return render_to_response(
         templates_list('inline-editable.html', obj), {
         'obj': obj,
-        'field': field_name,
+        'field_name': field_name,
         'inner': getattr(obj, field_name),
-        'url': reverse('django_inline_widget', args=[app_label, obj.__class__.__name__, obj.pk, field_name]),
     }, context_instance=RequestContext(request))