Ticket #21753: 0001-Allow-generic-editing-views-to-use-form_class-and-fi.patch

File 0001-Allow-generic-editing-views-to-use-form_class-and-fi.patch, 5.5 KB (added by gabejackson, 18 months ago)
  • django/forms/models.py

    From 01d751ae4010c2fac39a3de6ffea0a260cb90251 Mon Sep 17 00:00:00 2001
    From: Gabe Jackson <gabejackson@cxg.ch>
    Date: Thu, 9 Jan 2014 01:51:38 +0100
    Subject: [PATCH] Allow generic editing views to use `form_class` and `fields`
     together
    
    ---
     django/forms/models.py           | 11 ++++++++---
     django/views/generic/edit.py     | 41 ++++++++++++++++++++--------------------
     tests/generic_views/test_edit.py | 11 +++++++++++
     3 files changed, 39 insertions(+), 24 deletions(-)
    
    diff --git a/django/forms/models.py b/django/forms/models.py
    index a849436..8e8a886 100644
    a b class ModelFormMetaclass(DeclarativeFieldsMetaclass): 
    280280                                      opts.widgets, formfield_callback,
    281281                                      opts.localized_fields, opts.labels,
    282282                                      opts.help_texts, opts.error_messages)
    283 
    284283            # make sure opts.fields doesn't specify an invalid field
    285284            none_model_fields = [k for k, v in six.iteritems(fields) if not v]
    286285            missing_fields = (set(none_model_fields) -
    class ModelFormMetaclass(DeclarativeFieldsMetaclass): 
    290289                message = message % (', '.join(missing_fields),
    291290                                     opts.model.__name__)
    292291                raise FieldError(message)
     292           
    293293            # Override default model fields with any custom declared ones
    294             # (plus, include all the other declared fields).
    295             fields.update(new_class.declared_fields)
     294            if opts.fields:
     295                for field_name, field in fields.iteritems():
     296                    if not field or field_name in new_class.declared_fields:
     297                        fields[field_name] = new_class.declared_fields[field_name]
     298                fields.update(fields)
     299            else:
     300                fields.update(new_class.declared_fields)
    296301        else:
    297302            fields = new_class.declared_fields
    298303
  • django/views/generic/edit.py

    diff --git a/django/views/generic/edit.py b/django/views/generic/edit.py
    index 0a8301f..daeeba2 100644
    a b from django.views.generic.base import TemplateResponseMixin, ContextMixin, View 
    88from django.views.generic.detail import (SingleObjectMixin,
    99                        SingleObjectTemplateResponseMixin, BaseDetailView)
    1010
    11 
    1211class FormMixin(ContextMixin):
    1312    """
    1413    A mixin that provides a way to show and handle a form in a request.
    class ModelFormMixin(FormMixin, SingleObjectMixin): 
    9594        """
    9695        Returns the form class to use in this view.
    9796        """
    98         if self.form_class:
    99             return self.form_class
     97        if not self.form_class:
     98            self.form_class = model_forms.ModelForm
     99       
     100        if self.model is not None:
     101            # If a model has been explicitly provided, use it
     102            model = self.model
     103        elif hasattr(self, 'object') and self.object is not None:
     104            # If this view is operating on a single object, use
     105            # the class of that object
     106            model = self.object.__class__
    100107        else:
    101             if self.model is not None:
    102                 # If a model has been explicitly provided, use it
    103                 model = self.model
    104             elif hasattr(self, 'object') and self.object is not None:
    105                 # If this view is operating on a single object, use
    106                 # the class of that object
    107                 model = self.object.__class__
    108             else:
    109                 # Try to get a queryset and extract the model class
    110                 # from that
    111                 model = self.get_queryset().model
    112 
    113             if self.fields is None:
    114                 warnings.warn("Using ModelFormMixin (base class of %s) without "
    115                               "the 'fields' attribute is deprecated." % self.__class__.__name__,
    116                               DeprecationWarning)
    117 
    118             return model_forms.modelform_factory(model, fields=self.fields)
     108            # Try to get a queryset and extract the model class
     109            # from that
     110            model = self.get_queryset().model
     111
     112        if self.fields is None:
     113            warnings.warn("Using ModelFormMixin (base class of %s) without "
     114                            "the 'fields' attribute is deprecated." % self.__class__.__name__,
     115                            DeprecationWarning)
     116
     117        return model_forms.modelform_factory(model, form=self.form_class, fields=self.fields)
    119118
    120119    def get_form_kwargs(self):
    121120        """
  • tests/generic_views/test_edit.py

    diff --git a/tests/generic_views/test_edit.py b/tests/generic_views/test_edit.py
    index be26a14..eac4040 100644
    a b from django.views.generic.edit import FormMixin, CreateView 
    1313
    1414from . import views
    1515from .models import Artist, Author
     16from .test_forms import AuthorForm
    1617
    1718
    1819class FormMixinTests(TestCase):
    class CreateViewTests(TestCase): 
    142143
    143144        self.assertEqual(list(MyCreateView().get_form_class().base_fields),
    144145                         ['name'])
     146   
     147    def test_create_view_with_restricted_fields_and_form_class(self):
     148
     149        class MyCreateView(CreateView):
     150            model = Author
     151            form_class = AuthorForm
     152            fields = ['name']
     153
     154        self.assertEqual(list(MyCreateView().get_form_class().base_fields),
     155                         ['name'])
    145156
    146157    def test_create_view_all_fields(self):
    147158
Back to Top