Django

Code

Show
Ignore:
Timestamp:
07/18/08 16:42:08 (4 months ago)
Author:
brosner
Message:

newforms-admin: Merged from trunk up to [7952].

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • django/branches/newforms-admin

    • Property svnmerge-integrated changed from /django/trunk:1-4345,4350-4357,4359-4365,4371-4372,4374-4377,4380-4386,4388,4390-4391,4400-4402,4404-4408,4410,4412-4419,4426-4427,4430-4432,4434,4441,4443-4444,4446-4447,4450,4452-4453,4455-4458,4476,4503,4546,4564-4569,4580-4586,4617,4630,4641-6390,6392-7950 to /django/trunk:1-4345,4350-4357,4359-4365,4371-4372,4374-4377,4380-4386,4388,4390-4391,4400-4402,4404-4408,4410,4412-4419,4426-4427,4430-4432,4434,4441,4443-4444,4446-4447,4450,4452-4453,4455-4458,4476,4503,4546,4564-4569,4580-4586,4617,4630,4641-6390,6392-7953
  • django/branches/newforms-admin/django/views/generic/create_update.py

    r5918 r7954  
     1from django.newforms.models import ModelFormMetaclass, ModelForm 
     2from django.template import RequestContext, loader 
     3from django.http import Http404, HttpResponse, HttpResponseRedirect 
    14from django.core.xheaders import populate_xheaders 
    2 from django.template import loader 
    3 from django import oldforms 
    4 from django.db.models import FileField 
    5 from django.contrib.auth.views import redirect_to_login 
    6 from django.template import RequestContext 
    7 from django.http import Http404, HttpResponse, HttpResponseRedirect 
    85from django.core.exceptions import ObjectDoesNotExist, ImproperlyConfigured 
    96from django.utils.translation import ugettext 
    10  
    11 def create_object(request, model, template_name=None, 
     7from django.contrib.auth.views import redirect_to_login 
     8from django.views.generic import GenericViewError 
     9 
     10def deprecate_follow(follow): 
     11    """ 
     12    Issues a DeprecationWarning if follow is anything but None. 
     13 
     14    The old Manipulator-based forms used a follow argument that is no longer 
     15    needed for newforms-based forms. 
     16    """ 
     17    if follow is not None: 
     18        import warning 
     19        msg = ("Generic views have been changed to use newforms, and the" 
     20               "'follow' argument is no longer used.  Please update your code" 
     21               "to not use the 'follow' argument.") 
     22        warning.warn(msg, DeprecationWarning, stacklevel=3) 
     23 
     24def apply_extra_context(extra_context, context): 
     25    """ 
     26    Adds items from extra_context dict to context.  If a value in extra_context 
     27    is callable, then it is called and the result is added to context. 
     28    """ 
     29    for key, value in extra_context.iteritems(): 
     30        if callable(value): 
     31            context[key] = value() 
     32        else: 
     33            context[key] = value 
     34 
     35def get_model_and_form_class(model, form_class): 
     36    """ 
     37    Returns a model and form class based on the model and form_class 
     38    parameters that were passed to the generic view. 
     39 
     40    If ``form_class`` is given then its associated model will be returned along 
     41    with ``form_class`` itself.  Otherwise, if ``model`` is given, ``model`` 
     42    itself will be returned along with a ``ModelForm`` class created from 
     43    ``model``. 
     44    """ 
     45    if form_class: 
     46        return form_class._meta.model, form_class 
     47    if model: 
     48        # The inner Meta class fails if model = model is used for some reason. 
     49        tmp_model = model 
     50        # TODO: we should be able to construct a ModelForm without creating 
     51        # and passing in a temporary inner class. 
     52        class Meta: 
     53            model = tmp_model 
     54        class_name = model.__name__ + 'Form' 
     55        form_class = ModelFormMetaclass(class_name, (ModelForm,), {'Meta': Meta}) 
     56        return model, form_class 
     57    raise GenericViewError("Generic view must be called with either a model or" 
     58                           " form_class argument.") 
     59 
     60def redirect(post_save_redirect, obj): 
     61    """ 
     62    Returns a HttpResponseRedirect to ``post_save_redirect``. 
     63 
     64    ``post_save_redirect`` should be a string, and can contain named string- 
     65    substitution place holders of ``obj`` field names. 
     66 
     67    If ``post_save_redirect`` is None, then redirect to ``obj``'s URL returned 
     68    by ``get_absolute_url()``.  If ``obj`` has no ``get_absolute_url`` method, 
     69    then raise ImproperlyConfigured. 
     70 
     71    This method is meant to handle the post_save_redirect parameter to the 
     72    ``create_object`` and ``update_object`` views. 
     73    """ 
     74    if post_save_redirect: 
     75        return HttpResponseRedirect(post_save_redirect % obj.__dict__) 
     76    elif hasattr(obj, 'get_absolute_url'): 
     77        return HttpResponseRedirect(obj.get_absolute_url()) 
     78    else: 
     79        raise ImproperlyConfigured( 
     80            "No URL to redirect to.  Either pass a post_save_redirect" 
     81            " parameter to the generic view or define a get_absolute_url" 
     82            " method on the Model.") 
     83 
     84def lookup_object(model, object_id, slug, slug_field): 
     85    """ 
     86    Return the ``model`` object with the passed ``object_id``.  If 
     87    ``object_id`` is None, then return the the object whose ``slug_field`` 
     88    equals the passed ``slug``.  If ``slug`` and ``slug_field`` are not passed, 
     89    then raise Http404 exception. 
     90    """ 
     91    lookup_kwargs = {} 
     92    if object_id: 
     93        lookup_kwargs['%s__exact' % model._meta.pk.name] = object_id 
     94    elif slug and slug_field: 
     95        lookup_kwargs['%s__exact' % slug_field] = slug 
     96    else: 
     97        raise GenericViewError( 
     98            "Generic view must be called with either an object_id or a" 
     99            " slug/slug_field.") 
     100    try: 
     101        return model.objects.get(**lookup_kwargs) 
     102    except ObjectDoesNotExist: 
     103        raise Http404("No %s found for %s" 
     104                      % (model._meta.verbose_name, lookup_kwargs)) 
     105 
     106def create_object(request, model=None, template_name=None, 
    12107        template_loader=loader, extra_context=None, post_save_redirect=None, 
    13         login_required=False, follow=None, context_processors=None): 
     108        login_required=False, follow=None, context_processors=None, 
     109        form_class=None): 
    14110    """ 
    15111    Generic object-creation function. 
     
    18114    Context: 
    19115        form 
    20             the form wrapper for the object 
    21     """ 
     116            the form for the object 
     117    """ 
     118    deprecate_follow(follow) 
    22119    if extra_context is None: extra_context = {} 
    23120    if login_required and not request.user.is_authenticated(): 
    24121        return redirect_to_login(request.path) 
    25122 
    26     manipulator = model.AddManipulator(follow=follow) 
    27     if request.POST: 
    28         # If data was POSTed, we're trying to create a new object 
    29         new_data = request.POST.copy() 
    30  
    31         if model._meta.has_field_type(FileField): 
    32             new_data.update(request.FILES) 
    33  
    34         # Check for errors 
    35         errors = manipulator.get_validation_errors(new_data) 
    36         manipulator.do_html2python(new_data) 
    37  
    38         if not errors: 
    39             # No errors -- this means we can save the data! 
    40             new_object = manipulator.save(new_data) 
    41  
     123    model, form_class = get_model_and_form_class(model, form_class) 
     124    if request.method == 'POST': 
     125        form = form_class(request.POST, request.FILES) 
     126        if form.is_valid(): 
     127            new_object = form.save() 
    42128            if request.user.is_authenticated(): 
    43129                request.user.message_set.create(message=ugettext("The %(verbose_name)s was created successfully.") % {"verbose_name": model._meta.verbose_name}) 
    44  
    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() 
    57  
    58     # Create the FormWrapper, template, context, response 
    59     form = oldforms.FormWrapper(manipulator, new_data, errors) 
     130            return redirect(post_save_redirect, new_object) 
     131    else: 
     132        form = form_class() 
     133 
     134    # Create the template, context, response 
    60135    if not template_name: 
    61136        template_name = "%s/%s_form.html" % (model._meta.app_label, model._meta.object_name.lower()) 
     
    64139        'form': form, 
    65140    }, context_processors) 
    66     for key, value in extra_context.items(): 
    67         if callable(value): 
    68             c[key] = value() 
    69         else: 
    70             c[key] = value 
     141    apply_extra_context(extra_context, c) 
    71142    return HttpResponse(t.render(c)) 
    72143 
    73 def update_object(request, model, object_id=None, slug=None, 
     144def update_object(request, model=None, object_id=None, slug=None, 
    74145        slug_field='slug', template_name=None, template_loader=loader, 
    75146        extra_context=None, post_save_redirect=None, 
    76147        login_required=False, follow=None, context_processors=None, 
    77         template_object_name='object'): 
     148        template_object_name='object', form_class=None): 
    78149    """ 
    79150    Generic object-update function. 
     
    82153    Context: 
    83154        form 
    84             the form wrapper for the object 
     155            the form for the object 
    85156        object 
    86157            the original object being edited 
    87158    """ 
     159    deprecate_follow(follow) 
    88160    if extra_context is None: extra_context = {} 
    89161    if login_required and not request.user.is_authenticated(): 
    90162        return redirect_to_login(request.path) 
    91163 
    92     # Look up the object to be edited 
    93     lookup_kwargs = {} 
    94     if object_id: 
    95         lookup_kwargs['%s__exact' % model._meta.pk.name] = object_id 
    96     elif slug and slug_field: 
    97         lookup_kwargs['%s__exact' % slug_field] = slug 
    98     else: 
    99         raise AttributeError("Generic edit view must be called with either an object_id or a slug/slug_field") 
    100     try: 
    101         object = model.objects.get(**lookup_kwargs) 
    102     except ObjectDoesNotExist: 
    103         raise Http404, "No %s found for %s" % (model._meta.verbose_name, lookup_kwargs) 
    104  
    105     manipulator = model.ChangeManipulator(getattr(object, object._meta.pk.attname), follow=follow) 
    106  
    107     if request.POST: 
    108         new_data = request.POST.copy() 
    109         if model._meta.has_field_type(FileField): 
    110             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) 
    115  
     164    model, form_class = get_model_and_form_class(model, form_class) 
     165    obj = lookup_object(model, object_id, slug, slug_field) 
     166 
     167    if request.method == 'POST': 
     168        form = form_class(request.POST, request.FILES, instance=obj) 
     169        if form.is_valid(): 
     170            obj = form.save() 
    116171            if request.user.is_authenticated(): 
    117172                request.user.message_set.create(message=ugettext("The %(verbose_name)s was updated successfully.") % {"verbose_name": model._meta.verbose_name}) 
    118  
    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.") 
    126     else: 
    127         errors = {} 
    128         # This makes sure the form acurate represents the fields of the place. 
    129         new_data = manipulator.flatten_data() 
    130  
    131     form = oldforms.FormWrapper(manipulator, new_data, errors) 
     173            return redirect(post_save_redirect, obj) 
     174    else: 
     175        form = form_class(instance=obj) 
     176 
    132177    if not template_name: 
    133178        template_name = "%s/%s_form.html" % (model._meta.app_label, model._meta.object_name.lower()) 
     
    135180    c = RequestContext(request, { 
    136181        'form': form, 
    137         template_object_name: object
     182        template_object_name: obj
    138183    }, context_processors) 
    139     for key, value in extra_context.items(): 
    140         if callable(value): 
    141             c[key] = value() 
    142         else: 
    143             c[key] = value 
     184    apply_extra_context(extra_context, c) 
    144185    response = HttpResponse(t.render(c)) 
    145     populate_xheaders(request, response, model, getattr(object, object._meta.pk.attname)) 
     186    populate_xheaders(request, response, model, getattr(obj, obj._meta.pk.attname)) 
    146187    return response 
    147188 
    148 def delete_object(request, model, post_delete_redirect, 
    149         object_id=None, slug=None, slug_field='slug', template_name=None, 
    150         template_loader=loader, extra_context=None, 
    151         login_required=False, context_processors=None, template_object_name='object'): 
     189def delete_object(request, model, post_delete_redirect, object_id=None, 
     190        slug=None, slug_field='slug', template_name=None, 
     191        template_loader=loader, extra_context=None, login_required=False, 
     192        context_processors=None, template_object_name='object'): 
    152193    """ 
    153194    Generic object-delete function. 
     
    166207        return redirect_to_login(request.path) 
    167208 
    168     # Look up the object to be edited 
    169     lookup_kwargs = {} 
    170     if object_id: 
    171         lookup_kwargs['%s__exact' % model._meta.pk.name] = object_id 
    172     elif slug and slug_field: 
    173         lookup_kwargs['%s__exact' % slug_field] = slug 
    174     else: 
    175         raise AttributeError("Generic delete view must be called with either an object_id or a slug/slug_field") 
    176     try: 
    177         object = model._default_manager.get(**lookup_kwargs) 
    178     except ObjectDoesNotExist: 
    179         raise Http404, "No %s found for %s" % (model._meta.app_label, lookup_kwargs) 
     209    obj = lookup_object(model, object_id, slug, slug_field) 
    180210 
    181211    if request.method == 'POST': 
    182         object.delete() 
     212        obj.delete() 
    183213        if request.user.is_authenticated(): 
    184214            request.user.message_set.create(message=ugettext("The %(verbose_name)s was deleted.") % {"verbose_name": model._meta.verbose_name}) 
     
    189219        t = template_loader.get_template(template_name) 
    190220        c = RequestContext(request, { 
    191             template_object_name: object
     221            template_object_name: obj
    192222        }, context_processors) 
    193         for key, value in extra_context.items(): 
    194             if callable(value): 
    195                 c[key] = value() 
    196             else: 
    197                 c[key] = value 
     223        apply_extra_context(extra_context, c) 
    198224        response = HttpResponse(t.render(c)) 
    199         populate_xheaders(request, response, model, getattr(object, object._meta.pk.attname)) 
     225        populate_xheaders(request, response, model, getattr(obj, obj._meta.pk.attname)) 
    200226        return response 
  • django/branches/newforms-admin/django/views/generic/__init__.py

    r4265 r7954  
     1class GenericViewError(Exception): 
     2    """A problem in a generic view.""" 
     3    pass