| 262 | | Customize the admin change list |
|---|
| 263 | | =============================== |
|---|
| | 262 | Adding related objects |
|---|
| | 263 | ====================== |
|---|
| | 264 | |
|---|
| | 265 | OK, we have our Poll admin page. But a ``Poll`` has multiple ``Choices``, and the admin |
|---|
| | 266 | page doesn't display choices. |
|---|
| | 267 | |
|---|
| | 268 | Yet. |
|---|
| | 269 | |
|---|
| | 270 | In this case, there are two ways to solve this problem. The first is to give |
|---|
| | 271 | the ``Choice`` model its own ``admin`` attribute, just as we did with ``Poll``. |
|---|
| | 272 | Here's what that would look like:: |
|---|
| | 273 | |
|---|
| | 274 | class Choice(meta.Model): |
|---|
| | 275 | # ... |
|---|
| | 276 | admin = meta.Admin( |
|---|
| | 277 | fields = ( |
|---|
| | 278 | (None, {'fields': ('poll_id', 'choice', 'votes')}), |
|---|
| | 279 | ), |
|---|
| | 280 | ) |
|---|
| | 281 | |
|---|
| | 282 | (Note that we used "poll_id" to refer to the ``ForeignKey(Poll)`` field. The |
|---|
| | 283 | field name is automatically calculated from the model's class name, lowercased, |
|---|
| | 284 | plus '_id'.) |
|---|
| | 285 | |
|---|
| | 286 | Now "Choices" is an available option in the Django admin. The "Add choice" form |
|---|
| | 287 | looks like this:: |
|---|
| | 288 | |
|---|
| | 289 | .. image:: http://media.djangoproject.com/img/doc/tutorial/admin10.png |
|---|
| | 290 | :alt: Choice admin page |
|---|
| | 291 | |
|---|
| | 292 | In that form, the "Poll" field is a select box containing every poll in the |
|---|
| | 293 | database. In our case, only one poll exists at this point. |
|---|
| | 294 | |
|---|
| | 295 | Also note the "Add Another" link next to "Poll." Every object with a ForeignKey |
|---|
| | 296 | relationship to another gets this for free. When you click "Add Another," you'll |
|---|
| | 297 | get a popup window with the "Add poll" form. If you add a poll in that window |
|---|
| | 298 | and click "Save," Django will save the poll to the database and dynamically add |
|---|
| | 299 | it as the selected choice on the "Add choice" form you're looking at. |
|---|
| | 300 | |
|---|
| | 301 | But, really, this is an inefficient way of adding Choice objects to the system. |
|---|
| | 302 | It'd be better if you could add a bunch of Choices directly when you create the |
|---|
| | 303 | Poll object. Let's make that happen. |
|---|
| | 304 | |
|---|
| | 305 | Remove the ``admin`` for the Choice model. Then, edit the ``ForeignKey(Poll)`` |
|---|
| | 306 | field like so:: |
|---|
| | 307 | |
|---|
| | 308 | meta.ForeignKey(Poll, edit_inline=True, num_in_admin=3), |
|---|
| | 309 | |
|---|
| | 310 | This tells Django: "Choice objects are edited on the Poll admin page. By |
|---|
| | 311 | default, provide enough fields for 3 Choices." |
|---|
| | 312 | |
|---|
| | 313 | Then change the other fields in ``Choice`` to give them ``core=True``:: |
|---|
| | 314 | |
|---|
| | 315 | meta.CharField('choice', 'choice', maxlength=200, core=True), |
|---|
| | 316 | meta.IntegerField('votes', 'votes', core=True), |
|---|
| | 317 | |
|---|
| | 318 | This tells Django: "When you edit a Choice on the Poll admin page, the 'choice' |
|---|
| | 319 | and 'votes' fields are required. The presence of at least one of them signifies |
|---|
| | 320 | the addition of a new Choice object, and clearing at least one of them |
|---|
| | 321 | signifies the deletion of that existing Choice object." |
|---|
| | 322 | |
|---|
| | 323 | Load the "Add poll" page to see how that looks: |
|---|
| | 324 | |
|---|
| | 325 | .. image:: http://media.djangoproject.com/img/doc/tutorial/admin11t.png |
|---|
| | 326 | :alt: Add poll page now has choices on it |
|---|
| | 327 | :target: http://media.djangoproject.com/img/doc/tutorial/admin11.png |
|---|
| | 328 | |
|---|
| | 329 | It works like this: There are three slots for related Choices -- as specified |
|---|
| | 330 | by ``num_in_admin`` -- but each time you come back to the "Change" page for an |
|---|
| | 331 | already-created object, you get one extra slot. (This means there's no |
|---|
| | 332 | hard-coded limit on how many related objects can be added.) If you wanted space |
|---|
| | 333 | for three extra Choices each time you changed the poll, you'd use |
|---|
| | 334 | ``num_extra_on_change=3``. |
|---|
| | 335 | |
|---|
| | 336 | One small problem, though. It takes a lot of screen space to display all the |
|---|
| | 337 | fields for entering related Choice objects. For that reason, Django offers an |
|---|
| | 338 | alternate way of displaying inline related objects:: |
|---|
| | 339 | |
|---|
| | 340 | meta.ForeignKey(Poll, edit_inline=True, num_in_admin=3, edit_inline_type=meta.TABULAR), |
|---|
| | 341 | |
|---|
| | 342 | With that ``edit_inline_type=meta.TABULAR``, the related objects are displayed |
|---|
| | 343 | in a more compact, table-based format: |
|---|
| | 344 | |
|---|
| | 345 | .. image:: http://media.djangoproject.com/img/doc/tutorial/admin12.png |
|---|
| | 346 | :alt: Add poll page now has more compact choices |
|---|
| | 347 | |
|---|
| | 348 | More |
|---|
| | 349 | ==== |
|---|