Ticket #4236: create_update_newforms.diff

File create_update_newforms.diff, 13.9 KB (added by dmach@…, 8 years ago)
  • django/views/generic/create_update.py

     
     1from django import newforms as forms
     2from django.contrib.auth.views import redirect_to_login
     3from django.core.exceptions import ObjectDoesNotExist, ImproperlyConfigured
    14from django.core.xheaders import populate_xheaders
    2 from django.template import loader
    3 from django import oldforms
    45from django.db.models import FileField
    5 from django.contrib.auth.views import redirect_to_login
    6 from django.template import RequestContext
    76from django.http import Http404, HttpResponse, HttpResponseRedirect
    8 from django.core.exceptions import ObjectDoesNotExist, ImproperlyConfigured
    97from django.utils.translation import gettext
     8from django.template import RequestContext, loader
    109
    11 def create_object(request, model, template_name=None,
    12         template_loader=loader, extra_context=None, post_save_redirect=None,
    13         login_required=False, follow=None, context_processors=None):
     10
     11def create_object(request, model,
     12        template_name=None, template_loader=loader,
     13        extra_context=None, post_save_redirect=None,
     14        login_required=False, context_processors=None,
     15        not_required_fields=None, hidden_fields=None,
     16        default_data=None, choices=None):
    1417    """
    1518    Generic object-creation function.
    1619
     
    1922        form
    2023            the form wrapper for the object
    2124    """
    22     if extra_context is None: extra_context = {}
    2325    if login_required and not request.user.is_authenticated():
    2426        return redirect_to_login(request.path)
    2527
    26     manipulator = model.AddManipulator(follow=follow)
    27     if request.POST:
    28         # If data was POSTed, we're trying to create a new object
     28    FormClass = forms.models.form_for_model(model)
     29    if request.method == 'POST':
     30        # Create a form with POSTed data
    2931        new_data = request.POST.copy()
    3032
    3133        if model._meta.has_field_type(FileField):
    3234            new_data.update(request.FILES)
    3335
    34         # Check for errors
    35         errors = manipulator.get_validation_errors(new_data)
    36         manipulator.do_html2python(new_data)
     36        form = FormClass(new_data)
    3737
    38         if not errors:
    39             # No errors -- this means we can save the data!
    40             new_object = manipulator.save(new_data)
     38    else:
     39        # Create new form with default data
     40        if default_data is None: default_data = {}
     41        form = FormClass(default_data)
    4142
    42             if request.user.is_authenticated():
    43                 request.user.message_set.create(message=gettext("The %(verbose_name)s was created successfully.") % {"verbose_name": model._meta.verbose_name})
     43    # Modify choices
     44    if choices:
     45        for field in choices.keys():
     46            if not form.fields.has_key(field): raise FieldDoesNotExist
     47            form.fields[field] = forms.ChoiceField(choices[field])
    4448
    45             # Redirect to the new object: first by trying post_save_redirect,
    46             # then by obj.get_absolute_url; fail if neither works.
    47             if post_save_redirect:
    48                 return HttpResponseRedirect(post_save_redirect % new_object.__dict__)
    49             elif hasattr(new_object, 'get_absolute_url'):
    50                 return HttpResponseRedirect(new_object.get_absolute_url())
    51             else:
    52                 raise ImproperlyConfigured("No URL to redirect to from generic create view.")
    53     else:
    54         # No POST, so we want a brand new form without any data or errors
    55         errors = {}
    56         new_data = manipulator.flatten_data()
     49    # Mark some fields as 'hidden'
     50    if hidden_fields:
     51        for (field, value) in hidden_fields.iteritems():
     52            if not form.fields.has_key(field): raise FieldDoesNotExist
     53            form.fields[field].widget = forms.HiddenInput()
     54            # Prevent hidden field from being modified
     55            form.data[field] = value
     56            # Empty hidden fields are supposed not to be required
     57            if value == "": form.fields[field].required = False
    5758
    58     # Create the FormWrapper, template, context, response
    59     form = oldforms.FormWrapper(manipulator, new_data, errors)
    60     if not template_name:
     59    # Mark some fields as 'not required'
     60    if not_required_fields:
     61        for field in not_required_fields:
     62            if not form.fields.has_key(field): raise FieldDoesNotExist
     63            form.fields[field].required = False
     64
     65    if request.method == 'POST' and not form.errors:
     66        # Form does't contain errors, save the data
     67        new_object = form.save()
     68
     69        if request.user.is_authenticated():
     70            request.user.message_set.create(message=gettext("The %(verbose_name)s was created successfully.") % {"verbose_name": model._meta.verbose_name})
     71
     72        # Redirect to the new object: first by trying post_save_redirect,
     73        # then by obj.get_absolute_url; fail if neither works.
     74        if post_save_redirect:
     75            return HttpResponseRedirect(post_save_redirect % new_object.__dict__)
     76        elif hasattr(new_object, 'get_absolute_url'):
     77            return HttpResponseRedirect(new_object.get_absolute_url())
     78        else:
     79            raise ImproperlyConfigured("No URL to redirect to from generic create view.")
     80
     81    # Create template
     82    if template_name is None:
    6183        template_name = "%s/%s_form.html" % (model._meta.app_label, model._meta.object_name.lower())
    6284    t = template_loader.get_template(template_name)
     85
     86    # Create context
    6387    c = RequestContext(request, {
    6488        'form': form,
    6589    }, context_processors)
    66     for key, value in extra_context.items():
    67         if callable(value):
    68             c[key] = value()
    69         else:
    70             c[key] = value
     90
     91    # Add extra context
     92    if extra_context:
     93        for key, value in extra_context.items():
     94            if callable(value):
     95                c[key] = value()
     96            else:
     97                c[key] = value
     98
     99    # Render template and return the response
    71100    return HttpResponse(t.render(c))
    72101
    73 def update_object(request, model, object_id=None, slug=None,
    74         slug_field=None, template_name=None, template_loader=loader,
    75         extra_context=None, post_save_redirect=None,
    76         login_required=False, follow=None, context_processors=None,
    77         template_object_name='object'):
     102
     103def update_object(request, model,
     104        object_id=None, slug=None, slug_field=None,
     105        template_name=None, template_loader=loader,
     106        template_object_name='object',
     107        extra_context=None, context_processors=None,
     108        post_save_redirect=None, login_required=False,
     109        not_required_fields=None, hidden_fields=None,
     110        choices=None):
     111
    78112    """
    79113    Generic object-update function.
    80114
     
    85119        object
    86120            the original object being edited
    87121    """
    88     if extra_context is None: extra_context = {}
    89122    if login_required and not request.user.is_authenticated():
    90123        return redirect_to_login(request.path)
    91124
     
    97130        lookup_kwargs['%s__exact' % slug_field] = slug
    98131    else:
    99132        raise AttributeError("Generic edit view must be called with either an object_id or a slug/slug_field")
     133
    100134    try:
    101135        object = model.objects.get(**lookup_kwargs)
    102136    except ObjectDoesNotExist:
    103137        raise Http404, "No %s found for %s" % (model._meta.verbose_name, lookup_kwargs)
    104138
    105     manipulator = model.ChangeManipulator(getattr(object, object._meta.pk.attname), follow=follow)
     139    FormClass = forms.models.form_for_instance(object)
     140    if request.method == 'POST':
     141        # Create a form with POSTed data
     142        new_data = request.POST.copy()
    106143
    107     if request.POST:
    108         new_data = request.POST.copy()
    109144        if model._meta.has_field_type(FileField):
    110145            new_data.update(request.FILES)
    111         errors = manipulator.get_validation_errors(new_data)
    112         manipulator.do_html2python(new_data)
    113         if not errors:
    114             object = manipulator.save(new_data)
    115146
    116             if request.user.is_authenticated():
    117                 request.user.message_set.create(message=gettext("The %(verbose_name)s was updated successfully.") % {"verbose_name": model._meta.verbose_name})
     147        form = FormClass(new_data)
    118148
    119             # Do a post-after-redirect so that reload works, etc.
    120             if post_save_redirect:
    121                 return HttpResponseRedirect(post_save_redirect % object.__dict__)
    122             elif hasattr(object, 'get_absolute_url'):
    123                 return HttpResponseRedirect(object.get_absolute_url())
    124             else:
    125                 raise ImproperlyConfigured("No URL to redirect to from generic create view.")
    126149    else:
    127         errors = {}
    128         # This makes sure the form acurate represents the fields of the place.
    129         new_data = manipulator.flatten_data()
     150        # Create a form with original object data
     151        form = FormClass()
    130152
    131     form = oldforms.FormWrapper(manipulator, new_data, errors)
     153    # Modify choices
     154    if choices:
     155        for field in choices.keys():
     156            if not form.fields.has_key(field): raise FieldDoesNotExist
     157            form.fields[field] = forms.ChoiceField(choices[field])
     158
     159    # Mark some fields as 'hidden'
     160    if hidden_fields:
     161        for (field, value) in hidden_fields.iteritems():
     162            if not form.fields.has_key(field): raise FieldDoesNotExist
     163            form.fields[field].widget = forms.HiddenInput()
     164            # Prevent hidden field from being modified
     165            form.data[field] = value
     166            # Empty hidden fields are supposed not to be required
     167            if value == "": form.fields[field].required = False
     168
     169    # Mark some fields as 'not required'
     170    if not_required_fields:
     171        for field in not_required_fields:
     172            if not form.fields.has_key(field): raise FieldDoesNotExist
     173            form.fields[field].required = False
     174
     175    if request.method == 'POST' and not form.errors:
     176        object = form.save(new_data)
     177
     178        if request.user.is_authenticated():
     179            request.user.message_set.create(message=gettext("The %(verbose_name)s was updated successfully.") % {"verbose_name": model._meta.verbose_name})
     180
     181        # Do a post-after-redirect so that reload works, etc.
     182        if post_save_redirect:
     183            return HttpResponseRedirect(post_save_redirect % object.__dict__)
     184        elif hasattr(object, 'get_absolute_url'):
     185            return HttpResponseRedirect(object.get_absolute_url())
     186        else:
     187            raise ImproperlyConfigured("No URL to redirect to from generic create view.")
     188
     189    # Create template
    132190    if not template_name:
    133191        template_name = "%s/%s_form.html" % (model._meta.app_label, model._meta.object_name.lower())
    134192    t = template_loader.get_template(template_name)
     193
     194    # Create context
    135195    c = RequestContext(request, {
    136196        'form': form,
    137197        template_object_name: object,
    138198    }, context_processors)
    139     for key, value in extra_context.items():
    140         if callable(value):
    141             c[key] = value()
    142         else:
    143             c[key] = value
     199
     200    # Add extra context
     201    if extra_context:
     202        for key, value in extra_context.items():
     203            if callable(value):
     204                c[key] = value()
     205            else:
     206                c[key] = value
     207
     208    # Render template and return the response
    144209    response = HttpResponse(t.render(c))
    145210    populate_xheaders(request, response, model, getattr(object, object._meta.pk.attname))
    146211    return response
    147212
     213
    148214def delete_object(request, model, post_delete_redirect,
    149         object_id=None, slug=None, slug_field=None, template_name=None,
    150         template_loader=loader, extra_context=None,
    151         login_required=False, context_processors=None, template_object_name='object'):
     215        object_id=None, slug=None, slug_field=None,
     216        template_name=None, template_loader=loader,
     217        template_object_name='object', login_required=False,
     218        extra_context=None, context_processors=None):
    152219    """
    153220    Generic object-delete function.
    154221
     
    161228        object
    162229            the original object being deleted
    163230    """
    164     if extra_context is None: extra_context = {}
    165231    if login_required and not request.user.is_authenticated():
    166232        return redirect_to_login(request.path)
    167233
     
    173239        lookup_kwargs['%s__exact' % slug_field] = slug
    174240    else:
    175241        raise AttributeError("Generic delete view must be called with either an object_id or a slug/slug_field")
     242
    176243    try:
    177244        object = model._default_manager.get(**lookup_kwargs)
    178245    except ObjectDoesNotExist:
     
    183250        if request.user.is_authenticated():
    184251            request.user.message_set.create(message=gettext("The %(verbose_name)s was deleted.") % {"verbose_name": model._meta.verbose_name})
    185252        return HttpResponseRedirect(post_delete_redirect)
     253
    186254    else:
     255        # Create template
    187256        if not template_name:
    188             template_name = "%s/%s_confirm_delete.html" % (model._meta.app_label, model._meta.object_name.lower())
     257            template_name = "%s/%s_delete.html" % (model._meta.app_label, model._meta.object_name.lower())
    189258        t = template_loader.get_template(template_name)
     259
     260        # Create context
    190261        c = RequestContext(request, {
    191262            template_object_name: object,
    192263        }, context_processors)
    193         for key, value in extra_context.items():
    194             if callable(value):
    195                 c[key] = value()
    196             else:
    197                 c[key] = value
     264
     265        # Add extra context
     266        if extra_context:
     267            for key, value in extra_context.items():
     268                if callable(value):
     269                    c[key] = value()
     270                else:
     271                    c[key] = value
     272
     273        # Render template and return the response
    198274        response = HttpResponse(t.render(c))
    199275        populate_xheaders(request, response, model, getattr(object, object._meta.pk.attname))
    200276        return response
Back to Top