ModelForm-based create_update generic views

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
from django.template import RequestContext
from django.http import HttpResponseRedirect, Http404
from django.core.exceptions import ObjectDoesNotExist
from django.shortcuts import render_to_response
from django import newforms as forms

def update_object (request, model=None, form_class=None,
                   object_id=None, slug=None, slug_field='slug',
                   template_name=None,
                   pre_save=None, extra_context=None,
                   post_save_redirect=None):
    """
    Generic view to update instances of a model.

    Arguments:

    model: Model type to create

    form_class: ModelForm subclass to use (either this or model must
    be provided)

    object_id: id of object to update (must provide either this or
    slug/slug_field)

    slug: slug of object to update (must provide either this or object_id)

    slug_field: field to look up slug in (defaults to 'slug')
    
    template_name: name of template to use, or list of templates -
    defaults to <app_label>/<model_name>_form.html

    pre_save: callback function to modify object after form data is
    cleaned and applied and before instance save.  Function should
    take request and updated instance as arguments and return modified
    instance ready for save.

    extra_context: dictionary of items and/or callables to add to
    template context.

    post_save_redirect: URL to redirect to after successful object save -
    defaults to instance.get_absolute_url, or "/" if not defined.
    """
    model, form_class = _resolve_model_form(model, form_class)

    lookup_kwargs = {}
    if object_id:
        lookup_kwargs['%s__exact' % model._meta.pk.name] = object_id
    elif slug and slug_field:
        lookup_kwargs['%s__exact' % slug_field] = slug
    else:
        raise AttributeError("update_object view must be called with either an object_id or a slug/slug_field")
    try:
        instance = model.objects.get(**lookup_kwargs)
    except ObjectDoesNotExist:
        raise Http404, "No %s found for %s" % (model._meta.verbose_name, lookup_kwargs)

    return _create_update(request, model, form_class, instance,
                          template_name, pre_save, extra_context,
                          post_save_redirect)

def create_object (request, model=None, form_class=None,
                   template_name=None,
                   pre_save=None, extra_context=None,
                   post_save_redirect=None):
    """
    Generic view to create instances of a model.

    Arguments:

    model: Model type to create

    form_class: ModelForm subclass to use (either this or model must
    be provided)

    template_name: name of template to use, or list of templates -
    defaults to <app_label>/<model_name>_form.html

    pre_save: callback function to modify object after form data is
    cleaned and applied and before instance save.  Function should
    take request and instance as arguments and return modified
    instance ready for save.

    extra_context: dictionary of items and/or callables to add to
    template context.

    post_save_redirect: URL to redirect to after successful object save -
    defaults to instance.get_absolute_url, or "/" if not defined.
    """
    model, form_class = _resolve_model_form(model, form_class)

    return _create_update(request, model, form_class, None,
                          template_name, pre_save, extra_context,
                          post_save_redirect)


def _resolve_model_form (_model=None, form_class=None):
    if _model is None:
        try:
            _model = form_class._meta.model
        except AttributeError:
            raise AttributeError("create_object view requires either model or form_class (ModelForm subclass)")

    if form_class is None:
        class TempForm (forms.ModelForm):
            class Meta:
                model = _model
        form_class = TempForm
    return (_model, form_class)
    
def _create_update (request, model, form_class, instance,
                   template_name, pre_save, extra_context,
                   post_save_redirect):
    extra_context = extra_context or {}

    template_name = template_name or "%s/%s_form.html" % (
        model._meta.app_label, model._meta.object_name.lower())

    if request.method is 'POST':
        form = form_class(request.POST, instance=instance)
        if not form.errors:
            obj = form.save(commit=False)
            if callable(pre_save):
                obj = pre_save(request, obj)
            obj.save()
            if post_save_redirect is None:
                if hasattr(obj, 'get_absolute_url'):
                    post_save_redirect = obj.get_absolute_url()
                else:
                    post_save_redirect = "/"
            return HttpResponseRedirect(post_save_redirect)
    else:
        form = form_class(instance=instance)
        
    c = {}
    for key, value in extra_context.items():
        if callable(value):
            c[key] = value()
        else:
            c[key] = value
    c['form'] = form

    return render_to_response(template_name, c,
                              RequestContext(request))

More like this

  1. create_update for newforms (ModelForm) by Rozza 6 years, 1 month ago
  2. object-oriented generic views by carljm 5 years, 7 months ago
  3. Allow any view (probably a generic view) to accept POST variables into extra_context by orblivion 3 years, 5 months ago
  4. Allow any view (probably a generic view) to accept captured URL variables into extra_context. by orblivion 3 years, 5 months ago
  5. create_object and update_object for newforms by danjak 7 years, 1 month ago

Comments

carljm (on July 18, 2008):

And... it was checked in to trunk today. Never mind this snippet.

#

(Forgotten your password?)