| 34 | | * Edit your ``mysite/urls.py`` file and uncomment the line below |
|---|
| 35 | | "Uncomment this for admin:". This file is a URLconf; we'll dig into |
|---|
| 36 | | URLconfs in the next tutorial. For now, all you need to know is that it |
|---|
| 37 | | maps URL roots to applications. |
|---|
| | 34 | * Edit your ``mysite/urls.py`` file and uncomment the lines below the |
|---|
| | 35 | "Uncomment this for admin:" comments. This file is a URLconf; we'll dig |
|---|
| | 36 | into URLconfs in the next tutorial. For now, all you need to know is that |
|---|
| | 37 | it maps URL roots to applications. |
|---|
| 76 | | make the following change to add an inner ``Admin`` class:: |
|---|
| 77 | | |
|---|
| 78 | | class Poll(models.Model): |
|---|
| 79 | | # ... |
|---|
| 80 | | class Admin: |
|---|
| 81 | | pass |
|---|
| 82 | | |
|---|
| 83 | | The ``class Admin`` will contain all the settings that control how this model |
|---|
| 84 | | appears in the Django admin. All the settings are optional, however, so |
|---|
| 85 | | creating an empty class means "give this object an admin interface using |
|---|
| 86 | | all the default options." |
|---|
| | 76 | add the following to the bottom of the file:: |
|---|
| | 77 | |
|---|
| | 78 | from django.contrib import admin |
|---|
| | 79 | |
|---|
| | 80 | admin.site.register(Poll) |
|---|
| 148 | | Take a few minutes to marvel at all the code you didn't have to write. |
|---|
| 149 | | |
|---|
| 150 | | Let's customize this a bit. We can reorder the fields by explicitly adding a |
|---|
| 151 | | ``fields`` parameter to ``Admin``:: |
|---|
| 152 | | |
|---|
| 153 | | class Admin: |
|---|
| 154 | | fields = ( |
|---|
| 155 | | (None, {'fields': ('pub_date', 'question')}), |
|---|
| 156 | | ) |
|---|
| 157 | | |
|---|
| 158 | | That made the "Publication date" show up first instead of second: |
|---|
| | 142 | Take a few minutes to marvel at all the code you didn't have to write. When you |
|---|
| | 143 | call ``admin.site.register(Poll)``, Django just lets you edit the object and |
|---|
| | 144 | "guess" at how to display it within the admin. Often you'll want to control how |
|---|
| | 145 | the admin looks and works. You'll do this by telling Django about the options |
|---|
| | 146 | you want when you register the object. |
|---|
| | 147 | |
|---|
| | 148 | Let's see how this works by reordering the fields on the edit form. Replace the |
|---|
| | 149 | ``admin.site.register(Poll)`` line with:: |
|---|
| | 150 | |
|---|
| | 151 | class PollAdmin(admin.ModelAdmin): |
|---|
| | 152 | fields = ['pub_date', 'question'] |
|---|
| | 153 | |
|---|
| | 154 | admin.site.register(Poll, PollAdmin) |
|---|
| | 155 | |
|---|
| | 156 | You'll follow this pattern -- create a model admin object, then pass it as the |
|---|
| | 157 | second argument to ``admin.site.register()`` -- any time you need to change the |
|---|
| | 158 | admin options for an object. |
|---|
| | 159 | |
|---|
| | 160 | This particular change above makes the "Publication date" come before the |
|---|
| | 161 | "Question" field: |
|---|
| 169 | | class Admin: |
|---|
| 170 | | fields = ( |
|---|
| 171 | | (None, {'fields': ('question',)}), |
|---|
| 172 | | ('Date information', {'fields': ('pub_date',)}), |
|---|
| 173 | | ) |
|---|
| 174 | | |
|---|
| 175 | | The first element of each tuple in ``fields`` is the title of the fieldset. |
|---|
| | 172 | class PollAdmin(admin.ModelAdmin): |
|---|
| | 173 | fieldsets = [ |
|---|
| | 174 | (None, {'fields': ['question']}), |
|---|
| | 175 | ('Date information', {'fields': ['pub_date']}), |
|---|
| | 176 | ] |
|---|
| | 177 | |
|---|
| | 178 | admin.site.register(Poll, PollAdmin) |
|---|
| | 179 | |
|---|
| | 180 | The first element of each tuple in ``fieldsets`` is the title of the fieldset. |
|---|
| 187 | | class Admin: |
|---|
| 188 | | fields = ( |
|---|
| 189 | | (None, {'fields': ('question',)}), |
|---|
| 190 | | ('Date information', {'fields': ('pub_date',), 'classes': 'collapse'}), |
|---|
| 191 | | ) |
|---|
| | 192 | class PollAdmin(admin.ModelAdmin): |
|---|
| | 193 | fieldsets = [ |
|---|
| | 194 | (None, {'fields': ['question']}), |
|---|
| | 195 | ('Date information', {'fields': ['pub_date'], 'classes': 'pub_date'}), |
|---|
| | 196 | ] |
|---|
| 223 | | Also note the "Add Another" link next to "Poll." Every object with a ForeignKey |
|---|
| 224 | | relationship to another gets this for free. When you click "Add Another," you'll |
|---|
| 225 | | get a popup window with the "Add poll" form. If you add a poll in that window |
|---|
| 226 | | and click "Save," Django will save the poll to the database and dynamically add |
|---|
| 227 | | it as the selected choice on the "Add choice" form you're looking at. |
|---|
| | 224 | Also note the "Add Another" link next to "Poll." Every object with a |
|---|
| | 225 | ``ForeignKey`` relationship to another gets this for free. When you click "Add |
|---|
| | 226 | Another," you'll get a popup window with the "Add poll" form. If you add a poll |
|---|
| | 227 | in that window and click "Save," Django will save the poll to the database and |
|---|
| | 228 | dynamically add it as the selected choice on the "Add choice" form you're |
|---|
| | 229 | looking at. |
|---|
| 233 | | Remove the ``Admin`` for the Choice model. Then, edit the ``ForeignKey(Poll)`` |
|---|
| 234 | | field like so:: |
|---|
| 235 | | |
|---|
| 236 | | poll = models.ForeignKey(Poll, edit_inline=models.STACKED, num_in_admin=3) |
|---|
| | 235 | Remove the ``register()`` cal for the Choice model. Then, edit the ``Poll`` |
|---|
| | 236 | registration code to read:: |
|---|
| | 237 | |
|---|
| | 238 | class ChoiceInline(admin.StackedInline): |
|---|
| | 239 | model = Choice |
|---|
| | 240 | extra = 3 |
|---|
| | 241 | |
|---|
| | 242 | class PollAdmin(admin.ModelAdmin): |
|---|
| | 243 | fieldsets = [ |
|---|
| | 244 | (None, {'fields': ['question']}), |
|---|
| | 245 | ('Date information', {'fields': ['pub_date'], 'classes': 'pub_date'}), |
|---|
| | 246 | ] |
|---|
| | 247 | inlines = [ChoiceInline] |
|---|
| | 248 | |
|---|
| | 249 | admin.site.register(Poll, PollAdmin) |
|---|
| 239 | | default, provide enough fields for 3 Choices." |
|---|
| 240 | | |
|---|
| 241 | | Then change the other fields in ``Choice`` to give them ``core=True``:: |
|---|
| 242 | | |
|---|
| 243 | | choice = models.CharField(max_length=200, core=True) |
|---|
| 244 | | votes = models.IntegerField(core=True) |
|---|
| 245 | | |
|---|
| 246 | | This tells Django: "When you edit a Choice on the Poll admin page, the 'choice' |
|---|
| 247 | | and 'votes' fields are required. The presence of at least one of them signifies |
|---|
| 248 | | the addition of a new Choice object, and clearing both of them signifies the |
|---|
| 249 | | deletion of that existing Choice object." |
|---|
| | 252 | default, provide enough fields for 3 choices." |
|---|
| 258 | | by ``num_in_admin`` -- but each time you come back to the "Change" page for an |
|---|
| 259 | | already-created object, you get one extra slot. (This means there's no |
|---|
| 260 | | hard-coded limit on how many related objects can be added.) If you wanted space |
|---|
| 261 | | for three extra Choices each time you changed the poll, you'd use |
|---|
| 262 | | ``num_extra_on_change=3``. |
|---|
| | 261 | by ``extra`` -- and each time you come back to the "Change" page for an |
|---|
| | 262 | already-created object, you get another three extra slots. |
|---|
| 266 | | alternate way of displaying inline related objects:: |
|---|
| 267 | | |
|---|
| 268 | | poll = models.ForeignKey(Poll, edit_inline=models.TABULAR, num_in_admin=3) |
|---|
| 269 | | |
|---|
| 270 | | With that ``edit_inline=models.TABULAR`` (instead of ``models.STACKED``), the |
|---|
| | 266 | tabular way of displaying inline related objects; you just need to change |
|---|
| | 267 | the ``ChoiceInline`` declaration to read:: |
|---|
| | 268 | |
|---|
| | 269 | class ChoiceInline(admin.TabularInline): |
|---|
| | 270 | #... |
|---|
| | 271 | |
|---|
| | 272 | With that ``TabularInline`` (instead of ``StackedInline``), the |
|---|
| 288 | | By default, Django displays the ``str()`` of each object. But sometimes it'd |
|---|
| 289 | | be more helpful if we could display individual fields. To do that, use the |
|---|
| 290 | | ``list_display`` option, which is a tuple of field names to display, as columns, |
|---|
| 291 | | on the change list page for the object:: |
|---|
| 292 | | |
|---|
| 293 | | class Poll(models.Model): |
|---|
| | 290 | By default, Django displays the ``str()`` of each object. But sometimes it'd be |
|---|
| | 291 | more helpful if we could display individual fields. To do that, use the |
|---|
| | 292 | ``list_display`` admin option, which is a tuple of field names to display, as |
|---|
| | 293 | columns, on the change list page for the object:: |
|---|
| | 294 | |
|---|
| | 295 | class PollAdmin(admin.ModelAdmin): |
|---|