Ticket #14470: modeladmin.diff

File modeladmin.diff, 74.0 KB (added by Preston Timmons, 14 years ago)
  • tests/regressiontests/modeladmin/models.py

    diff --git a/tests/regressiontests/modeladmin/models.py b/tests/regressiontests/modeladmin/models.py
    index 36ea416..20dfe2c 100644
    a b class ValidationTestModel(models.Model):  
    3434
    3535class ValidationTestInlineModel(models.Model):
    3636    parent = models.ForeignKey(ValidationTestModel)
    37 
    38 __test__ = {'API_TESTS': """
    39 
    40 >>> from django.contrib.admin.options import ModelAdmin, TabularInline, HORIZONTAL, VERTICAL
    41 >>> from django.contrib.admin.sites import AdminSite
    42 
    43 None of the following tests really depend on the content of the request, so
    44 we'll just pass in None.
    45 
    46 >>> request = None
    47 
    48 # the sign_date is not 100 percent accurate ;)
    49 >>> band = Band(name='The Doors', bio='', sign_date=date(1965, 1, 1))
    50 >>> band.save()
    51 
    52 Under the covers, the admin system will initialize ModelAdmin with a Model
    53 class and an AdminSite instance, so let's just go ahead and do that manually
    54 for testing.
    55 
    56 >>> site = AdminSite()
    57 >>> ma = ModelAdmin(Band, site)
    58 
    59 >>> ma.get_form(request).base_fields.keys()
    60 ['name', 'bio', 'sign_date']
    61 
    62 
    63 # form/fields/fieldsets interaction ##########################################
    64 
    65 fieldsets_add and fieldsets_change should return a special data structure that
    66 is used in the templates. They should generate the "right thing" whether we
    67 have specified a custom form, the fields arugment, or nothing at all.
    68 
    69 Here's the default case. There are no custom form_add/form_change methods,
    70 no fields argument, and no fieldsets argument.
    71 
    72 >>> ma = ModelAdmin(Band, site)
    73 >>> ma.get_fieldsets(request)
    74 [(None, {'fields': ['name', 'bio', 'sign_date']})]
    75 >>> ma.get_fieldsets(request, band)
    76 [(None, {'fields': ['name', 'bio', 'sign_date']})]
    77 
    78 
    79 If we specify the fields argument, fieldsets_add and fielsets_change should
    80 just stick the fields into a formsets structure and return it.
    81 
    82 >>> class BandAdmin(ModelAdmin):
    83 ...     fields = ['name']
    84 
    85 >>> ma = BandAdmin(Band, site)
    86 >>> ma.get_fieldsets(request)
    87 [(None, {'fields': ['name']})]
    88 >>> ma.get_fieldsets(request, band)
    89 [(None, {'fields': ['name']})]
    90 
    91 
    92 
    93 
    94 If we specify fields or fieldsets, it should exclude fields on the Form class
    95 to the fields specified. This may cause errors to be raised in the db layer if
    96 required model fields arent in fields/fieldsets, but that's preferable to
    97 ghost errors where you have a field in your Form class that isn't being
    98 displayed because you forgot to add it to fields/fielsets
    99 
    100 >>> class BandAdmin(ModelAdmin):
    101 ...     fields = ['name']
    102 
    103 >>> ma = BandAdmin(Band, site)
    104 >>> ma.get_form(request).base_fields.keys()
    105 ['name']
    106 >>> ma.get_form(request, band).base_fields.keys()
    107 ['name']
    108 
    109 >>> class BandAdmin(ModelAdmin):
    110 ...     fieldsets = [(None, {'fields': ['name']})]
    111 
    112 >>> ma = BandAdmin(Band, site)
    113 >>> ma.get_form(request).base_fields.keys()
    114 ['name']
    115 >>> ma.get_form(request, band).base_fields.keys()
    116 ['name']
    117 
    118 
    119 # Using `exclude`.
    120 
    121 >>> class BandAdmin(ModelAdmin):
    122 ...     exclude = ['bio']
    123 >>> ma = BandAdmin(Band, site)
    124 >>> ma.get_form(request).base_fields.keys()
    125 ['name', 'sign_date']
    126 
    127 # You can also pass a tuple to `exclude`.
    128  
    129 >>> class BandAdmin(ModelAdmin):
    130 ...     exclude = ('bio',)
    131 >>> ma = BandAdmin(Band, site)
    132 >>> ma.get_form(request).base_fields.keys()
    133 ['name', 'sign_date']
    134  
    135 # Using `fields` and `exclude`.
    136 
    137 >>> class BandAdmin(ModelAdmin):
    138 ...     fields = ['name', 'bio']
    139 ...     exclude = ['bio']
    140 >>> ma = BandAdmin(Band, site)
    141 >>> ma.get_form(request).base_fields.keys()
    142 ['name']
    143 
    144 If we specify a form, it should use it allowing custom validation to work
    145 properly. This won't, however, break any of the admin widgets or media.
    146 
    147 >>> from django import forms
    148 >>> class AdminBandForm(forms.ModelForm):
    149 ...     delete = forms.BooleanField()
    150 ...     
    151 ...     class Meta:
    152 ...         model = Band
    153 
    154 >>> class BandAdmin(ModelAdmin):
    155 ...     form = AdminBandForm
    156 
    157 >>> ma = BandAdmin(Band, site)
    158 >>> ma.get_form(request).base_fields.keys()
    159 ['name', 'bio', 'sign_date', 'delete']
    160 >>> type(ma.get_form(request).base_fields['sign_date'].widget)
    161 <class 'django.contrib.admin.widgets.AdminDateWidget'>
    162 
    163 If we need to override the queryset of a ModelChoiceField in our custom form
    164 make sure that RelatedFieldWidgetWrapper doesn't mess that up.
    165 
    166 >>> band2 = Band(name='The Beetles', bio='', sign_date=date(1962, 1, 1))
    167 >>> band2.save()
    168 
    169 >>> class AdminConcertForm(forms.ModelForm):
    170 ...     class Meta:
    171 ...         model = Concert
    172 ...
    173 ...     def __init__(self, *args, **kwargs):
    174 ...         super(AdminConcertForm, self).__init__(*args, **kwargs)
    175 ...         self.fields["main_band"].queryset = Band.objects.filter(name='The Doors')
    176 
    177 >>> class ConcertAdmin(ModelAdmin):
    178 ...     form = AdminConcertForm
    179 
    180 >>> ma = ConcertAdmin(Concert, site)
    181 >>> form = ma.get_form(request)()
    182 >>> print form["main_band"]
    183 <select name="main_band" id="id_main_band">
    184 <option value="" selected="selected">---------</option>
    185 <option value="1">The Doors</option>
    186 </select>
    187 
    188 >>> band2.delete()
    189 
    190 # radio_fields behavior ################################################
    191 
    192 First, without any radio_fields specified, the widgets for ForeignKey
    193 and fields with choices specified ought to be a basic Select widget.
    194 ForeignKey widgets in the admin are wrapped with RelatedFieldWidgetWrapper so
    195 they need to be handled properly when type checking. For Select fields, all of
    196 the choices lists have a first entry of dashes.
    197 
    198 >>> cma = ModelAdmin(Concert, site)
    199 >>> cmafa = cma.get_form(request)
    200 
    201 >>> type(cmafa.base_fields['main_band'].widget.widget)
    202 <class 'django.forms.widgets.Select'>
    203 >>> list(cmafa.base_fields['main_band'].widget.choices)
    204 [(u'', u'---------'), (1, u'The Doors')]
    205 
    206 >>> type(cmafa.base_fields['opening_band'].widget.widget)
    207 <class 'django.forms.widgets.Select'>
    208 >>> list(cmafa.base_fields['opening_band'].widget.choices)
    209 [(u'', u'---------'), (1, u'The Doors')]
    210 
    211 >>> type(cmafa.base_fields['day'].widget)
    212 <class 'django.forms.widgets.Select'>
    213 >>> list(cmafa.base_fields['day'].widget.choices)
    214 [('', '---------'), (1, 'Fri'), (2, 'Sat')]
    215 
    216 >>> type(cmafa.base_fields['transport'].widget)
    217 <class 'django.forms.widgets.Select'>
    218 >>> list(cmafa.base_fields['transport'].widget.choices)
    219 [('', '---------'), (1, 'Plane'), (2, 'Train'), (3, 'Bus')]
    220 
    221 Now specify all the fields as radio_fields.  Widgets should now be
    222 RadioSelect, and the choices list should have a first entry of 'None' if
    223 blank=True for the model field.  Finally, the widget should have the
    224 'radiolist' attr, and 'inline' as well if the field is specified HORIZONTAL.
    225 
    226 >>> class ConcertAdmin(ModelAdmin):
    227 ...     radio_fields = {
    228 ...         'main_band': HORIZONTAL,
    229 ...         'opening_band': VERTICAL,
    230 ...         'day': VERTICAL,
    231 ...         'transport': HORIZONTAL,
    232 ...     }
    233 
    234 >>> cma = ConcertAdmin(Concert, site)
    235 >>> cmafa = cma.get_form(request)
    236 
    237 >>> type(cmafa.base_fields['main_band'].widget.widget)
    238 <class 'django.contrib.admin.widgets.AdminRadioSelect'>
    239 >>> cmafa.base_fields['main_band'].widget.attrs
    240 {'class': 'radiolist inline'}
    241 >>> list(cmafa.base_fields['main_band'].widget.choices)
    242 [(1, u'The Doors')]
    243 
    244 >>> type(cmafa.base_fields['opening_band'].widget.widget)
    245 <class 'django.contrib.admin.widgets.AdminRadioSelect'>
    246 >>> cmafa.base_fields['opening_band'].widget.attrs
    247 {'class': 'radiolist'}
    248 >>> list(cmafa.base_fields['opening_band'].widget.choices)
    249 [(u'', u'None'), (1, u'The Doors')]
    250 
    251 >>> type(cmafa.base_fields['day'].widget)
    252 <class 'django.contrib.admin.widgets.AdminRadioSelect'>
    253 >>> cmafa.base_fields['day'].widget.attrs
    254 {'class': 'radiolist'}
    255 >>> list(cmafa.base_fields['day'].widget.choices)
    256 [(1, 'Fri'), (2, 'Sat')]
    257 
    258 >>> type(cmafa.base_fields['transport'].widget)
    259 <class 'django.contrib.admin.widgets.AdminRadioSelect'>
    260 >>> cmafa.base_fields['transport'].widget.attrs
    261 {'class': 'radiolist inline'}
    262 >>> list(cmafa.base_fields['transport'].widget.choices)
    263 [('', u'None'), (1, 'Plane'), (2, 'Train'), (3, 'Bus')]
    264 
    265 >>> class AdminConcertForm(forms.ModelForm):
    266 ...     class Meta:
    267 ...         model = Concert
    268 ...         exclude = ('transport',)
    269 
    270 >>> class ConcertAdmin(ModelAdmin):
    271 ...     form = AdminConcertForm
    272 
    273 >>> ma = ConcertAdmin(Concert, site)
    274 >>> ma.get_form(request).base_fields.keys()
    275 ['main_band', 'opening_band', 'day']
    276 
    277 >>> class AdminConcertForm(forms.ModelForm):
    278 ...     extra = forms.CharField()
    279 ...     class Meta:
    280 ...         model = Concert
    281 ...         fields = ['extra', 'transport']
    282 
    283 >>> class ConcertAdmin(ModelAdmin):
    284 ...     form = AdminConcertForm
    285 
    286 >>> ma = ConcertAdmin(Concert, site)
    287 >>> ma.get_form(request).base_fields.keys()
    288 ['extra', 'transport']
    289 
    290 >>> class ConcertInline(TabularInline):
    291 ...     form = AdminConcertForm
    292 ...     model = Concert
    293 ...     fk_name = 'main_band'
    294 ...     can_delete = True
    295 
    296 >>> class BandAdmin(ModelAdmin):
    297 ...     inlines = [
    298 ...         ConcertInline
    299 ...     ]
    300 
    301 >>> ma = BandAdmin(Band, site)
    302 >>> list(ma.get_formsets(request))[0]().forms[0].fields.keys()
    303 ['extra', 'transport', 'id', 'DELETE', 'main_band']
    304 
    305 
    306 >>> band.delete()
    307 
    308 # ModelAdmin Option Validation ################################################
    309 
    310 >>> from django.contrib.admin.validation import validate
    311 >>> from django.conf import settings
    312 
    313 # Ensure validation only runs when DEBUG = True
    314 
    315 >>> settings.DEBUG = True
    316 
    317 >>> class ValidationTestModelAdmin(ModelAdmin):
    318 ...     raw_id_fields = 10
    319 >>> site = AdminSite()
    320 >>> site.register(ValidationTestModel, ValidationTestModelAdmin)
    321 Traceback (most recent call last):
    322 ...
    323 ImproperlyConfigured: 'ValidationTestModelAdmin.raw_id_fields' must be a list or tuple.
    324 
    325 >>> settings.DEBUG = False
    326 
    327 >>> class ValidationTestModelAdmin(ModelAdmin):
    328 ...     raw_id_fields = 10
    329 >>> site = AdminSite()
    330 >>> site.register(ValidationTestModel, ValidationTestModelAdmin)
    331 
    332 # raw_id_fields
    333 
    334 >>> class ValidationTestModelAdmin(ModelAdmin):
    335 ...     raw_id_fields = 10
    336 >>> validate(ValidationTestModelAdmin, ValidationTestModel)
    337 Traceback (most recent call last):
    338 ...
    339 ImproperlyConfigured: 'ValidationTestModelAdmin.raw_id_fields' must be a list or tuple.
    340 
    341 >>> class ValidationTestModelAdmin(ModelAdmin):
    342 ...     raw_id_fields = ('non_existent_field',)
    343 >>> validate(ValidationTestModelAdmin, ValidationTestModel)
    344 Traceback (most recent call last):
    345 ...
    346 ImproperlyConfigured: 'ValidationTestModelAdmin.raw_id_fields' refers to field 'non_existent_field' that is missing from model 'ValidationTestModel'.
    347 
    348 >>> class ValidationTestModelAdmin(ModelAdmin):
    349 ...     raw_id_fields = ('name',)
    350 >>> validate(ValidationTestModelAdmin, ValidationTestModel)
    351 Traceback (most recent call last):
    352 ...
    353 ImproperlyConfigured: 'ValidationTestModelAdmin.raw_id_fields[0]', 'name' must be either a ForeignKey or ManyToManyField.
    354 
    355 >>> class ValidationTestModelAdmin(ModelAdmin):
    356 ...     raw_id_fields = ('users',)
    357 >>> validate(ValidationTestModelAdmin, ValidationTestModel)
    358 
    359 # fieldsets
    360 
    361 >>> class ValidationTestModelAdmin(ModelAdmin):
    362 ...     fieldsets = 10
    363 >>> validate(ValidationTestModelAdmin, ValidationTestModel)
    364 Traceback (most recent call last):
    365 ...
    366 ImproperlyConfigured: 'ValidationTestModelAdmin.fieldsets' must be a list or tuple.
    367 
    368 >>> class ValidationTestModelAdmin(ModelAdmin):
    369 ...     fieldsets = ({},)
    370 >>> validate(ValidationTestModelAdmin, ValidationTestModel)
    371 Traceback (most recent call last):
    372 ...
    373 ImproperlyConfigured: 'ValidationTestModelAdmin.fieldsets[0]' must be a list or tuple.
    374 
    375 >>> class ValidationTestModelAdmin(ModelAdmin):
    376 ...     fieldsets = ((),)
    377 >>> validate(ValidationTestModelAdmin, ValidationTestModel)
    378 Traceback (most recent call last):
    379 ...
    380 ImproperlyConfigured: 'ValidationTestModelAdmin.fieldsets[0]' does not have exactly two elements.
    381 
    382 >>> class ValidationTestModelAdmin(ModelAdmin):
    383 ...     fieldsets = (("General", ()),)
    384 >>> validate(ValidationTestModelAdmin, ValidationTestModel)
    385 Traceback (most recent call last):
    386 ...
    387 ImproperlyConfigured: 'ValidationTestModelAdmin.fieldsets[0][1]' must be a dictionary.
    388 
    389 >>> class ValidationTestModelAdmin(ModelAdmin):
    390 ...     fieldsets = (("General", {}),)
    391 >>> validate(ValidationTestModelAdmin, ValidationTestModel)
    392 Traceback (most recent call last):
    393 ...
    394 ImproperlyConfigured: 'fields' key is required in ValidationTestModelAdmin.fieldsets[0][1] field options dict.
    395 
    396 >>> class ValidationTestModelAdmin(ModelAdmin):
    397 ...     fieldsets = (("General", {"fields": ("non_existent_field",)}),)
    398 >>> validate(ValidationTestModelAdmin, ValidationTestModel)
    399 Traceback (most recent call last):
    400 ...
    401 ImproperlyConfigured: 'ValidationTestModelAdmin.fieldsets[0][1]['fields']' refers to field 'non_existent_field' that is missing from the form.
    402 
    403 >>> class ValidationTestModelAdmin(ModelAdmin):
    404 ...     fieldsets = (("General", {"fields": ("name",)}),)
    405 >>> validate(ValidationTestModelAdmin, ValidationTestModel)
    406 
    407 >>> class ValidationTestModelAdmin(ModelAdmin):
    408 ...     fieldsets = (("General", {"fields": ("name",)}),)
    409 ...     fields = ["name",]
    410 >>> validate(ValidationTestModelAdmin, ValidationTestModel)
    411 Traceback (most recent call last):
    412 ...
    413 ImproperlyConfigured: Both fieldsets and fields are specified in ValidationTestModelAdmin.
    414 
    415 >>> class ValidationTestModelAdmin(ModelAdmin):
    416 ...     fieldsets = [(None, {'fields': ['name', 'name']})]
    417 >>> validate(ValidationTestModelAdmin, ValidationTestModel)
    418 Traceback (most recent call last):
    419 ...
    420 ImproperlyConfigured: There are duplicate field(s) in ValidationTestModelAdmin.fieldsets
    421 
    422 >>> class ValidationTestModelAdmin(ModelAdmin):
    423 ...     fields = ["name", "name"]
    424 >>> validate(ValidationTestModelAdmin, ValidationTestModel)
    425 Traceback (most recent call last):
    426 ...
    427 ImproperlyConfigured: There are duplicate field(s) in ValidationTestModelAdmin.fields
    428 
    429 # form
    430 
    431 >>> class FakeForm(object):
    432 ...     pass
    433 >>> class ValidationTestModelAdmin(ModelAdmin):
    434 ...     form = FakeForm
    435 >>> validate(ValidationTestModelAdmin, ValidationTestModel)
    436 Traceback (most recent call last):
    437 ...
    438 ImproperlyConfigured: ValidationTestModelAdmin.form does not inherit from BaseModelForm.
    439 
    440 # fielsets with custom form
    441 
    442 >>> class BandAdmin(ModelAdmin):
    443 ...     fieldsets = (
    444 ...         ('Band', {
    445 ...             'fields': ('non_existent_field',)
    446 ...         }),
    447 ...     )
    448 >>> validate(BandAdmin, Band)
    449 Traceback (most recent call last):
    450 ...
    451 ImproperlyConfigured: 'BandAdmin.fieldsets[0][1]['fields']' refers to field 'non_existent_field' that is missing from the form.
    452 
    453 >>> class BandAdmin(ModelAdmin):
    454 ...     fieldsets = (
    455 ...         ('Band', {
    456 ...             'fields': ('name',)
    457 ...         }),
    458 ...     )
    459 >>> validate(BandAdmin, Band)
    460 
    461 >>> class AdminBandForm(forms.ModelForm):
    462 ...     class Meta:
    463 ...         model = Band
    464 >>> class BandAdmin(ModelAdmin):
    465 ...     form = AdminBandForm
    466 ...
    467 ...     fieldsets = (
    468 ...         ('Band', {
    469 ...             'fields': ('non_existent_field',)
    470 ...         }),
    471 ...     )
    472 >>> validate(BandAdmin, Band)
    473 Traceback (most recent call last):
    474 ...
    475 ImproperlyConfigured: 'BandAdmin.fieldsets[0][1]['fields']' refers to field 'non_existent_field' that is missing from the form.
    476 
    477 >>> class AdminBandForm(forms.ModelForm):
    478 ...     delete = forms.BooleanField()
    479 ...
    480 ...     class Meta:
    481 ...         model = Band
    482 >>> class BandAdmin(ModelAdmin):
    483 ...     form = AdminBandForm
    484 ...
    485 ...     fieldsets = (
    486 ...         ('Band', {
    487 ...             'fields': ('name', 'bio', 'sign_date', 'delete')
    488 ...         }),
    489 ...     )
    490 >>> validate(BandAdmin, Band)
    491 
    492 # filter_vertical
    493 
    494 >>> class ValidationTestModelAdmin(ModelAdmin):
    495 ...     filter_vertical = 10
    496 >>> validate(ValidationTestModelAdmin, ValidationTestModel)
    497 Traceback (most recent call last):
    498 ...
    499 ImproperlyConfigured: 'ValidationTestModelAdmin.filter_vertical' must be a list or tuple.
    500 
    501 >>> class ValidationTestModelAdmin(ModelAdmin):
    502 ...     filter_vertical = ("non_existent_field",)
    503 >>> validate(ValidationTestModelAdmin, ValidationTestModel)
    504 Traceback (most recent call last):
    505 ...
    506 ImproperlyConfigured: 'ValidationTestModelAdmin.filter_vertical' refers to field 'non_existent_field' that is missing from model 'ValidationTestModel'.
    507 
    508 >>> class ValidationTestModelAdmin(ModelAdmin):
    509 ...     filter_vertical = ("name",)
    510 >>> validate(ValidationTestModelAdmin, ValidationTestModel)
    511 Traceback (most recent call last):
    512 ...
    513 ImproperlyConfigured: 'ValidationTestModelAdmin.filter_vertical[0]' must be a ManyToManyField.
    514 
    515 >>> class ValidationTestModelAdmin(ModelAdmin):
    516 ...     filter_vertical = ("users",)
    517 >>> validate(ValidationTestModelAdmin, ValidationTestModel)
    518 
    519 # filter_horizontal
    520 
    521 >>> class ValidationTestModelAdmin(ModelAdmin):
    522 ...     filter_horizontal = 10
    523 >>> validate(ValidationTestModelAdmin, ValidationTestModel)
    524 Traceback (most recent call last):
    525 ...
    526 ImproperlyConfigured: 'ValidationTestModelAdmin.filter_horizontal' must be a list or tuple.
    527 
    528 >>> class ValidationTestModelAdmin(ModelAdmin):
    529 ...     filter_horizontal = ("non_existent_field",)
    530 >>> validate(ValidationTestModelAdmin, ValidationTestModel)
    531 Traceback (most recent call last):
    532 ...
    533 ImproperlyConfigured: 'ValidationTestModelAdmin.filter_horizontal' refers to field 'non_existent_field' that is missing from model 'ValidationTestModel'.
    534 
    535 >>> class ValidationTestModelAdmin(ModelAdmin):
    536 ...     filter_horizontal = ("name",)
    537 >>> validate(ValidationTestModelAdmin, ValidationTestModel)
    538 Traceback (most recent call last):
    539 ...
    540 ImproperlyConfigured: 'ValidationTestModelAdmin.filter_horizontal[0]' must be a ManyToManyField.
    541 
    542 >>> class ValidationTestModelAdmin(ModelAdmin):
    543 ...     filter_horizontal = ("users",)
    544 >>> validate(ValidationTestModelAdmin, ValidationTestModel)
    545 
    546 # radio_fields
    547 
    548 >>> class ValidationTestModelAdmin(ModelAdmin):
    549 ...     radio_fields = ()
    550 >>> validate(ValidationTestModelAdmin, ValidationTestModel)
    551 Traceback (most recent call last):
    552 ...
    553 ImproperlyConfigured: 'ValidationTestModelAdmin.radio_fields' must be a dictionary.
    554 
    555 >>> class ValidationTestModelAdmin(ModelAdmin):
    556 ...     radio_fields = {"non_existent_field": None}
    557 >>> validate(ValidationTestModelAdmin, ValidationTestModel)
    558 Traceback (most recent call last):
    559 ...
    560 ImproperlyConfigured: 'ValidationTestModelAdmin.radio_fields' refers to field 'non_existent_field' that is missing from model 'ValidationTestModel'.
    561 
    562 >>> class ValidationTestModelAdmin(ModelAdmin):
    563 ...     radio_fields = {"name": None}
    564 >>> validate(ValidationTestModelAdmin, ValidationTestModel)
    565 Traceback (most recent call last):
    566 ...
    567 ImproperlyConfigured: 'ValidationTestModelAdmin.radio_fields['name']' is neither an instance of ForeignKey nor does have choices set.
    568 
    569 >>> class ValidationTestModelAdmin(ModelAdmin):
    570 ...     radio_fields = {"state": None}
    571 >>> validate(ValidationTestModelAdmin, ValidationTestModel)
    572 Traceback (most recent call last):
    573 ...
    574 ImproperlyConfigured: 'ValidationTestModelAdmin.radio_fields['state']' is neither admin.HORIZONTAL nor admin.VERTICAL.
    575 
    576 >>> class ValidationTestModelAdmin(ModelAdmin):
    577 ...     radio_fields = {"state": VERTICAL}
    578 >>> validate(ValidationTestModelAdmin, ValidationTestModel)
    579 
    580 # prepopulated_fields
    581 
    582 >>> class ValidationTestModelAdmin(ModelAdmin):
    583 ...     prepopulated_fields = ()
    584 >>> validate(ValidationTestModelAdmin, ValidationTestModel)
    585 Traceback (most recent call last):
    586 ...
    587 ImproperlyConfigured: 'ValidationTestModelAdmin.prepopulated_fields' must be a dictionary.
    588 
    589 >>> class ValidationTestModelAdmin(ModelAdmin):
    590 ...     prepopulated_fields = {"non_existent_field": None}
    591 >>> validate(ValidationTestModelAdmin, ValidationTestModel)
    592 Traceback (most recent call last):
    593 ...
    594 ImproperlyConfigured: 'ValidationTestModelAdmin.prepopulated_fields' refers to field 'non_existent_field' that is missing from model 'ValidationTestModel'.
    595 
    596 >>> class ValidationTestModelAdmin(ModelAdmin):
    597 ...     prepopulated_fields = {"slug": ("non_existent_field",)}
    598 >>> validate(ValidationTestModelAdmin, ValidationTestModel)
    599 Traceback (most recent call last):
    600 ...
    601 ImproperlyConfigured: 'ValidationTestModelAdmin.prepopulated_fields['slug'][0]' refers to field 'non_existent_field' that is missing from model 'ValidationTestModel'.
    602 
    603 >>> class ValidationTestModelAdmin(ModelAdmin):
    604 ...     prepopulated_fields = {"users": ("name",)}
    605 >>> validate(ValidationTestModelAdmin, ValidationTestModel)
    606 Traceback (most recent call last):
    607 ...
    608 ImproperlyConfigured: 'ValidationTestModelAdmin.prepopulated_fields['users']' is either a DateTimeField, ForeignKey or ManyToManyField. This isn't allowed.
    609 
    610 >>> class ValidationTestModelAdmin(ModelAdmin):
    611 ...     prepopulated_fields = {"slug": ("name",)}
    612 >>> validate(ValidationTestModelAdmin, ValidationTestModel)
    613 
    614 # list_display
    615 
    616 >>> class ValidationTestModelAdmin(ModelAdmin):
    617 ...     list_display = 10
    618 >>> validate(ValidationTestModelAdmin, ValidationTestModel)
    619 Traceback (most recent call last):
    620 ...
    621 ImproperlyConfigured: 'ValidationTestModelAdmin.list_display' must be a list or tuple.
    622 
    623 >>> class ValidationTestModelAdmin(ModelAdmin):
    624 ...     list_display = ('non_existent_field',)
    625 >>> validate(ValidationTestModelAdmin, ValidationTestModel)
    626 Traceback (most recent call last):
    627 ...
    628 ImproperlyConfigured: ValidationTestModelAdmin.list_display[0], 'non_existent_field' is not a callable or an attribute of 'ValidationTestModelAdmin' or found in the model 'ValidationTestModel'.
    629 
    630 
    631 >>> class ValidationTestModelAdmin(ModelAdmin):
    632 ...     list_display = ('users',)
    633 >>> validate(ValidationTestModelAdmin, ValidationTestModel)
    634 Traceback (most recent call last):
    635 ...
    636 ImproperlyConfigured: 'ValidationTestModelAdmin.list_display[0]', 'users' is a ManyToManyField which is not supported.
    637 
    638 >>> class ValidationTestModelAdmin(ModelAdmin):
    639 ...     list_display = ('name',)
    640 >>> validate(ValidationTestModelAdmin, ValidationTestModel)
    641 
    642 # list_display_links
    643 
    644 >>> class ValidationTestModelAdmin(ModelAdmin):
    645 ...     list_display_links = 10
    646 >>> validate(ValidationTestModelAdmin, ValidationTestModel)
    647 Traceback (most recent call last):
    648 ...
    649 ImproperlyConfigured: 'ValidationTestModelAdmin.list_display_links' must be a list or tuple.
    650 
    651 >>> class ValidationTestModelAdmin(ModelAdmin):
    652 ...     list_display_links = ('non_existent_field',)
    653 >>> validate(ValidationTestModelAdmin, ValidationTestModel)
    654 Traceback (most recent call last):
    655 ...
    656 ImproperlyConfigured: 'ValidationTestModelAdmin.list_display_links[0]' refers to 'non_existent_field' that is neither a field, method or property of model 'ValidationTestModel'.
    657 
    658 >>> class ValidationTestModelAdmin(ModelAdmin):
    659 ...     list_display_links = ('name',)
    660 >>> validate(ValidationTestModelAdmin, ValidationTestModel)
    661 Traceback (most recent call last):
    662 ...
    663 ImproperlyConfigured: 'ValidationTestModelAdmin.list_display_links[0]'refers to 'name' which is not defined in 'list_display'.
    664 
    665 >>> class ValidationTestModelAdmin(ModelAdmin):
    666 ...     list_display = ('name',)
    667 ...     list_display_links = ('name',)
    668 >>> validate(ValidationTestModelAdmin, ValidationTestModel)
    669 
    670 # list_filter
    671 
    672 >>> class ValidationTestModelAdmin(ModelAdmin):
    673 ...     list_filter = 10
    674 >>> validate(ValidationTestModelAdmin, ValidationTestModel)
    675 Traceback (most recent call last):
    676 ...
    677 ImproperlyConfigured: 'ValidationTestModelAdmin.list_filter' must be a list or tuple.
    678 
    679 >>> class ValidationTestModelAdmin(ModelAdmin):
    680 ...     list_filter = ('non_existent_field',)
    681 >>> validate(ValidationTestModelAdmin, ValidationTestModel)
    682 Traceback (most recent call last):
    683 ...
    684 ImproperlyConfigured: 'ValidationTestModelAdmin.list_filter[0]' refers to field 'non_existent_field' that is missing from model 'ValidationTestModel'.
    685 
    686 >>> class ValidationTestModelAdmin(ModelAdmin):
    687 ...     list_filter = ('is_active',)
    688 >>> validate(ValidationTestModelAdmin, ValidationTestModel)
    689 
    690 # list_per_page
    691 
    692 >>> class ValidationTestModelAdmin(ModelAdmin):
    693 ...     list_per_page = 'hello'
    694 >>> validate(ValidationTestModelAdmin, ValidationTestModel)
    695 Traceback (most recent call last):
    696 ...
    697 ImproperlyConfigured: 'ValidationTestModelAdmin.list_per_page' should be a integer.
    698 
    699 >>> class ValidationTestModelAdmin(ModelAdmin):
    700 ...     list_per_page = 100
    701 >>> validate(ValidationTestModelAdmin, ValidationTestModel)
    702 
    703 # search_fields
    704 
    705 >>> class ValidationTestModelAdmin(ModelAdmin):
    706 ...     search_fields = 10
    707 >>> validate(ValidationTestModelAdmin, ValidationTestModel)
    708 Traceback (most recent call last):
    709 ...
    710 ImproperlyConfigured: 'ValidationTestModelAdmin.search_fields' must be a list or tuple.
    711 
    712 # date_hierarchy
    713 
    714 >>> class ValidationTestModelAdmin(ModelAdmin):
    715 ...     date_hierarchy = 'non_existent_field'
    716 >>> validate(ValidationTestModelAdmin, ValidationTestModel)
    717 Traceback (most recent call last):
    718 ...
    719 ImproperlyConfigured: 'ValidationTestModelAdmin.date_hierarchy' refers to field 'non_existent_field' that is missing from model 'ValidationTestModel'.
    720 
    721 >>> class ValidationTestModelAdmin(ModelAdmin):
    722 ...     date_hierarchy = 'name'
    723 >>> validate(ValidationTestModelAdmin, ValidationTestModel)
    724 Traceback (most recent call last):
    725 ...
    726 ImproperlyConfigured: 'ValidationTestModelAdmin.date_hierarchy is neither an instance of DateField nor DateTimeField.
    727 
    728 >>> class ValidationTestModelAdmin(ModelAdmin):
    729 ...     date_hierarchy = 'pub_date'
    730 >>> validate(ValidationTestModelAdmin, ValidationTestModel)
    731 
    732 # ordering
    733 
    734 >>> class ValidationTestModelAdmin(ModelAdmin):
    735 ...     ordering = 10
    736 >>> validate(ValidationTestModelAdmin, ValidationTestModel)
    737 Traceback (most recent call last):
    738 ...
    739 ImproperlyConfigured: 'ValidationTestModelAdmin.ordering' must be a list or tuple.
    740 
    741 >>> class ValidationTestModelAdmin(ModelAdmin):
    742 ...     ordering = ('non_existent_field',)
    743 >>> validate(ValidationTestModelAdmin, ValidationTestModel)
    744 Traceback (most recent call last):
    745 ...
    746 ImproperlyConfigured: 'ValidationTestModelAdmin.ordering[0]' refers to field 'non_existent_field' that is missing from model 'ValidationTestModel'.
    747 
    748 >>> class ValidationTestModelAdmin(ModelAdmin):
    749 ...     ordering = ('?', 'name')
    750 >>> validate(ValidationTestModelAdmin, ValidationTestModel)
    751 Traceback (most recent call last):
    752 ...
    753 ImproperlyConfigured: 'ValidationTestModelAdmin.ordering' has the random ordering marker '?', but contains other fields as well. Please either remove '?' or the other fields.
    754 
    755 >>> class ValidationTestModelAdmin(ModelAdmin):
    756 ...     ordering = ('?',)
    757 >>> validate(ValidationTestModelAdmin, ValidationTestModel)
    758 
    759 >>> class ValidationTestModelAdmin(ModelAdmin):
    760 ...     ordering = ('band__name',)
    761 >>> validate(ValidationTestModelAdmin, ValidationTestModel)
    762 
    763 >>> class ValidationTestModelAdmin(ModelAdmin):
    764 ...     ordering = ('name',)
    765 >>> validate(ValidationTestModelAdmin, ValidationTestModel)
    766 
    767 # list_select_related
    768 
    769 >>> class ValidationTestModelAdmin(ModelAdmin):
    770 ...     list_select_related = 1
    771 >>> validate(ValidationTestModelAdmin, ValidationTestModel)
    772 Traceback (most recent call last):
    773 ...
    774 ImproperlyConfigured: 'ValidationTestModelAdmin.list_select_related' should be a boolean.
    775 
    776 >>> class ValidationTestModelAdmin(ModelAdmin):
    777 ...     list_select_related = False
    778 >>> validate(ValidationTestModelAdmin, ValidationTestModel)
    779 
    780 # save_as
    781 
    782 >>> class ValidationTestModelAdmin(ModelAdmin):
    783 ...     save_as = 1
    784 >>> validate(ValidationTestModelAdmin, ValidationTestModel)
    785 Traceback (most recent call last):
    786 ...
    787 ImproperlyConfigured: 'ValidationTestModelAdmin.save_as' should be a boolean.
    788 
    789 >>> class ValidationTestModelAdmin(ModelAdmin):
    790 ...     save_as = True
    791 >>> validate(ValidationTestModelAdmin, ValidationTestModel)
    792 
    793 # save_on_top
    794 
    795 >>> class ValidationTestModelAdmin(ModelAdmin):
    796 ...     save_on_top = 1
    797 >>> validate(ValidationTestModelAdmin, ValidationTestModel)
    798 Traceback (most recent call last):
    799 ...
    800 ImproperlyConfigured: 'ValidationTestModelAdmin.save_on_top' should be a boolean.
    801 
    802 >>> class ValidationTestModelAdmin(ModelAdmin):
    803 ...     save_on_top = True
    804 >>> validate(ValidationTestModelAdmin, ValidationTestModel)
    805 
    806 # inlines
    807 
    808 >>> from django.contrib.admin.options import TabularInline
    809 
    810 >>> class ValidationTestModelAdmin(ModelAdmin):
    811 ...     inlines = 10
    812 >>> validate(ValidationTestModelAdmin, ValidationTestModel)
    813 Traceback (most recent call last):
    814 ...
    815 ImproperlyConfigured: 'ValidationTestModelAdmin.inlines' must be a list or tuple.
    816 
    817 >>> class ValidationTestInline(object):
    818 ...     pass
    819 >>> class ValidationTestModelAdmin(ModelAdmin):
    820 ...     inlines = [ValidationTestInline]
    821 >>> validate(ValidationTestModelAdmin, ValidationTestModel)
    822 Traceback (most recent call last):
    823 ...
    824 ImproperlyConfigured: 'ValidationTestModelAdmin.inlines[0]' does not inherit from BaseModelAdmin.
    825 
    826 >>> class ValidationTestInline(TabularInline):
    827 ...     pass
    828 >>> class ValidationTestModelAdmin(ModelAdmin):
    829 ...     inlines = [ValidationTestInline]
    830 >>> validate(ValidationTestModelAdmin, ValidationTestModel)
    831 Traceback (most recent call last):
    832 ...
    833 ImproperlyConfigured: 'model' is a required attribute of 'ValidationTestModelAdmin.inlines[0]'.
    834 
    835 >>> class SomethingBad(object):
    836 ...     pass
    837 >>> class ValidationTestInline(TabularInline):
    838 ...     model = SomethingBad
    839 >>> class ValidationTestModelAdmin(ModelAdmin):
    840 ...     inlines = [ValidationTestInline]
    841 >>> validate(ValidationTestModelAdmin, ValidationTestModel)
    842 Traceback (most recent call last):
    843 ...
    844 ImproperlyConfigured: 'ValidationTestModelAdmin.inlines[0].model' does not inherit from models.Model.
    845 
    846 >>> class ValidationTestInline(TabularInline):
    847 ...     model = ValidationTestInlineModel
    848 >>> class ValidationTestModelAdmin(ModelAdmin):
    849 ...     inlines = [ValidationTestInline]
    850 >>> validate(ValidationTestModelAdmin, ValidationTestModel)
    851 
    852 # fields
    853 
    854 >>> class ValidationTestInline(TabularInline):
    855 ...     model = ValidationTestInlineModel
    856 ...     fields = 10
    857 >>> class ValidationTestModelAdmin(ModelAdmin):
    858 ...     inlines = [ValidationTestInline]
    859 >>> validate(ValidationTestModelAdmin, ValidationTestModel)
    860 Traceback (most recent call last):
    861 ...
    862 ImproperlyConfigured: 'ValidationTestInline.fields' must be a list or tuple.
    863 
    864 >>> class ValidationTestInline(TabularInline):
    865 ...     model = ValidationTestInlineModel
    866 ...     fields = ("non_existent_field",)
    867 >>> class ValidationTestModelAdmin(ModelAdmin):
    868 ...     inlines = [ValidationTestInline]
    869 >>> validate(ValidationTestModelAdmin, ValidationTestModel)
    870 Traceback (most recent call last):
    871 ...
    872 ImproperlyConfigured: 'ValidationTestInline.fields' refers to field 'non_existent_field' that is missing from the form.
    873 
    874 # fk_name
    875 
    876 >>> class ValidationTestInline(TabularInline):
    877 ...     model = ValidationTestInlineModel
    878 ...     fk_name = "non_existent_field"
    879 >>> class ValidationTestModelAdmin(ModelAdmin):
    880 ...     inlines = [ValidationTestInline]
    881 >>> validate(ValidationTestModelAdmin, ValidationTestModel)
    882 Traceback (most recent call last):
    883 ...
    884 ImproperlyConfigured: 'ValidationTestInline.fk_name' refers to field 'non_existent_field' that is missing from model 'ValidationTestInlineModel'.
    885 
    886 >>> class ValidationTestInline(TabularInline):
    887 ...     model = ValidationTestInlineModel
    888 ...     fk_name = "parent"
    889 >>> class ValidationTestModelAdmin(ModelAdmin):
    890 ...     inlines = [ValidationTestInline]
    891 >>> validate(ValidationTestModelAdmin, ValidationTestModel)
    892 
    893 # extra
    894 
    895 >>> class ValidationTestInline(TabularInline):
    896 ...     model = ValidationTestInlineModel
    897 ...     extra = "hello"
    898 >>> class ValidationTestModelAdmin(ModelAdmin):
    899 ...     inlines = [ValidationTestInline]
    900 >>> validate(ValidationTestModelAdmin, ValidationTestModel)
    901 Traceback (most recent call last):
    902 ...
    903 ImproperlyConfigured: 'ValidationTestInline.extra' should be a integer.
    904 
    905 >>> class ValidationTestInline(TabularInline):
    906 ...     model = ValidationTestInlineModel
    907 ...     extra = 2
    908 >>> class ValidationTestModelAdmin(ModelAdmin):
    909 ...     inlines = [ValidationTestInline]
    910 >>> validate(ValidationTestModelAdmin, ValidationTestModel)
    911 
    912 # max_num
    913 
    914 >>> class ValidationTestInline(TabularInline):
    915 ...     model = ValidationTestInlineModel
    916 ...     max_num = "hello"
    917 >>> class ValidationTestModelAdmin(ModelAdmin):
    918 ...     inlines = [ValidationTestInline]
    919 >>> validate(ValidationTestModelAdmin, ValidationTestModel)
    920 Traceback (most recent call last):
    921 ...
    922 ImproperlyConfigured: 'ValidationTestInline.max_num' should be an integer or None (default).
    923 
    924 >>> class ValidationTestInline(TabularInline):
    925 ...     model = ValidationTestInlineModel
    926 ...     max_num = 2
    927 >>> class ValidationTestModelAdmin(ModelAdmin):
    928 ...     inlines = [ValidationTestInline]
    929 >>> validate(ValidationTestModelAdmin, ValidationTestModel)
    930 
    931 # formset
    932 
    933 >>> from django.forms.models import BaseModelFormSet
    934 
    935 >>> class FakeFormSet(object):
    936 ...     pass
    937 >>> class ValidationTestInline(TabularInline):
    938 ...     model = ValidationTestInlineModel
    939 ...     formset = FakeFormSet
    940 >>> class ValidationTestModelAdmin(ModelAdmin):
    941 ...     inlines = [ValidationTestInline]
    942 >>> validate(ValidationTestModelAdmin, ValidationTestModel)
    943 Traceback (most recent call last):
    944 ...
    945 ImproperlyConfigured: 'ValidationTestInline.formset' does not inherit from BaseModelFormSet.
    946 
    947 >>> class RealModelFormSet(BaseModelFormSet):
    948 ...     pass
    949 >>> class ValidationTestInline(TabularInline):
    950 ...     model = ValidationTestInlineModel
    951 ...     formset = RealModelFormSet
    952 >>> class ValidationTestModelAdmin(ModelAdmin):
    953 ...     inlines = [ValidationTestInline]
    954 >>> validate(ValidationTestModelAdmin, ValidationTestModel)
    955 
    956 """
    957 }
  • new file tests/regressiontests/modeladmin/tests.py

    diff --git a/tests/regressiontests/modeladmin/tests.py b/tests/regressiontests/modeladmin/tests.py
    new file mode 100644
    index 0000000..d82c563
    - +  
     1from datetime import date
     2
     3from django import forms
     4from django.conf import settings
     5from django.contrib.admin.options import ModelAdmin, TabularInline, \
     6    HORIZONTAL, VERTICAL
     7from django.contrib.admin.sites import AdminSite
     8from django.contrib.admin.validation import validate
     9from django.contrib.admin.widgets import AdminDateWidget, AdminRadioSelect
     10from django.core.exceptions import ImproperlyConfigured
     11from django.forms.models import BaseModelFormSet
     12from django.forms.widgets import Select
     13from django.test import TestCase
     14
     15from models import Band, Concert, ValidationTestModel, \
     16    ValidationTestInlineModel
     17
     18
     19# None of the following tests really depend on the content of the request,
     20# so we'll just pass in None.
     21request = None
     22
     23
     24class ModelAdminTest(TestCase):
     25
     26    def setUp(self):
     27        self.band = Band.objects.create(
     28            name='The Doors',
     29            bio='',
     30            sign_date=date(1965, 1, 1),
     31        )
     32        self.site = AdminSite()
     33
     34    # form/fields/fieldsets interaction ##############################
     35
     36    def test_default_fields(self):
     37        ma = ModelAdmin(Band, self.site)
     38
     39        self.assertEquals(ma.get_form(request).base_fields.keys(),
     40            ['name', 'bio', 'sign_date'])
     41
     42    def test_default_fieldsets(self):
     43        """
     44        fieldsets_add and fieldsets_change should return a special data structure that
     45        is used in the templates. They should generate the "right thing" whether we
     46        have specified a custom form, the fields argument, or nothing at all.
     47
     48        Here's the default case. There are no custom form_add/form_change methods,
     49        no fields argument, and no fieldsets argument.
     50        """
     51
     52        ma = ModelAdmin(Band, self.site)
     53        self.assertEqual(ma.get_fieldsets(request),
     54            [(None, {'fields': ['name', 'bio', 'sign_date']})])
     55
     56        self.assertEqual(ma.get_fieldsets(request, self.band),
     57            [(None, {'fields': ['name', 'bio', 'sign_date']})])
     58
     59    def test_field_arguments(self):
     60        """
     61        If we specify the fields argument, fieldsets_add and fielsets_change should
     62        just stick the fields into a formsets structure and return it.
     63        """
     64
     65        class BandAdmin(ModelAdmin):
     66             fields = ['name']
     67
     68        ma = BandAdmin(Band, self.site)
     69
     70        self.assertEqual( ma.get_fieldsets(request),
     71            [(None, {'fields': ['name']})])
     72
     73        self.assertEqual(ma.get_fieldsets(request, self.band),
     74            [(None, {'fields': ['name']})])
     75
     76    def test_field_arguments_restricted_on_form(self):
     77        """
     78        If we specify fields or fieldsets, it should exclude fields on the Form class
     79        to the fields specified. This may cause errors to be raised in the db layer if
     80        required model fields arent in fields/fieldsets, but that's preferable to
     81        ghost errors where you have a field in your Form class that isn't being
     82        displayed because you forgot to add it to fields/fielsets
     83        """
     84
     85        # Using `fields`.
     86        class BandAdmin(ModelAdmin):
     87            fields = ['name']
     88
     89        ma = BandAdmin(Band, self.site)
     90        self.assertEqual(ma.get_form(request).base_fields.keys(), ['name'])
     91        self.assertEqual(ma.get_form(request, self.band).base_fields.keys(),
     92            ['name'])
     93
     94        # Using `fieldsets`.
     95        class BandAdmin(ModelAdmin):
     96            fieldsets = [(None, {'fields': ['name']})]
     97
     98        ma = BandAdmin(Band, self.site)
     99        self.assertEqual(ma.get_form(request).base_fields.keys(), ['name'])
     100        self.assertEqual(ma.get_form(request, self.band).base_fields.keys(),
     101            ['name'])
     102
     103        # Using `exclude`.
     104        class BandAdmin(ModelAdmin):
     105            exclude = ['bio']
     106
     107        ma = BandAdmin(Band, self.site)
     108        self.assertEqual(ma.get_form(request).base_fields.keys(),
     109            ['name', 'sign_date'])
     110
     111        # You can also pass a tuple to `exclude`.
     112        class BandAdmin(ModelAdmin):
     113            exclude = ('bio',)
     114
     115        ma = BandAdmin(Band, self.site)
     116        self.assertEqual(ma.get_form(request).base_fields.keys(),
     117            ['name', 'sign_date'])
     118
     119        # Using `fields` and `exclude`.
     120        class BandAdmin(ModelAdmin):
     121            fields = ['name', 'bio']
     122            exclude = ['bio']
     123
     124        ma = BandAdmin(Band, self.site)
     125        self.assertEqual(ma.get_form(request).base_fields.keys(),
     126            ['name'])
     127
     128    def test_custom_form_validation(self):
     129        """
     130        If we specify a form, it should use it allowing custom validation to work
     131        properly. This won't, however, break any of the admin widgets or media.
     132        """
     133
     134        class AdminBandForm(forms.ModelForm):
     135            delete = forms.BooleanField()
     136
     137            class Meta:
     138                model = Band
     139
     140        class BandAdmin(ModelAdmin):
     141            form = AdminBandForm
     142
     143        ma = BandAdmin(Band, self.site)
     144        self.assertEqual(ma.get_form(request).base_fields.keys(),
     145            ['name', 'bio', 'sign_date', 'delete'])
     146
     147        self.assertEqual(
     148            type(ma.get_form(request).base_fields['sign_date'].widget),
     149            AdminDateWidget)
     150
     151    def test_queryset_override(self):
     152        """
     153        If we need to override the queryset of a ModelChoiceField in our custom form
     154        make sure that RelatedFieldWidgetWrapper doesn't mess that up.
     155        """
     156
     157        band2 = Band(name='The Beetles', bio='', sign_date=date(1962, 1, 1))
     158        band2.save()
     159
     160        class AdminConcertForm(forms.ModelForm):
     161            class Meta:
     162                model = Concert
     163
     164            def __init__(self, *args, **kwargs):
     165                super(AdminConcertForm, self).__init__(*args, **kwargs)
     166                self.fields["main_band"].queryset = Band.objects.filter(
     167                    name='The Doors')
     168
     169        class ConcertAdmin(ModelAdmin):
     170            form = AdminConcertForm
     171
     172        ma = ConcertAdmin(Concert, self.site)
     173        form = ma.get_form(request)()
     174
     175        self.assertEqual(str(form["main_band"]),
     176            '<select name="main_band" id="id_main_band">\n'
     177            '<option value="" selected="selected">---------</option>\n'
     178            '<option value="1">The Doors</option>\n'
     179            '</select>')
     180
     181    # radio_fields behavior ###########################################
     182
     183    def test_default_foreign_key_widget(self):
     184        """
     185        First, without any radio_fields specified, the widgets for ForeignKey
     186        and fields with choices specified ought to be a basic Select widget.
     187        ForeignKey widgets in the admin are wrapped with RelatedFieldWidgetWrapper so
     188        they need to be handled properly when type checking. For Select fields, all of
     189        the choices lists have a first entry of dashes.
     190        """
     191
     192        cma = ModelAdmin(Concert, self.site)
     193        cmafa = cma.get_form(request)
     194
     195        self.assertEqual(type(cmafa.base_fields['main_band'].widget.widget),
     196            Select)
     197        self.assertEqual(
     198            list(cmafa.base_fields['main_band'].widget.choices),
     199            [(u'', u'---------'), (1, u'The Doors')])
     200
     201        self.assertEqual(
     202            type(cmafa.base_fields['opening_band'].widget.widget), Select)
     203        self.assertEqual(
     204            list(cmafa.base_fields['opening_band'].widget.choices),
     205            [(u'', u'---------'), (1, u'The Doors')])
     206
     207        self.assertEqual(type(cmafa.base_fields['day'].widget), Select)
     208        self.assertEqual(list(cmafa.base_fields['day'].widget.choices),
     209            [('', '---------'), (1, 'Fri'), (2, 'Sat')])
     210
     211        self.assertEqual(type(cmafa.base_fields['transport'].widget),
     212            Select)
     213        self.assertEqual(
     214            list(cmafa.base_fields['transport'].widget.choices),
     215            [('', '---------'), (1, 'Plane'), (2, 'Train'), (3, 'Bus')])
     216
     217    def test_foreign_key_as_radio_field(self):
     218        """
     219        Now specify all the fields as radio_fields.  Widgets should now be
     220        RadioSelect, and the choices list should have a first entry of 'None' if
     221        blank=True for the model field.  Finally, the widget should have the
     222        'radiolist' attr, and 'inline' as well if the field is specified HORIZONTAL.
     223        """
     224
     225        class ConcertAdmin(ModelAdmin):
     226            radio_fields = {
     227                'main_band': HORIZONTAL,
     228                'opening_band': VERTICAL,
     229                'day': VERTICAL,
     230                'transport': HORIZONTAL,
     231            }
     232
     233        cma = ConcertAdmin(Concert, self.site)
     234        cmafa = cma.get_form(request)
     235
     236        self.assertEqual(type(cmafa.base_fields['main_band'].widget.widget),
     237            AdminRadioSelect)
     238        self.assertEqual(cmafa.base_fields['main_band'].widget.attrs,
     239            {'class': 'radiolist inline'})
     240        self.assertEqual(list(cmafa.base_fields['main_band'].widget.choices),
     241            [(1, u'The Doors')])
     242
     243        self.assertEqual(
     244            type(cmafa.base_fields['opening_band'].widget.widget),
     245            AdminRadioSelect)
     246        self.assertEqual(cmafa.base_fields['opening_band'].widget.attrs,
     247            {'class': 'radiolist'})
     248        self.assertEqual(
     249            list(cmafa.base_fields['opening_band'].widget.choices),
     250            [(u'', u'None'), (1, u'The Doors')])
     251
     252        self.assertEqual(type(cmafa.base_fields['day'].widget),
     253            AdminRadioSelect)
     254        self.assertEqual(cmafa.base_fields['day'].widget.attrs,
     255            {'class': 'radiolist'})
     256        self.assertEqual(list(cmafa.base_fields['day'].widget.choices),
     257            [(1, 'Fri'), (2, 'Sat')])
     258
     259        self.assertEqual(type(cmafa.base_fields['transport'].widget),
     260            AdminRadioSelect)
     261        self.assertEqual(cmafa.base_fields['transport'].widget.attrs,
     262            {'class': 'radiolist inline'})
     263        self.assertEqual(list(cmafa.base_fields['transport'].widget.choices),
     264            [('', u'None'), (1, 'Plane'), (2, 'Train'), (3, 'Bus')])
     265
     266        class AdminConcertForm(forms.ModelForm):
     267            class Meta:
     268                model = Concert
     269                exclude = ('transport',)
     270
     271        class ConcertAdmin(ModelAdmin):
     272            form = AdminConcertForm
     273
     274        ma = ConcertAdmin(Concert, self.site)
     275        self.assertEqual(ma.get_form(request).base_fields.keys(),
     276            ['main_band', 'opening_band', 'day'])
     277
     278        class AdminConcertForm(forms.ModelForm):
     279            extra = forms.CharField()
     280
     281            class Meta:
     282                model = Concert
     283                fields = ['extra', 'transport']
     284
     285        class ConcertAdmin(ModelAdmin):
     286            form = AdminConcertForm
     287
     288        ma = ConcertAdmin(Concert, self.site)
     289        self.assertEqual(ma.get_form(request).base_fields.keys(),
     290            ['extra', 'transport'])
     291
     292        class ConcertInline(TabularInline):
     293            form = AdminConcertForm
     294            model = Concert
     295            fk_name = 'main_band'
     296            can_delete = True
     297
     298        class BandAdmin(ModelAdmin):
     299            inlines = [
     300                ConcertInline
     301            ]
     302
     303        ma = BandAdmin(Band, self.site)
     304        self.assertEqual(
     305            list(ma.get_formsets(request))[0]().forms[0].fields.keys(),
     306            ['extra', 'transport', 'id', 'DELETE', 'main_band'])
     307
     308    # ModelAdmin Option Validation ####################################
     309
     310    def test_validation_only_runs_in_debug(self):
     311        # Ensure validation only runs when DEBUG = True
     312        settings.DEBUG = True
     313
     314        class ValidationTestModelAdmin(ModelAdmin):
     315            raw_id_fields = 10
     316
     317        site = AdminSite()
     318
     319        self.assertRaisesRegexp(
     320            ImproperlyConfigured,
     321            "'ValidationTestModelAdmin.raw_id_fields' must be a list or tuple.",
     322            site.register,
     323            ValidationTestModel,
     324            ValidationTestModelAdmin,
     325        )
     326
     327        settings.DEBUG = False
     328
     329        site = AdminSite()
     330        site.register(ValidationTestModel, ValidationTestModelAdmin)
     331
     332    def test_raw_id_fields_validation(self):
     333
     334        class ValidationTestModelAdmin(ModelAdmin):
     335            raw_id_fields = 10
     336
     337        self.assertRaisesRegexp(
     338            ImproperlyConfigured,
     339            "'ValidationTestModelAdmin.raw_id_fields' must be a list or tuple.",
     340            validate,
     341            ValidationTestModelAdmin,
     342            ValidationTestModel,
     343        )
     344
     345        class ValidationTestModelAdmin(ModelAdmin):
     346            raw_id_fields = ('non_existent_field',)
     347
     348        self.assertRaisesRegexp(
     349            ImproperlyConfigured,
     350            "'ValidationTestModelAdmin.raw_id_fields' refers to field 'non_existent_field' that is missing from model 'ValidationTestModel'.",
     351            validate,
     352            ValidationTestModelAdmin,
     353            ValidationTestModel,
     354        )
     355
     356        class ValidationTestModelAdmin(ModelAdmin):
     357            raw_id_fields = ('name',)
     358
     359        self.assertRaisesRegexp(
     360            ImproperlyConfigured,
     361            "'ValidationTestModelAdmin.raw_id_fields\[0\]', 'name' must be either a ForeignKey or ManyToManyField.",
     362            validate,
     363            ValidationTestModelAdmin,
     364            ValidationTestModel,
     365        )
     366
     367        class ValidationTestModelAdmin(ModelAdmin):
     368            raw_id_fields = ('users',)
     369
     370        validate(ValidationTestModelAdmin, ValidationTestModel)
     371
     372    def test_fieldsets_validation(self):
     373
     374        class ValidationTestModelAdmin(ModelAdmin):
     375            fieldsets = 10
     376
     377        self.assertRaisesRegexp(
     378            ImproperlyConfigured,
     379            "'ValidationTestModelAdmin.fieldsets' must be a list or tuple.",
     380            validate,
     381            ValidationTestModelAdmin,
     382            ValidationTestModel,
     383        )
     384
     385        class ValidationTestModelAdmin(ModelAdmin):
     386            fieldsets = ({},)
     387
     388        self.assertRaisesRegexp(
     389            ImproperlyConfigured,
     390            "'ValidationTestModelAdmin.fieldsets\[0\]' must be a list or tuple.",
     391            validate,
     392            ValidationTestModelAdmin,
     393            ValidationTestModel,
     394        )
     395
     396        class ValidationTestModelAdmin(ModelAdmin):
     397            fieldsets = ((),)
     398
     399        self.assertRaisesRegexp(
     400            ImproperlyConfigured,
     401            "'ValidationTestModelAdmin.fieldsets\[0\]' does not have exactly two elements.",
     402            validate,
     403            ValidationTestModelAdmin,
     404            ValidationTestModel,
     405        )
     406
     407        class ValidationTestModelAdmin(ModelAdmin):
     408            fieldsets = (("General", ()),)
     409
     410        self.assertRaisesRegexp(
     411            ImproperlyConfigured,
     412            "'ValidationTestModelAdmin.fieldsets\[0\]\[1\]' must be a dictionary.",
     413            validate,
     414            ValidationTestModelAdmin,
     415            ValidationTestModel,
     416        )
     417
     418        class ValidationTestModelAdmin(ModelAdmin):
     419            fieldsets = (("General", {}),)
     420
     421        self.assertRaisesRegexp(
     422            ImproperlyConfigured,
     423            "'fields' key is required in ValidationTestModelAdmin.fieldsets\[0\]\[1\] field options dict.",
     424            validate,
     425            ValidationTestModelAdmin,
     426            ValidationTestModel,
     427        )
     428
     429        class ValidationTestModelAdmin(ModelAdmin):
     430            fieldsets = (("General", {"fields": ("non_existent_field",)}),)
     431
     432        self.assertRaisesRegexp(
     433            ImproperlyConfigured,
     434            "'ValidationTestModelAdmin.fieldsets\[0\]\[1\]\['fields'\]' refers to field 'non_existent_field' that is missing from the form.",
     435            validate,
     436            ValidationTestModelAdmin,
     437            ValidationTestModel,
     438        )
     439
     440        class ValidationTestModelAdmin(ModelAdmin):
     441            fieldsets = (("General", {"fields": ("name",)}),)
     442
     443        validate(ValidationTestModelAdmin, ValidationTestModel)
     444
     445        class ValidationTestModelAdmin(ModelAdmin):
     446            fieldsets = (("General", {"fields": ("name",)}),)
     447            fields = ["name",]
     448
     449        self.assertRaisesRegexp(
     450            ImproperlyConfigured,
     451            "Both fieldsets and fields are specified in ValidationTestModelAdmin.",
     452            validate,
     453            ValidationTestModelAdmin,
     454            ValidationTestModel,
     455        )
     456
     457        class ValidationTestModelAdmin(ModelAdmin):
     458            fieldsets = [(None, {'fields': ['name', 'name']})]
     459
     460        self.assertRaisesRegexp(
     461            ImproperlyConfigured,
     462            "There are duplicate field\(s\) in ValidationTestModelAdmin.fieldsets",
     463            validate,
     464            ValidationTestModelAdmin,
     465            ValidationTestModel,
     466        )
     467
     468        class ValidationTestModelAdmin(ModelAdmin):
     469            fields = ["name", "name"]
     470
     471        self.assertRaisesRegexp(
     472            ImproperlyConfigured,
     473            "There are duplicate field\(s\) in ValidationTestModelAdmin.fields",
     474            validate,
     475            ValidationTestModelAdmin,
     476            ValidationTestModel,
     477        )
     478
     479    def test_form_validation(self):
     480
     481        class FakeForm(object):
     482            pass
     483
     484        class ValidationTestModelAdmin(ModelAdmin):
     485            form = FakeForm
     486
     487        self.assertRaisesRegexp(
     488            ImproperlyConfigured,
     489            "ValidationTestModelAdmin.form does not inherit from BaseModelForm.",
     490            validate,
     491            ValidationTestModelAdmin,
     492            ValidationTestModel,
     493        )
     494
     495    def test_fieldsets_with_custom_form_validation(self):
     496
     497        class BandAdmin(ModelAdmin):
     498
     499            fieldsets = (
     500                ('Band', {
     501                    'fields': ('non_existent_field',)
     502                }),
     503            )
     504
     505        self.assertRaisesRegexp(
     506            ImproperlyConfigured,
     507            "'BandAdmin.fieldsets\[0\]\[1\]\['fields'\]' refers to field 'non_existent_field' that is missing from the form.",
     508            validate,
     509            BandAdmin,
     510            Band,
     511        )
     512
     513        class BandAdmin(ModelAdmin):
     514            fieldsets = (
     515                ('Band', {
     516                    'fields': ('name',)
     517                }),
     518            )
     519
     520        validate(BandAdmin, Band)
     521
     522        class AdminBandForm(forms.ModelForm):
     523            class Meta:
     524                model = Band
     525
     526        class BandAdmin(ModelAdmin):
     527            form = AdminBandForm
     528
     529            fieldsets = (
     530                ('Band', {
     531                    'fields': ('non_existent_field',)
     532                }),
     533            )
     534
     535        self.assertRaisesRegexp(
     536            ImproperlyConfigured,
     537            "'BandAdmin.fieldsets\[0]\[1\]\['fields'\]' refers to field 'non_existent_field' that is missing from the form.",
     538            validate,
     539            BandAdmin,
     540            Band,
     541        )
     542
     543        class AdminBandForm(forms.ModelForm):
     544            delete = forms.BooleanField()
     545
     546            class Meta:
     547                model = Band
     548
     549        class BandAdmin(ModelAdmin):
     550            form = AdminBandForm
     551
     552            fieldsets = (
     553                ('Band', {
     554                    'fields': ('name', 'bio', 'sign_date', 'delete')
     555                }),
     556            )
     557
     558        validate(BandAdmin, Band)
     559
     560    def test_filter_vertical_validation(self):
     561
     562        class ValidationTestModelAdmin(ModelAdmin):
     563            filter_vertical = 10
     564
     565        self.assertRaisesRegexp(
     566            ImproperlyConfigured,
     567            "'ValidationTestModelAdmin.filter_vertical' must be a list or tuple.",
     568            validate,
     569            ValidationTestModelAdmin,
     570            ValidationTestModel,
     571        )
     572
     573        class ValidationTestModelAdmin(ModelAdmin):
     574            filter_vertical = ("non_existent_field",)
     575
     576        self.assertRaisesRegexp(
     577            ImproperlyConfigured,
     578            "'ValidationTestModelAdmin.filter_vertical' refers to field 'non_existent_field' that is missing from model 'ValidationTestModel'.",
     579            validate,
     580            ValidationTestModelAdmin,
     581            ValidationTestModel,
     582        )
     583
     584        class ValidationTestModelAdmin(ModelAdmin):
     585            filter_vertical = ("name",)
     586
     587        self.assertRaisesRegexp(
     588            ImproperlyConfigured,
     589            "'ValidationTestModelAdmin.filter_vertical\[0\]' must be a ManyToManyField.",
     590            validate,
     591            ValidationTestModelAdmin,
     592            ValidationTestModel,
     593        )
     594
     595        class ValidationTestModelAdmin(ModelAdmin):
     596            filter_vertical = ("users",)
     597
     598        validate(ValidationTestModelAdmin, ValidationTestModel)
     599
     600    def test_filter_horizontal_validation(self):
     601
     602        class ValidationTestModelAdmin(ModelAdmin):
     603            filter_horizontal = 10
     604
     605        self.assertRaisesRegexp(
     606            ImproperlyConfigured,
     607            "'ValidationTestModelAdmin.filter_horizontal' must be a list or tuple.",
     608            validate,
     609            ValidationTestModelAdmin,
     610            ValidationTestModel,
     611        )
     612
     613        class ValidationTestModelAdmin(ModelAdmin):
     614            filter_horizontal = ("non_existent_field",)
     615
     616        self.assertRaisesRegexp(
     617            ImproperlyConfigured,
     618            "'ValidationTestModelAdmin.filter_horizontal' refers to field 'non_existent_field' that is missing from model 'ValidationTestModel'.",
     619            validate,
     620            ValidationTestModelAdmin,
     621            ValidationTestModel,
     622        )
     623
     624        class ValidationTestModelAdmin(ModelAdmin):
     625            filter_horizontal = ("name",)
     626
     627        self.assertRaisesRegexp(
     628            ImproperlyConfigured,
     629            "'ValidationTestModelAdmin.filter_horizontal\[0\]' must be a ManyToManyField.",
     630            validate,
     631            ValidationTestModelAdmin,
     632            ValidationTestModel,
     633        )
     634
     635        class ValidationTestModelAdmin(ModelAdmin):
     636            filter_horizontal = ("users",)
     637
     638        validate(ValidationTestModelAdmin, ValidationTestModel)
     639
     640    def test_radio_fields_validation(self):
     641
     642        class ValidationTestModelAdmin(ModelAdmin):
     643            radio_fields = ()
     644
     645        self.assertRaisesRegexp(
     646            ImproperlyConfigured,
     647            "'ValidationTestModelAdmin.radio_fields' must be a dictionary.",
     648            validate,
     649            ValidationTestModelAdmin,
     650            ValidationTestModel,
     651        )
     652
     653        class ValidationTestModelAdmin(ModelAdmin):
     654            radio_fields = {"non_existent_field": None}
     655
     656        self.assertRaisesRegexp(
     657            ImproperlyConfigured,
     658            "'ValidationTestModelAdmin.radio_fields' refers to field 'non_existent_field' that is missing from model 'ValidationTestModel'.",
     659            validate,
     660            ValidationTestModelAdmin,
     661            ValidationTestModel,
     662        )
     663
     664        class ValidationTestModelAdmin(ModelAdmin):
     665            radio_fields = {"name": None}
     666
     667        self.assertRaisesRegexp(
     668            ImproperlyConfigured,
     669            "'ValidationTestModelAdmin.radio_fields\['name'\]' is neither an instance of ForeignKey nor does have choices set.",
     670            validate,
     671            ValidationTestModelAdmin,
     672            ValidationTestModel,
     673        )
     674
     675        class ValidationTestModelAdmin(ModelAdmin):
     676            radio_fields = {"state": None}
     677
     678        self.assertRaisesRegexp(
     679            ImproperlyConfigured,
     680            "'ValidationTestModelAdmin.radio_fields\['state'\]' is neither admin.HORIZONTAL nor admin.VERTICAL.",
     681            validate,
     682            ValidationTestModelAdmin,
     683            ValidationTestModel,
     684        )
     685
     686        class ValidationTestModelAdmin(ModelAdmin):
     687            radio_fields = {"state": VERTICAL}
     688
     689        validate(ValidationTestModelAdmin, ValidationTestModel)
     690
     691    def test_prepopulated_fields_validation(self):
     692
     693        class ValidationTestModelAdmin(ModelAdmin):
     694            prepopulated_fields = ()
     695
     696        self.assertRaisesRegexp(
     697            ImproperlyConfigured,
     698            "'ValidationTestModelAdmin.prepopulated_fields' must be a dictionary.",
     699            validate,
     700            ValidationTestModelAdmin,
     701            ValidationTestModel,
     702        )
     703
     704        class ValidationTestModelAdmin(ModelAdmin):
     705            prepopulated_fields = {"non_existent_field": None}
     706
     707        self.assertRaisesRegexp(
     708            ImproperlyConfigured,
     709            "'ValidationTestModelAdmin.prepopulated_fields' refers to field 'non_existent_field' that is missing from model 'ValidationTestModel'.",
     710            validate,
     711            ValidationTestModelAdmin,
     712            ValidationTestModel,
     713        )
     714
     715        class ValidationTestModelAdmin(ModelAdmin):
     716            prepopulated_fields = {"slug": ("non_existent_field",)}
     717
     718        self.assertRaisesRegexp(
     719            ImproperlyConfigured,
     720            "'ValidationTestModelAdmin.prepopulated_fields\['slug'\]\[0\]' refers to field 'non_existent_field' that is missing from model 'ValidationTestModel'.",
     721            validate,
     722            ValidationTestModelAdmin,
     723            ValidationTestModel,
     724        )
     725
     726        class ValidationTestModelAdmin(ModelAdmin):
     727            prepopulated_fields = {"users": ("name",)}
     728
     729        self.assertRaisesRegexp(
     730            ImproperlyConfigured,
     731            "'ValidationTestModelAdmin.prepopulated_fields\['users'\]' is either a DateTimeField, ForeignKey or ManyToManyField. This isn't allowed.",
     732            validate,
     733            ValidationTestModelAdmin,
     734            ValidationTestModel,
     735        )
     736
     737        class ValidationTestModelAdmin(ModelAdmin):
     738            prepopulated_fields = {"slug": ("name",)}
     739
     740        validate(ValidationTestModelAdmin, ValidationTestModel)
     741
     742    def test_list_display_validation(self):
     743
     744        class ValidationTestModelAdmin(ModelAdmin):
     745            list_display = 10
     746
     747        self.assertRaisesRegexp(
     748            ImproperlyConfigured,
     749            "'ValidationTestModelAdmin.list_display' must be a list or tuple.",
     750            validate,
     751            ValidationTestModelAdmin,
     752            ValidationTestModel,
     753        )
     754
     755        class ValidationTestModelAdmin(ModelAdmin):
     756            list_display = ('non_existent_field',)
     757
     758        self.assertRaisesRegexp(
     759            ImproperlyConfigured,
     760            "ValidationTestModelAdmin.list_display\[0\], 'non_existent_field' is not a callable or an attribute of 'ValidationTestModelAdmin' or found in the model 'ValidationTestModel'.",
     761            validate,
     762            ValidationTestModelAdmin,
     763            ValidationTestModel,
     764        )
     765
     766        class ValidationTestModelAdmin(ModelAdmin):
     767            list_display = ('users',)
     768
     769        self.assertRaisesRegexp(
     770            ImproperlyConfigured,
     771            "'ValidationTestModelAdmin.list_display\[0\]', 'users' is a ManyToManyField which is not supported.",
     772            validate,
     773            ValidationTestModelAdmin,
     774            ValidationTestModel,
     775        )
     776
     777        class ValidationTestModelAdmin(ModelAdmin):
     778            list_display = ('name',)
     779
     780        validate(ValidationTestModelAdmin, ValidationTestModel)
     781
     782    def test_list_display_links_validation(self):
     783
     784        class ValidationTestModelAdmin(ModelAdmin):
     785            list_display_links = 10
     786
     787        self.assertRaisesRegexp(
     788            ImproperlyConfigured,
     789            "'ValidationTestModelAdmin.list_display_links' must be a list or tuple.",
     790            validate,
     791            ValidationTestModelAdmin,
     792            ValidationTestModel,
     793        )
     794
     795        class ValidationTestModelAdmin(ModelAdmin):
     796            list_display_links = ('non_existent_field',)
     797
     798        self.assertRaisesRegexp(
     799            ImproperlyConfigured,
     800            "'ValidationTestModelAdmin.list_display_links\[0\]' refers to 'non_existent_field' that is neither a field, method or property of model 'ValidationTestModel'.",
     801            validate,
     802            ValidationTestModelAdmin,
     803            ValidationTestModel,
     804        )
     805
     806        class ValidationTestModelAdmin(ModelAdmin):
     807            list_display_links = ('name',)
     808
     809        self.assertRaisesRegexp(
     810            ImproperlyConfigured,
     811            "'ValidationTestModelAdmin.list_display_links\[0\]'refers to 'name' which is not defined in 'list_display'.",
     812            validate,
     813            ValidationTestModelAdmin,
     814            ValidationTestModel,
     815        )
     816
     817        class ValidationTestModelAdmin(ModelAdmin):
     818            list_display = ('name',)
     819            list_display_links = ('name',)
     820
     821        validate(ValidationTestModelAdmin, ValidationTestModel)
     822
     823    def test_list_filter_validation(self):
     824
     825        class ValidationTestModelAdmin(ModelAdmin):
     826            list_filter = 10
     827
     828        self.assertRaisesRegexp(
     829            ImproperlyConfigured,
     830            "'ValidationTestModelAdmin.list_filter' must be a list or tuple.",
     831            validate,
     832            ValidationTestModelAdmin,
     833            ValidationTestModel,
     834        )
     835
     836        class ValidationTestModelAdmin(ModelAdmin):
     837            list_filter = ('non_existent_field',)
     838
     839        self.assertRaisesRegexp(
     840            ImproperlyConfigured,
     841            "'ValidationTestModelAdmin.list_filter\[0\]' refers to field 'non_existent_field' that is missing from model 'ValidationTestModel'.",
     842            validate,
     843            ValidationTestModelAdmin,
     844            ValidationTestModel,
     845        )
     846
     847        class ValidationTestModelAdmin(ModelAdmin):
     848            list_filter = ('is_active',)
     849
     850        validate(ValidationTestModelAdmin, ValidationTestModel)
     851
     852    def test_list_per_page_validation(self):
     853
     854        class ValidationTestModelAdmin(ModelAdmin):
     855            list_per_page = 'hello'
     856
     857        self.assertRaisesRegexp(
     858            ImproperlyConfigured,
     859            "'ValidationTestModelAdmin.list_per_page' should be a integer.",
     860            validate,
     861            ValidationTestModelAdmin,
     862            ValidationTestModel,
     863        )
     864
     865        class ValidationTestModelAdmin(ModelAdmin):
     866            list_per_page = 100
     867
     868        validate(ValidationTestModelAdmin, ValidationTestModel)
     869
     870    def test_search_fields_validation(self):
     871
     872        class ValidationTestModelAdmin(ModelAdmin):
     873            search_fields = 10
     874
     875        self.assertRaisesRegexp(
     876            ImproperlyConfigured,
     877            "'ValidationTestModelAdmin.search_fields' must be a list or tuple.",
     878            validate,
     879            ValidationTestModelAdmin,
     880            ValidationTestModel,
     881        )
     882
     883    def test_date_hierarchy_validation(self):
     884
     885        class ValidationTestModelAdmin(ModelAdmin):
     886            date_hierarchy = 'non_existent_field'
     887
     888        self.assertRaisesRegexp(
     889            ImproperlyConfigured,
     890            "'ValidationTestModelAdmin.date_hierarchy' refers to field 'non_existent_field' that is missing from model 'ValidationTestModel'.",
     891            validate,
     892            ValidationTestModelAdmin,
     893            ValidationTestModel,
     894        )
     895
     896        class ValidationTestModelAdmin(ModelAdmin):
     897            date_hierarchy = 'name'
     898
     899        self.assertRaisesRegexp(
     900            ImproperlyConfigured,
     901            "'ValidationTestModelAdmin.date_hierarchy is neither an instance of DateField nor DateTimeField.",
     902            validate,
     903            ValidationTestModelAdmin,
     904            ValidationTestModel,
     905        )
     906
     907        class ValidationTestModelAdmin(ModelAdmin):
     908            date_hierarchy = 'pub_date'
     909
     910        validate(ValidationTestModelAdmin, ValidationTestModel)
     911
     912    def test_ordering_validation(self):
     913
     914        class ValidationTestModelAdmin(ModelAdmin):
     915            ordering = 10
     916
     917        self.assertRaisesRegexp(
     918            ImproperlyConfigured,
     919            "'ValidationTestModelAdmin.ordering' must be a list or tuple.",
     920            validate,
     921            ValidationTestModelAdmin,
     922            ValidationTestModel,
     923        )
     924
     925        class ValidationTestModelAdmin(ModelAdmin):
     926            ordering = ('non_existent_field',)
     927
     928        self.assertRaisesRegexp(
     929            ImproperlyConfigured,
     930            "'ValidationTestModelAdmin.ordering\[0\]' refers to field 'non_existent_field' that is missing from model 'ValidationTestModel'.",
     931            validate,
     932            ValidationTestModelAdmin,
     933            ValidationTestModel,
     934        )
     935
     936        class ValidationTestModelAdmin(ModelAdmin):
     937            ordering = ('?', 'name')
     938
     939        self.assertRaisesRegexp(
     940            ImproperlyConfigured,
     941            "'ValidationTestModelAdmin.ordering' has the random ordering marker '\?', but contains other fields as well. Please either remove '\?' or the other fields.",
     942            validate,
     943            ValidationTestModelAdmin,
     944            ValidationTestModel,
     945        )
     946
     947        class ValidationTestModelAdmin(ModelAdmin):
     948            ordering = ('?',)
     949
     950        validate(ValidationTestModelAdmin, ValidationTestModel)
     951
     952        class ValidationTestModelAdmin(ModelAdmin):
     953            ordering = ('band__name',)
     954
     955        validate(ValidationTestModelAdmin, ValidationTestModel)
     956
     957        class ValidationTestModelAdmin(ModelAdmin):
     958            ordering = ('name',)
     959
     960        validate(ValidationTestModelAdmin, ValidationTestModel)
     961
     962    def test_list_select_related_validation(self):
     963
     964        class ValidationTestModelAdmin(ModelAdmin):
     965            list_select_related = 1
     966
     967        self.assertRaisesRegexp(
     968            ImproperlyConfigured,
     969            "'ValidationTestModelAdmin.list_select_related' should be a boolean.",
     970            validate,
     971            ValidationTestModelAdmin,
     972            ValidationTestModel,
     973        )
     974
     975        class ValidationTestModelAdmin(ModelAdmin):
     976            list_select_related = False
     977
     978        validate(ValidationTestModelAdmin, ValidationTestModel)
     979
     980    def test_save_as_validation(self):
     981
     982        class ValidationTestModelAdmin(ModelAdmin):
     983            save_as = 1
     984
     985        self.assertRaisesRegexp(
     986            ImproperlyConfigured,
     987            "'ValidationTestModelAdmin.save_as' should be a boolean.",
     988            validate,
     989            ValidationTestModelAdmin,
     990            ValidationTestModel,
     991        )
     992
     993        class ValidationTestModelAdmin(ModelAdmin):
     994            save_as = True
     995
     996        validate(ValidationTestModelAdmin, ValidationTestModel)
     997
     998    def test_save_on_top_validation(self):
     999
     1000        class ValidationTestModelAdmin(ModelAdmin):
     1001            save_on_top = 1
     1002
     1003        self.assertRaisesRegexp(
     1004            ImproperlyConfigured,
     1005            "'ValidationTestModelAdmin.save_on_top' should be a boolean.",
     1006            validate,
     1007            ValidationTestModelAdmin,
     1008            ValidationTestModel,
     1009        )
     1010
     1011        class ValidationTestModelAdmin(ModelAdmin):
     1012            save_on_top = True
     1013
     1014        validate(ValidationTestModelAdmin, ValidationTestModel)
     1015
     1016    def test_inlines_validation(self):
     1017
     1018        class ValidationTestModelAdmin(ModelAdmin):
     1019            inlines = 10
     1020
     1021        self.assertRaisesRegexp(
     1022            ImproperlyConfigured,
     1023            "'ValidationTestModelAdmin.inlines' must be a list or tuple.",
     1024            validate,
     1025            ValidationTestModelAdmin,
     1026            ValidationTestModel,
     1027        )
     1028
     1029        class ValidationTestInline(object):
     1030            pass
     1031
     1032        class ValidationTestModelAdmin(ModelAdmin):
     1033            inlines = [ValidationTestInline]
     1034
     1035        self.assertRaisesRegexp(
     1036            ImproperlyConfigured,
     1037            "'ValidationTestModelAdmin.inlines\[0\]' does not inherit from BaseModelAdmin.",
     1038            validate,
     1039            ValidationTestModelAdmin,
     1040            ValidationTestModel,
     1041        )
     1042
     1043        class ValidationTestInline(TabularInline):
     1044            pass
     1045
     1046        class ValidationTestModelAdmin(ModelAdmin):
     1047            inlines = [ValidationTestInline]
     1048
     1049        self.assertRaisesRegexp(
     1050            ImproperlyConfigured,
     1051            "'model' is a required attribute of 'ValidationTestModelAdmin.inlines\[0\]'.",
     1052            validate,
     1053            ValidationTestModelAdmin,
     1054            ValidationTestModel,
     1055        )
     1056
     1057        class SomethingBad(object):
     1058            pass
     1059
     1060        class ValidationTestInline(TabularInline):
     1061            model = SomethingBad
     1062
     1063        class ValidationTestModelAdmin(ModelAdmin):
     1064            inlines = [ValidationTestInline]
     1065
     1066        self.assertRaisesRegexp(
     1067            ImproperlyConfigured,
     1068            "'ValidationTestModelAdmin.inlines\[0\].model' does not inherit from models.Model.",
     1069            validate,
     1070            ValidationTestModelAdmin,
     1071            ValidationTestModel,
     1072        )
     1073
     1074        class ValidationTestInline(TabularInline):
     1075            model = ValidationTestInlineModel
     1076
     1077        class ValidationTestModelAdmin(ModelAdmin):
     1078            inlines = [ValidationTestInline]
     1079
     1080        validate(ValidationTestModelAdmin, ValidationTestModel)
     1081
     1082    def test_fields_validation(self):
     1083
     1084        class ValidationTestInline(TabularInline):
     1085            model = ValidationTestInlineModel
     1086            fields = 10
     1087
     1088        class ValidationTestModelAdmin(ModelAdmin):
     1089            inlines = [ValidationTestInline]
     1090
     1091        self.assertRaisesRegexp(
     1092            ImproperlyConfigured,
     1093            "'ValidationTestInline.fields' must be a list or tuple.",
     1094            validate,
     1095            ValidationTestModelAdmin,
     1096            ValidationTestModel,
     1097        )
     1098
     1099        class ValidationTestInline(TabularInline):
     1100            model = ValidationTestInlineModel
     1101            fields = ("non_existent_field",)
     1102
     1103        class ValidationTestModelAdmin(ModelAdmin):
     1104            inlines = [ValidationTestInline]
     1105
     1106        self.assertRaisesRegexp(
     1107            ImproperlyConfigured,
     1108            "'ValidationTestInline.fields' refers to field 'non_existent_field' that is missing from the form.",
     1109            validate,
     1110            ValidationTestModelAdmin,
     1111            ValidationTestModel,
     1112        )
     1113
     1114    def test_fk_name_validation(self):
     1115
     1116        class ValidationTestInline(TabularInline):
     1117            model = ValidationTestInlineModel
     1118            fk_name = "non_existent_field"
     1119
     1120        class ValidationTestModelAdmin(ModelAdmin):
     1121            inlines = [ValidationTestInline]
     1122
     1123        self.assertRaisesRegexp(
     1124            ImproperlyConfigured,
     1125            "'ValidationTestInline.fk_name' refers to field 'non_existent_field' that is missing from model 'ValidationTestInlineModel'.",
     1126            validate,
     1127            ValidationTestModelAdmin,
     1128            ValidationTestModel,
     1129        )
     1130
     1131        class ValidationTestInline(TabularInline):
     1132            model = ValidationTestInlineModel
     1133            fk_name = "parent"
     1134
     1135        class ValidationTestModelAdmin(ModelAdmin):
     1136            inlines = [ValidationTestInline]
     1137
     1138        validate(ValidationTestModelAdmin, ValidationTestModel)
     1139
     1140    def test_extra_validation(self):
     1141
     1142        class ValidationTestInline(TabularInline):
     1143            model = ValidationTestInlineModel
     1144            extra = "hello"
     1145
     1146        class ValidationTestModelAdmin(ModelAdmin):
     1147            inlines = [ValidationTestInline]
     1148
     1149        self.assertRaisesRegexp(
     1150            ImproperlyConfigured,
     1151            "'ValidationTestInline.extra' should be a integer.",
     1152            validate,
     1153            ValidationTestModelAdmin,
     1154            ValidationTestModel,
     1155        )
     1156
     1157        class ValidationTestInline(TabularInline):
     1158            model = ValidationTestInlineModel
     1159            extra = 2
     1160
     1161        class ValidationTestModelAdmin(ModelAdmin):
     1162            inlines = [ValidationTestInline]
     1163
     1164        validate(ValidationTestModelAdmin, ValidationTestModel)
     1165
     1166    def test_max_num_validation(self):
     1167
     1168        class ValidationTestInline(TabularInline):
     1169            model = ValidationTestInlineModel
     1170            max_num = "hello"
     1171
     1172        class ValidationTestModelAdmin(ModelAdmin):
     1173            inlines = [ValidationTestInline]
     1174
     1175        self.assertRaisesRegexp(
     1176            ImproperlyConfigured,
     1177            "'ValidationTestInline.max_num' should be an integer or None \(default\).",
     1178            validate,
     1179            ValidationTestModelAdmin,
     1180            ValidationTestModel,
     1181        )
     1182
     1183        class ValidationTestInline(TabularInline):
     1184            model = ValidationTestInlineModel
     1185            max_num = 2
     1186
     1187        class ValidationTestModelAdmin(ModelAdmin):
     1188            inlines = [ValidationTestInline]
     1189
     1190        validate(ValidationTestModelAdmin, ValidationTestModel)
     1191
     1192    def test_formset_validation(self):
     1193
     1194        class FakeFormSet(object):
     1195            pass
     1196
     1197        class ValidationTestInline(TabularInline):
     1198            model = ValidationTestInlineModel
     1199            formset = FakeFormSet
     1200
     1201        class ValidationTestModelAdmin(ModelAdmin):
     1202            inlines = [ValidationTestInline]
     1203
     1204        self.assertRaisesRegexp(
     1205            ImproperlyConfigured,
     1206            "'ValidationTestInline.formset' does not inherit from BaseModelFormSet.",
     1207            validate,
     1208            ValidationTestModelAdmin,
     1209            ValidationTestModel,
     1210        )
     1211
     1212        class RealModelFormSet(BaseModelFormSet):
     1213            pass
     1214
     1215        class ValidationTestInline(TabularInline):
     1216            model = ValidationTestInlineModel
     1217            formset = RealModelFormSet
     1218
     1219        class ValidationTestModelAdmin(ModelAdmin):
     1220            inlines = [ValidationTestInline]
     1221
     1222        validate(ValidationTestModelAdmin, ValidationTestModel)
Back to Top