1 | from django.db import models
|
---|
2 | from django.contrib import admin
|
---|
3 | from django import forms
|
---|
4 |
|
---|
5 | class Poll(models.Model):
|
---|
6 | question = models.CharField(max_length=200)
|
---|
7 | pub_date = models.DateTimeField('date published')
|
---|
8 |
|
---|
9 | class Choice(models.Model):
|
---|
10 | poll = models.ForeignKey(Poll)
|
---|
11 | choice = models.CharField(max_length=200)
|
---|
12 | votes = models.IntegerField()
|
---|
13 |
|
---|
14 |
|
---|
15 | class MyModelForm(forms.ModelForm): pass
|
---|
16 |
|
---|
17 | class MyWorkingModelFormMetaclass(forms.models.ModelFormMetaclass): #inheriting gets rid of a nasty metaclass conflict
|
---|
18 | def __new__(cls, name, bases, attrs):
|
---|
19 | formfield_callback = attrs.pop('formfield_callback',
|
---|
20 | lambda f: f.formfield())
|
---|
21 | try:
|
---|
22 | parents = [b for b in bases if issubclass(b, MyWorkingModelForm)]
|
---|
23 | except NameError:
|
---|
24 | # We are defining MyWorkingModelForm itself.
|
---|
25 | parents = None
|
---|
26 | print repr(parents)
|
---|
27 | new_class = super(MyWorkingModelFormMetaclass, cls).__new__(cls, name, bases,
|
---|
28 | attrs)
|
---|
29 | if not parents:
|
---|
30 | return new_class
|
---|
31 |
|
---|
32 | if 'media' not in attrs:
|
---|
33 | new_class.media = forms.models.media_property(new_class)
|
---|
34 | declared_fields = forms.models.get_declared_fields(bases, attrs, False)
|
---|
35 | opts = new_class._meta = forms.models.ModelFormOptions(getattr(new_class, 'Meta', None))
|
---|
36 | if opts.model:
|
---|
37 | # If a model is defined, extract form fields from it.
|
---|
38 | fields = forms.models.fields_for_model(opts.model, opts.fields,
|
---|
39 | opts.exclude, formfield_callback)
|
---|
40 | # Override default model fields with any custom declared ones
|
---|
41 | # (plus, include all the other declared fields).
|
---|
42 | fields.update(declared_fields)
|
---|
43 | else:
|
---|
44 | fields = declared_fields
|
---|
45 | new_class.declared_fields = declared_fields
|
---|
46 | new_class.base_fields = fields
|
---|
47 | return new_class
|
---|
48 |
|
---|
49 | class MyWorkingModelForm(forms.BaseModelForm):
|
---|
50 | __metaclass__ = MyWorkingModelFormMetaclass
|
---|
51 |
|
---|
52 |
|
---|
53 | class ChoiceInline(admin.StackedInline):
|
---|
54 | model = Choice
|
---|
55 | extra = 3
|
---|
56 |
|
---|
57 | class PollAdmin(admin.ModelAdmin):
|
---|
58 | # the following is the default-- I am simply making it explicit
|
---|
59 | form = forms.ModelForm
|
---|
60 |
|
---|
61 | # uncomment this to cause this to break
|
---|
62 | #form = MyModelForm
|
---|
63 |
|
---|
64 | # uncomment this to cause this to almost work again
|
---|
65 | #form = MyWorkingModelForm
|
---|
66 |
|
---|
67 | fieldsets = [
|
---|
68 | (None, {'fields': ['question']}),
|
---|
69 | ('Date information', {'fields': ['pub_date'], 'classes': ['collapse']}),
|
---|
70 | ]
|
---|
71 | inlines = [ChoiceInline]
|
---|
72 |
|
---|
73 | admin.site.register(Poll, PollAdmin)
|
---|