diff --git a/info/django.info b/info/django.info index 4b338740..3552e2f4 100644 --- a/info/django.info +++ b/info/django.info @@ -1,6 +1,6 @@ This is django.info, produced by makeinfo version 6.7 from django.texi. - Django 4.0.2, March 27, 2022 + Django 4.0.2, March 29, 2022 Copyright © Django Software Foundation and contributors @@ -18,7 +18,7 @@ File: django.info, Node: Top, Next: Django documentation, Up: (dir) Django documentation contents ***************************** - Django 4.0.2, March 27, 2022 + Django 4.0.2, March 29, 2022 Copyright © Django Software Foundation and contributors @@ -61,10 +61,29 @@ Django documentation Getting started +* Django at a glance:: * Quick install guide:: +* Writing your first Django app, part 1: Writing your first Django app part 1. +* Writing your first Django app, part 2: Writing your first Django app part 2. * Writing your first Django app, part 3: Writing your first Django app part 3. * Writing your first Django app, part 4: Writing your first Django app part 4. +* Writing your first Django app, part 5: Writing your first Django app part 5. +* Writing your first Django app, part 6: Writing your first Django app part 6. +* Writing your first Django app, part 7: Writing your first Django app part 7. * Advanced tutorial; How to write reusable apps: Advanced tutorial How to write reusable apps. +* What to read next:: +* Writing your first patch for Django:: + +Django at a glance + +* Design your model:: +* Install it:: +* Enjoy the free API:: +* A dynamic admin interface; it’s not just scaffolding – it’s the whole house: A dynamic admin interface it’s not just scaffolding – it’s the whole house. +* Design your URLs:: +* Write your views:: +* Design your templates:: +* This is just the surface:: Quick install guide @@ -74,6 +93,36 @@ Quick install guide * Verifying:: * That’s it!:: +Writing your first Django app, part 1 + +* Creating a project:: +* The development server:: +* Creating the Polls app:: +* Write your first view:: + +Write your first view + +* path() argument; route: path argument route. +* path() argument; view: path argument view. +* path() argument; kwargs: path argument kwargs. +* path() argument; name: path argument name. + +Writing your first Django app, part 2 + +* Database setup:: +* Creating models:: +* Activating models:: +* Playing with the API:: +* Introducing the Django Admin:: + +Introducing the Django Admin + +* Creating an admin user:: +* Start the development server:: +* Enter the admin site:: +* Make the poll app modifiable in the admin:: +* Explore the free admin functionality:: + Writing your first Django app, part 3 * Overview:: @@ -102,6 +151,64 @@ Use generic views: Less code is better * Amend URLconf:: * Amend views:: +Writing your first Django app, part 5 + +* Introducing automated testing:: +* Basic testing strategies:: +* Writing our first test:: +* Test a view:: +* When testing, more is better: When testing more is better. +* Further testing:: +* What’s next?:: + +Introducing automated testing + +* What are automated tests?:: +* Why you need to create tests:: + +Why you need to create tests + +* Tests will save you time:: +* Tests don’t just identify problems, they prevent them: Tests don’t just identify problems they prevent them. +* Tests make your code more attractive:: +* Tests help teams work together:: + +Writing our first test + +* We identify a bug:: +* Create a test to expose the bug:: +* Running tests:: +* Fixing the bug:: +* More comprehensive tests:: + +Test a view + +* A test for a view:: +* The Django test client:: +* Improving our view:: +* Testing our new view:: +* Testing the DetailView:: +* Ideas for more tests:: + +Writing your first Django app, part 6 + +* Customize your app’s look and feel:: +* Adding a background-image:: + +Writing your first Django app, part 7 + +* Customize the admin form:: +* Adding related objects:: +* Customize the admin change list:: +* Customize the admin look and feel:: +* Customize the admin index page:: +* What’s next?: What’s next?<2>. + +Customize the admin look and feel + +* Customizing your project’s templates:: +* Customizing your application’s templates:: + Advanced tutorial: How to write reusable apps * Reusability matters:: @@ -112,12 +219,67 @@ Advanced tutorial: How to write reusable apps * Publishing your app:: * Installing Python packages with a virtual environment:: +What to read next + +* Finding documentation:: +* How the documentation is organized: How the documentation is organized<2>. +* How documentation is updated:: +* Where to get it:: +* Differences between versions:: + +Where to get it + +* On the web:: +* In plain text:: +* As HTML, locally: As HTML locally. + +Writing your first patch for Django + +* Introduction:: +* Code of Conduct:: +* Installing Git:: +* Getting a copy of Django’s development version:: +* Running Django’s test suite for the first time:: +* Working on a feature:: +* Creating a branch for your patch:: +* Writing some tests for your ticket:: +* Writing the code for your ticket:: +* Running Django’s test suite for the second time:: +* Writing Documentation:: +* Previewing your changes:: +* Committing the changes in the patch:: +* Pushing the commit and making a pull request:: +* Next steps:: + +Introduction + +* Who’s this tutorial for?:: +* What does this tutorial cover?:: + +Getting a copy of Django’s development version + +* Creating projects with a local copy of Django:: + +Writing some tests for your ticket + +* Writing a test for ticket #99999:: +* Running your new test:: + +Next steps + +* More information for new contributors:: +* Finding your first real ticket:: +* What’s next after creating a pull request?:: + Using Django +* How to install Django:: * Models and databases:: * Handling HTTP requests:: * Working with forms:: +* Templates:: * Class-based views:: +* Migrations:: * Managing files:: * Testing in Django:: * User authentication in Django:: @@ -137,6 +299,19 @@ Using Django * External packages:: * Asynchronous support: Asynchronous support<3>. +How to install Django + +* Install Python: Install Python<2>. +* Install Apache and mod_wsgi:: +* Get your database running:: +* Install the Django code:: + +Install the Django code + +* Installing an official release with pip:: +* Installing a distribution-specific package:: +* Installing the development version:: + Models and databases * Models:: @@ -583,7 +758,7 @@ Reverse resolution of URLs URL namespaces -* Introduction:: +* Introduction: Introduction<2>. * Reversing namespaced URLs:: * URL namespaces and included URLconfs:: @@ -897,6 +1072,37 @@ Media objects * Combining Media objects:: * Order of assets:: +Templates + +* The Django template language:: +* Support for template engines:: + +The Django template language + +* Syntax:: +* Components:: + +Syntax + +* Variables:: +* Tags:: +* Filters:: +* Comments:: + +Components + +* Engine:: +* Template:: +* Context:: +* Loaders:: +* Context processors:: + +Support for template engines + +* Configuration:: +* Usage:: +* Built-in backends:: + Class-based views * Introduction to class-based views:: @@ -968,6 +1174,50 @@ Subclassing generic views * Supporting other HTTP methods:: +Migrations + +* The Commands:: +* Backend Support:: +* Workflow:: +* Transactions: Transactions<2>. +* Dependencies:: +* Migration files:: +* Adding migrations to apps:: +* Reversing migrations:: +* Historical models:: +* Considerations when removing model fields:: +* Data Migrations:: +* Squashing migrations:: +* Serializing values:: +* Supporting multiple Django versions:: + +Backend Support + +* PostgreSQL:: +* MySQL:: +* SQLite:: + +Workflow + +* Version control:: + +Migration files + +* Custom fields:: +* Model managers:: +* Initial migrations:: +* History consistency:: + +Data Migrations + +* Accessing models from other apps:: +* More advanced migrations:: + +Serializing values + +* Custom serializers:: +* Adding a deconstruct() method: Adding a deconstruct method. + Managing files * Using files in models:: @@ -983,12 +1233,13 @@ File storage Testing in Django * Writing and running tests:: +* Testing tools:: * Advanced testing topics:: Writing and running tests * Writing tests:: -* Running tests:: +* Running tests: Running tests<2>. Running tests @@ -1005,6 +1256,45 @@ Speeding up the tests * Password hashing:: * Preserving the test database:: +Testing tools + +* The test client:: +* Provided test case classes:: +* Test cases features:: +* Testing asynchronous code:: +* Email services:: +* Management Commands:: +* Skipping tests:: + +The test client + +* Overview and a quick example:: +* Making requests:: +* Testing responses:: +* Exceptions:: +* Persistent state:: +* Setting the language:: +* Example: Example<7>. + +Provided test case classes + +* SimpleTestCase:: +* TransactionTestCase:: +* TestCase:: +* LiveServerTestCase:: + +Test cases features + +* Default test client:: +* Customizing the test client:: +* Fixture loading:: +* URLconf configuration:: +* Multi-database support:: +* Overriding settings:: +* Emptying the test outbox:: +* Assertions:: +* Tagging tests:: + Advanced testing topics * The request factory:: @@ -1019,7 +1309,7 @@ Advanced testing topics The request factory -* Example: Example<7>. +* Example: Example<8>. * AsyncRequestFactory:: Tests and multiple databases @@ -1049,7 +1339,7 @@ User authentication in Django * Customizing authentication in Django:: * Overview: Overview<3>. * Installation:: -* Usage:: +* Usage: Usage<2>. Using the Django authentication system @@ -1459,14 +1749,14 @@ Migration guide Database -* PostgreSQL:: +* PostgreSQL: PostgreSQL<2>. * Other databases:: FAQ * Setup:: * Troubleshooting:: -* Usage: Usage<2>. +* Usage: Usage<3>. Logging @@ -1482,7 +1772,7 @@ The cast of players * Loggers:: * Handlers:: -* Filters:: +* Filters: Filters<2>. * Formatters:: Security implications @@ -1498,7 +1788,7 @@ Configuring logging Pagination * The Paginator class:: -* Example: Example<8>. +* Example: Example<9>. * Paginating a ListView:: * Using Paginator in a view function:: @@ -1518,7 +1808,7 @@ Security in Django Performance and optimization -* Introduction: Introduction<2>. +* Introduction: Introduction<3>. * General approaches:: * Caching: Caching<2>. * Understanding laziness:: @@ -1680,7 +1970,7 @@ Writing your own checks External packages * Localflavor:: -* Comments:: +* Comments: Comments<2>. * Formtools:: Asynchronous support @@ -1708,11 +1998,13 @@ Async adapter functions * How to create custom template tags and filters:: * How to write a custom storage class:: * How to deploy Django:: +* How to upgrade Django to a newer version:: * How to manage error reporting:: * How to provide initial data for models:: * How to integrate Django with a legacy database:: * How to configure and use logging:: * How to create CSV output:: +* How to create PDF files:: * How to override templates:: * How to manage static files (e.g. images, JavaScript, CSS): How to manage static files e g images JavaScript CSS. * How to deploy static files:: @@ -1721,7 +2013,7 @@ Async adapter functions How to authenticate using REMOTE_USER -* Configuration:: +* Configuration: Configuration<2>. * Using REMOTE_USER on login pages only:: How to create custom django-admin commands @@ -1741,7 +2033,7 @@ Command objects How to create custom model fields -* Introduction: Introduction<3>. +* Introduction: Introduction<4>. * Background theory:: * Writing a field subclass:: * Writing a FileField subclass:: @@ -1937,6 +2229,15 @@ Error reporting * ADMINS and MANAGERS:: * Customize the default error views:: +How to upgrade Django to a newer version + +* Required Reading:: +* Dependencies: Dependencies<2>. +* Resolving deprecation warnings:: +* Installation: Installation<2>. +* Testing: Testing<2>. +* Deployment:: + How to manage error reporting * Email reports:: @@ -2000,6 +2301,12 @@ Using the Python CSV library * Streaming large CSV files:: +How to create PDF files + +* Install ReportLab:: +* Write your view:: +* Other formats:: + How to override templates * Overriding from the project’s templates directory:: @@ -2011,8 +2318,8 @@ How to manage static files (e.g. images, JavaScript, CSS) * Configuring static files:: * Serving static files during development:: * Serving files uploaded by a user during development:: -* Testing: Testing<2>. -* Deployment:: +* Testing: Testing<3>. +* Deployment: Deployment<2>. * Learn more:: How to deploy static files @@ -2028,7 +2335,7 @@ Serving static files in production How to install Django on Windows -* Install Python: Install Python<2>. +* Install Python: Install Python<3>. * About pip:: * Setting up a virtual environment:: * Install Django: Install Django<2>. @@ -2153,6 +2460,8 @@ API Reference * contrib packages:: * Cross Site Request Forgery protection:: * Databases: Databases<2>. +* django-admin and manage.py: django-admin and manage py. +* Running management commands from your code:: * Django Exceptions:: * File handling:: * Forms: Forms<2>. @@ -2163,9 +2472,9 @@ API Reference * Paginator:: * Request and response objects:: * SchemaEditor:: -* Settings: Settings<8>. +* Settings: Settings<9>. * Signals: Signals<3>. -* Templates: Templates<3>. +* Templates: Templates<4>. * TemplateResponse and SimpleTemplateResponse:: * Unicode data:: * django.urls utility functions: django urls utility functions. @@ -2222,7 +2531,7 @@ Core system checks * Models: Models<2>. * Security: Security<3>. * Signals: Signals<2>. -* Templates:: +* Templates: Templates<2>. * Translation: Translation<2>. * URLs:: @@ -2398,6 +2707,7 @@ contrib packages * The redirects app:: * The sitemap framework:: * The “sites” framework:: +* The staticfiles app:: * The syndication feed framework:: * admin: admin<2>. * auth: auth<2>. @@ -2581,7 +2891,7 @@ Generic relations The flatpages app -* Installation: Installation<2>. +* Installation: Installation<3>. * How it works:: * How to add, change and delete flatpages: How to add change and delete flatpages. * Flatpage templates:: @@ -2605,10 +2915,11 @@ Getting a list of FlatPage objects in your templates Integrating with django.contrib.sitemaps -* Example: Example<9>. +* Example: Example<10>. GeoDjango +* GeoDjango Tutorial:: * GeoDjango Installation:: * GeoDjango Model API:: * GeoDjango Database API:: @@ -2627,11 +2938,59 @@ GeoDjango * Testing GeoDjango apps:: * Deploying GeoDjango:: +GeoDjango Tutorial + +* Introduction: Introduction<5>. +* Setting Up:: +* Geographic Data:: +* Geographic Models:: +* Importing Spatial Data:: +* Spatial Queries:: +* Putting your data on the map:: + +Setting Up + +* Create a Spatial Database:: +* Create a New Project:: +* Configure settings.py: Configure settings py. + +Geographic Data + +* World Borders:: +* Use ogrinfo to examine spatial data:: + +Geographic Models + +* Defining a Geographic Model:: +* Run migrate:: + +Importing Spatial Data + +* GDAL Interface:: +* LayerMapping:: +* Try ogrinspect:: + +Spatial Queries + +* Spatial Lookups:: +* Automatic Spatial Transformations:: +* Lazy Geometries:: +* Geographic annotations:: + +Putting your data on the map + +* Geographic Admin:: + +Geographic Admin + +* Basics:: +* GISModelAdmin:: + GeoDjango Installation * Overview: Overview<12>. * Requirements:: -* Installation: Installation<3>. +* Installation: Installation<4>. * Troubleshooting: Troubleshooting<6>. * Platform-specific instructions:: @@ -2700,7 +3059,7 @@ Installing SpatiaLite Installing from source -* SQLite:: +* SQLite: SQLite<2>. * SpatiaLite library (libspatialite): SpatiaLite library libspatialite. macOS-specific instructions @@ -2739,7 +3098,7 @@ KyngChaos packages Windows * Python: Python<2>. -* PostgreSQL: PostgreSQL<2>. +* PostgreSQL: PostgreSQL<3>. * PostGIS:: * OSGeo4W:: * Modify Windows environment:: @@ -2787,7 +3146,7 @@ GeoDjango Database API * Spatial Backends:: * Creating and Saving Models with Geometry Fields:: * Creating and Saving Models with Raster Fields:: -* Spatial Lookups:: +* Spatial Lookups: Spatial Lookups<2>. * Distance Queries:: * Compatibility Tables:: @@ -2803,12 +3162,12 @@ Spatial Lookups Distance Queries -* Introduction: Introduction<4>. +* Introduction: Introduction<6>. * Distance Lookups:: Compatibility Tables -* Spatial Lookups: Spatial Lookups<2>. +* Spatial Lookups: Spatial Lookups<3>. * Database functions:: * Aggregate Functions:: @@ -2841,7 +3200,7 @@ Form widgets GIS QuerySet API Reference -* Spatial Lookups: Spatial Lookups<3>. +* Spatial Lookups: Spatial Lookups<4>. * Distance Lookups: Distance Lookups<2>. Spatial Lookups @@ -2933,7 +3292,7 @@ Geographic Database Functions Measurement Objects -* Example: Example<10>. +* Example: Example<11>. * Supported units:: * Measurement API:: @@ -2952,7 +3311,7 @@ GEOS API * Geometry Factories:: * I/O Objects:: * Settings: Settings<2>. -* Exceptions:: +* Exceptions: Exceptions<2>. Background @@ -3009,7 +3368,7 @@ GDAL API * Coordinate System Objects:: * Raster Data Objects:: * Settings: Settings<3>. -* Exceptions: Exceptions<2>. +* Exceptions: Exceptions<3>. Overview @@ -3062,11 +3421,11 @@ Settings Geolocation with GeoIP2 -* Example: Example<11>. +* Example: Example<12>. * API Reference: API Reference<2>. * Methods: Methods<6>. * Settings: Settings<4>. -* Exceptions: Exceptions<3>. +* Exceptions: Exceptions<4>. Methods @@ -3088,7 +3447,7 @@ GeoDjango Utilities LayerMapping data import utility -* Example: Example<12>. +* Example: Example<13>. * LayerMapping API:: * Troubleshooting: Troubleshooting<7>. @@ -3113,13 +3472,13 @@ GeoDjango Management Commands GeoDjango’s admin site -* GISModelAdmin:: +* GISModelAdmin: GISModelAdmin<2>. * GeoModelAdmin:: * OSMGeoAdmin:: Geographic Feeds -* Example: Example<13>. +* Example: Example<14>. * API Reference: API Reference<3>. API Reference @@ -3129,7 +3488,7 @@ API Reference Geographic Sitemaps -* Example: Example<14>. +* Example: Example<15>. * Reference:: Reference @@ -3159,7 +3518,7 @@ Obtaining sufficient privileges GeoDjango tests -* Example: Example<15>. +* Example: Example<16>. django.contrib.humanize @@ -3433,7 +3792,7 @@ Range validators The redirects app -* Installation: Installation<4>. +* Installation: Installation<5>. * How it works: How it works<2>. * How to add, change and delete redirects: How to add change and delete redirects. * Middleware: Middleware<3>. @@ -3446,7 +3805,7 @@ How to add, change and delete redirects The sitemap framework * Overview: Overview<14>. -* Installation: Installation<5>. +* Installation: Installation<6>. * Initialization:: * Sitemap classes:: * An example: An example<3>. @@ -3459,7 +3818,7 @@ The sitemap framework Shortcuts -* Example: Example<16>. +* Example: Example<17>. Template customization @@ -3490,6 +3849,35 @@ Example usage * Getting the current domain for display:: * Getting the current domain for full URLs:: +The staticfiles app + +* Settings: Settings<7>. +* Management Commands: Management Commands<2>. +* Storages:: +* Finders Module:: +* Other Helpers:: + +Management Commands + +* collectstatic:: +* findstatic:: +* runserver:: + +collectstatic + +* Customizing the ignored pattern list:: + +Storages + +* StaticFilesStorage:: +* ManifestStaticFilesStorage: ManifestStaticFilesStorage<2>. +* ManifestFilesMixin:: + +Other Helpers + +* Static file development view:: +* Specialized test case to support ‘live testing’:: + The syndication feed framework * The high-level framework:: @@ -3519,11 +3907,11 @@ Cross Site Request Forgery protection * Rejected requests:: * How it works: How it works<3>. * Caching: Caching<3>. -* Testing: Testing<3>. +* Testing: Testing<4>. * Limitations: Limitations<2>. * Edge cases:: * Contrib and reusable apps:: -* Settings: Settings<7>. +* Settings: Settings<8>. * Frequently Asked Questions:: How to use it @@ -3653,6 +4041,126 @@ Connecting to the database * Full DSN and Easy Connect:: +django-admin and manage.py + +* Usage: Usage<4>. +* Available commands:: +* Commands provided by applications:: +* Default options:: +* Extra niceties:: + +Usage + +* Getting runtime help:: +* App names:: +* Determining the version:: +* Displaying debug output:: + +Available commands + +* check:: +* compilemessages:: +* createcachetable:: +* dbshell:: +* diffsettings:: +* dumpdata:: +* flush:: +* inspectdb: inspectdb<2>. +* loaddata:: +* makemessages:: +* makemigrations:: +* migrate:: +* runserver: runserver<2>. +* sendtestemail:: +* shell:: +* showmigrations:: +* sqlflush:: +* sqlmigrate:: +* sqlsequencereset:: +* squashmigrations:: +* startapp:: +* startproject:: +* test:: +* testserver:: + +dumpdata + +* Fixtures compression:: + +inspectdb + +* Database-specific notes: Database-specific notes<2>. + +Database-specific notes + +* Oracle: Oracle<2>. +* PostgreSQL: PostgreSQL<4>. + +loaddata + +* What’s a “fixture”?:: +* Compressed fixtures:: +* Database-specific fixtures:: +* Loading fixtures from stdin:: + +runserver + +* Examples of using different ports and addresses:: +* Serving static files with the development server:: + +test + +* Test runner options:: + +Commands provided by applications + +* django.contrib.auth: django contrib auth<2>. +* django.contrib.contenttypes: django contrib contenttypes. +* django.contrib.gis: django contrib gis. +* django.contrib.sessions: django contrib sessions. +* django.contrib.sitemaps: django contrib sitemaps. +* django.contrib.staticfiles: django contrib staticfiles. + +django.contrib.auth + +* changepassword:: +* createsuperuser:: + +django.contrib.contenttypes + +* remove_stale_contenttypes:: + +django.contrib.gis + +* ogrinspect: ogrinspect<3>. + +django.contrib.sessions + +* clearsessions:: + +django.contrib.sitemaps + +* ping_google:: + +django.contrib.staticfiles + +* collectstatic: collectstatic<2>. +* findstatic: findstatic<2>. + +Extra niceties + +* Syntax coloring:: +* Bash completion:: + +Syntax coloring + +* Windows support:: +* Custom colors:: + +Running management commands from your code + +* Output redirection:: + Django Exceptions * Django Core Exceptions:: @@ -3978,7 +4486,7 @@ Django logging extensions * Loggers: Loggers<2>. * Handlers: Handlers<2>. -* Filters: Filters<2>. +* Filters: Filters<3>. Loggers @@ -4179,7 +4687,7 @@ Constraints reference CheckConstraint -* check:: +* check: check<2>. * name: name<3>. UniqueConstraint @@ -4608,7 +5116,7 @@ Paginator * Paginator class:: * Page class:: -* Exceptions: Exceptions<4>. +* Exceptions: Exceptions<5>. Paginator class @@ -4643,7 +5151,7 @@ QueryDict objects HttpResponse objects -* Usage: Usage<3>. +* Usage: Usage<5>. * Attributes: Attributes<8>. * Methods: Methods<11>. * HttpResponse subclasses:: @@ -4661,7 +5169,7 @@ HttpResponse subclasses JsonResponse objects -* Usage: Usage<4>. +* Usage: Usage<6>. Usage @@ -4960,8 +5468,8 @@ Core Settings Topical Index * Models: Models<4>. * Security: Security<4>. * Serialization:: -* Templates: Templates<2>. -* Testing: Testing<4>. +* Templates: Templates<3>. +* Testing: Testing<5>. * URLs: URLs<3>. Signals @@ -5005,17 +5513,17 @@ Database Wrappers Templates -* The Django template language:: +* The Django template language: The Django template language<2>. * Built-in template tags and filters:: * The Django template language; for Python programmers: The Django template language for Python programmers. The Django template language -* Templates: Templates<4>. -* Variables:: -* Filters: Filters<3>. -* Tags:: -* Comments: Comments<2>. +* Templates: Templates<5>. +* Variables: Variables<2>. +* Filters: Filters<4>. +* Tags: Tags<2>. +* Comments: Comments<3>. * Template inheritance:: * Automatic HTML escaping:: * Accessing method calls:: @@ -5074,7 +5582,7 @@ Built-in tag reference if * Boolean operators:: -* Filters: Filters<4>. +* Filters: Filters<5>. * Complex expressions:: Boolean operators @@ -5241,7 +5749,7 @@ Unicode data * Creating the database:: * General string handling:: * Models: Models<5>. -* Templates: Templates<5>. +* Templates: Templates<6>. * Files:: * Form submission:: @@ -5360,7 +5868,7 @@ API stability * What “stable” means:: * Stable APIs:: -* Exceptions: Exceptions<5>. +* Exceptions: Exceptions<6>. Exceptions @@ -5501,27 +6009,27 @@ Minor features * django.contrib.admin: django contrib admin. * django.contrib.admindocs: django contrib admindocs. -* django.contrib.auth: django contrib auth<2>. -* django.contrib.gis: django contrib gis. +* django.contrib.auth: django contrib auth<3>. +* django.contrib.gis: django contrib gis<2>. * django.contrib.postgres: django contrib postgres<2>. -* django.contrib.staticfiles: django contrib staticfiles. +* django.contrib.staticfiles: django contrib staticfiles<2>. * Cache: Cache<2>. * CSRF:: * Forms: Forms<4>. * Internationalization:: * Generic Views:: * Logging: Logging<4>. -* Management Commands:: +* Management Commands: Management Commands<3>. * Models: Models<7>. * Requests and Responses:: * Signals: Signals<4>. -* Templates: Templates<6>. +* Templates: Templates<7>. * Tests:: Backwards incompatible changes in 4.0 * Database backend API:: -* django.contrib.gis: django contrib gis<2>. +* django.contrib.gis: django contrib gis<3>. * Dropped support for PostgreSQL 9.6: Dropped support for PostgreSQL 9 6. * Dropped support for Oracle 12.2 and 18c: Dropped support for Oracle 12 2 and 18c. * CSRF_TRUSTED_ORIGINS changes:: @@ -5634,11 +6142,11 @@ What’s new in Django 3.2 Minor features * django.contrib.admin: django contrib admin<2>. -* django.contrib.auth: django contrib auth<3>. -* django.contrib.contenttypes: django contrib contenttypes. -* django.contrib.gis: django contrib gis<3>. +* django.contrib.auth: django contrib auth<4>. +* django.contrib.contenttypes: django contrib contenttypes<2>. +* django.contrib.gis: django contrib gis<4>. * django.contrib.postgres: django contrib postgres<3>. -* django.contrib.sitemaps: django contrib sitemaps. +* django.contrib.sitemaps: django contrib sitemaps<2>. * django.contrib.syndication: django contrib syndication. * Database backends:: * Decorators:: @@ -5646,15 +6154,15 @@ Minor features * File Uploads: File Uploads<2>. * Forms: Forms<5>. * Generic Views: Generic Views<2>. -* Management Commands: Management Commands<2>. -* Migrations:: +* Management Commands: Management Commands<4>. +* Migrations: Migrations<2>. * Models: Models<8>. * Pagination: Pagination<2>. * Requests and Responses: Requests and Responses<2>. * Security: Security<5>. * Serialization: Serialization<2>. * Signals: Signals<5>. -* Templates: Templates<7>. +* Templates: Templates<8>. * Tests: Tests<2>. * Utilities: Utilities<2>. * Validators: Validators<4>. @@ -5663,7 +6171,7 @@ Backwards incompatible changes in 3.2 * Database backend API: Database backend API<2>. * django.contrib.admin: django contrib admin<3>. -* django.contrib.gis: django contrib gis<4>. +* django.contrib.gis: django contrib gis<5>. * Dropped support for PostgreSQL 9.5: Dropped support for PostgreSQL 9 5. * Dropped support for MySQL 5.6: Dropped support for MySQL 5 6. * Miscellaneous: Miscellaneous<5>. @@ -5770,13 +6278,13 @@ What’s new in Django 3.1 Minor features * django.contrib.admin: django contrib admin<4>. -* django.contrib.auth: django contrib auth<4>. -* django.contrib.contenttypes: django contrib contenttypes<2>. -* django.contrib.gis: django contrib gis<5>. +* django.contrib.auth: django contrib auth<5>. +* django.contrib.contenttypes: django contrib contenttypes<3>. +* django.contrib.gis: django contrib gis<6>. * django.contrib.humanize: django contrib humanize<3>. * django.contrib.postgres: django contrib postgres<4>. -* django.contrib.sessions: django contrib sessions. -* django.contrib.staticfiles: django contrib staticfiles<2>. +* django.contrib.sessions: django contrib sessions<2>. +* django.contrib.staticfiles: django contrib staticfiles<3>. * Cache: Cache<3>. * CSRF: CSRF<2>. * Email: Email<2>. @@ -5784,12 +6292,12 @@ Minor features * File Storage:: * Forms: Forms<6>. * Internationalization: Internationalization<2>. -* Management Commands: Management Commands<3>. +* Management Commands: Management Commands<5>. * Models: Models<9>. * Pagination: Pagination<3>. * Requests and Responses: Requests and Responses<3>. * Security: Security<6>. -* Templates: Templates<8>. +* Templates: Templates<9>. * Tests: Tests<3>. * URLs: URLs<4>. * Utilities: Utilities<3>. @@ -5910,17 +6418,17 @@ What’s new in Django 3.0 Minor features * django.contrib.admin: django contrib admin<5>. -* django.contrib.auth: django contrib auth<5>. -* django.contrib.gis: django contrib gis<6>. +* django.contrib.auth: django contrib auth<6>. +* django.contrib.gis: django contrib gis<7>. * django.contrib.postgres: django contrib postgres<5>. -* django.contrib.sessions: django contrib sessions<2>. +* django.contrib.sessions: django contrib sessions<3>. * django.contrib.syndication: django contrib syndication<2>. * Cache: Cache<4>. * File Storage: File Storage<2>. * Forms: Forms<7>. * Internationalization: Internationalization<3>. * Logging: Logging<5>. -* Management Commands: Management Commands<4>. +* Management Commands: Management Commands<6>. * Models: Models<10>. * Requests and Responses: Requests and Responses<4>. * Security: Security<7>. @@ -5931,7 +6439,7 @@ Backwards incompatible changes in 3.0 * Model.save() when providing a default for the primary key: Model save when providing a default for the primary key. * Database backend API: Database backend API<4>. * django.contrib.admin: django contrib admin<6>. -* django.contrib.gis: django contrib gis<7>. +* django.contrib.gis: django contrib gis<8>. * Dropped support for PostgreSQL 9.4: Dropped support for PostgreSQL 9 4. * Dropped support for Oracle 12.1: Dropped support for Oracle 12 1. * Removed private Python 2 compatibility APIs:: @@ -6118,15 +6626,15 @@ What’s new in Django 2.2 Minor features * django.contrib.admin: django contrib admin<7>. -* django.contrib.auth: django contrib auth<6>. -* django.contrib.gis: django contrib gis<8>. +* django.contrib.auth: django contrib auth<7>. +* django.contrib.gis: django contrib gis<9>. * django.contrib.postgres: django contrib postgres<6>. -* django.contrib.staticfiles: django contrib staticfiles<3>. +* django.contrib.staticfiles: django contrib staticfiles<4>. * Database backends: Database backends<2>. * Generic Views: Generic Views<3>. * Internationalization: Internationalization<4>. -* Management Commands: Management Commands<5>. -* Migrations: Migrations<2>. +* Management Commands: Management Commands<7>. +* Migrations: Migrations<3>. * Models: Models<11>. * Requests and Responses: Requests and Responses<5>. * Serialization: Serialization<3>. @@ -6138,7 +6646,7 @@ Backwards incompatible changes in 2.2 * Database backend API: Database backend API<5>. * Admin actions are no longer collected from base ModelAdmin classes:: -* django.contrib.gis: django contrib gis<9>. +* django.contrib.gis: django contrib gis<10>. * TransactionTestCase serialized data loading:: * sqlparse is required dependency:: * cached_property aliases:: @@ -6260,24 +6768,24 @@ What’s new in Django 2.1 Minor features * django.contrib.admin: django contrib admin<8>. -* django.contrib.auth: django contrib auth<7>. -* django.contrib.gis: django contrib gis<10>. -* django.contrib.sessions: django contrib sessions<3>. +* django.contrib.auth: django contrib auth<8>. +* django.contrib.gis: django contrib gis<11>. +* django.contrib.sessions: django contrib sessions<4>. * Cache: Cache<5>. * CSRF: CSRF<3>. * Forms: Forms<8>. * Internationalization: Internationalization<5>. -* Management Commands: Management Commands<6>. -* Migrations: Migrations<3>. +* Management Commands: Management Commands<8>. +* Migrations: Migrations<4>. * Models: Models<12>. * Requests and Responses: Requests and Responses<6>. -* Templates: Templates<9>. +* Templates: Templates<10>. * Tests: Tests<6>. Backwards incompatible changes in 2.1 * Database backend API: Database backend API<6>. -* django.contrib.gis: django contrib gis<11>. +* django.contrib.gis: django contrib gis<12>. * Dropped support for MySQL 5.5: Dropped support for MySQL 5 5. * Dropped support for PostgreSQL 9.3: Dropped support for PostgreSQL 9 3. * Removed BCryptPasswordHasher from the default PASSWORD_HASHERS setting:: @@ -6391,20 +6899,20 @@ What’s new in Django 2.0 Minor features * django.contrib.admin: django contrib admin<9>. -* django.contrib.auth: django contrib auth<8>. -* django.contrib.gis: django contrib gis<12>. +* django.contrib.auth: django contrib auth<9>. +* django.contrib.gis: django contrib gis<13>. * django.contrib.postgres: django contrib postgres<7>. -* django.contrib.sitemaps: django contrib sitemaps<2>. +* django.contrib.sitemaps: django contrib sitemaps<3>. * Cache: Cache<6>. * File Storage: File Storage<3>. * Forms: Forms<9>. * Generic Views: Generic Views<4>. -* Management Commands: Management Commands<7>. -* Migrations: Migrations<4>. +* Management Commands: Management Commands<9>. +* Migrations: Migrations<5>. * Models: Models<13>. * Pagination: Pagination<4>. * Requests and Responses: Requests and Responses<7>. -* Templates: Templates<10>. +* Templates: Templates<11>. * Tests: Tests<7>. * Validators: Validators<6>. @@ -6603,9 +7111,9 @@ What’s new in Django 1.11 Minor features * django.contrib.admin: django contrib admin<10>. -* django.contrib.auth: django contrib auth<9>. -* django.contrib.contenttypes: django contrib contenttypes<3>. -* django.contrib.gis: django contrib gis<13>. +* django.contrib.auth: django contrib auth<10>. +* django.contrib.contenttypes: django contrib contenttypes<4>. +* django.contrib.gis: django contrib gis<14>. * django.contrib.postgres: django contrib postgres<8>. * Cache: Cache<7>. * CSRF: CSRF<4>. @@ -6614,19 +7122,19 @@ Minor features * File Storage: File Storage<4>. * Forms: Forms<10>. * Internationalization: Internationalization<6>. -* Management Commands: Management Commands<8>. -* Migrations: Migrations<5>. +* Management Commands: Management Commands<10>. +* Migrations: Migrations<6>. * Models: Models<14>. * Requests and Responses: Requests and Responses<8>. * Serialization: Serialization<4>. -* Templates: Templates<11>. +* Templates: Templates<12>. * Tests: Tests<8>. * Validators: Validators<7>. Backwards incompatible changes in 1.11 -* django.contrib.gis: django contrib gis<14>. -* django.contrib.staticfiles: django contrib staticfiles<4>. +* django.contrib.gis: django contrib gis<15>. +* django.contrib.staticfiles: django contrib staticfiles<5>. * Database backend API: Database backend API<8>. * Dropped support for PostgreSQL 9.2 and PostGIS 2.0: Dropped support for PostgreSQL 9 2 and PostGIS 2 0. * LiveServerTestCase binds to port zero:: @@ -6711,12 +7219,12 @@ What’s new in Django 1.10 Minor features * django.contrib.admin: django contrib admin<11>. -* django.contrib.auth: django contrib auth<10>. -* django.contrib.gis: django contrib gis<15>. +* django.contrib.auth: django contrib auth<11>. +* django.contrib.gis: django contrib gis<16>. * django.contrib.postgres: django contrib postgres<9>. -* django.contrib.sessions: django contrib sessions<4>. +* django.contrib.sessions: django contrib sessions<5>. * django.contrib.sites: django contrib sites. -* django.contrib.staticfiles: django contrib staticfiles<5>. +* django.contrib.staticfiles: django contrib staticfiles<6>. * Cache: Cache<8>. * CSRF: CSRF<5>. * Database backends: Database backends<4>. @@ -6724,12 +7232,12 @@ Minor features * Forms: Forms<11>. * Generic Views: Generic Views<5>. * Internationalization: Internationalization<7>. -* Management Commands: Management Commands<9>. -* Migrations: Migrations<6>. +* Management Commands: Management Commands<11>. +* Migrations: Migrations<7>. * Models: Models<15>. * Requests and Responses: Requests and Responses<9>. * Serialization: Serialization<5>. -* Templates: Templates<12>. +* Templates: Templates<13>. * Tests: Tests<9>. * URLs: URLs<6>. * Validators: Validators<8>. @@ -6747,7 +7255,7 @@ Backwards incompatible changes in 1.10 * Removed null assignment check for non-null foreign key fields:: * Removed weak password hashers from the default PASSWORD_HASHERS setting:: * Field.get_prep_lookup() and Field.get_db_prep_lookup() methods are removed: Field get_prep_lookup and Field get_db_prep_lookup methods are removed. -* django.contrib.gis: django contrib gis<16>. +* django.contrib.gis: django contrib gis<17>. * Maximum size of a request body and the number of GET/POST parameters is limited:: * Miscellaneous: Miscellaneous<20>. @@ -6755,7 +7263,7 @@ Features deprecated in 1.10 * Direct assignment to a reverse foreign key or many-to-many relation:: * Non-timezone-aware Storage API:: -* django.contrib.gis: django contrib gis<17>. +* django.contrib.gis: django contrib gis<18>. * CommaSeparatedIntegerField model field:: * Using a model name as a query lookup when default_related_name is set:: * __search query lookup:: @@ -6859,11 +7367,11 @@ Minor features * django.contrib.admin: django contrib admin<12>. * django.contrib.admindocs: django contrib admindocs<2>. -* django.contrib.auth: django contrib auth<11>. -* django.contrib.contenttypes: django contrib contenttypes<4>. -* django.contrib.gis: django contrib gis<18>. +* django.contrib.auth: django contrib auth<12>. +* django.contrib.contenttypes: django contrib contenttypes<5>. +* django.contrib.gis: django contrib gis<19>. * django.contrib.postgres: django contrib postgres<10>. -* django.contrib.sessions: django contrib sessions<5>. +* django.contrib.sessions: django contrib sessions<6>. * django.contrib.sites: django contrib sites<2>. * django.contrib.syndication: django contrib syndication<3>. * Cache: Cache<9>. @@ -6873,11 +7381,11 @@ Minor features * Forms: Forms<12>. * Generic Views: Generic Views<6>. * Internationalization: Internationalization<8>. -* Management Commands: Management Commands<10>. -* Migrations: Migrations<7>. +* Management Commands: Management Commands<12>. +* Migrations: Migrations<8>. * Models: Models<16>. * Requests and Responses: Requests and Responses<10>. -* Templates: Templates<13>. +* Templates: Templates<14>. * Tests: Tests<10>. * URLs: URLs<7>. * Validators: Validators<9>. @@ -7051,10 +7559,10 @@ Minor features * django.contrib.admin: django contrib admin<13>. * django.contrib.admindocs: django contrib admindocs<3>. -* django.contrib.auth: django contrib auth<12>. -* django.contrib.gis: django contrib gis<19>. -* django.contrib.sessions: django contrib sessions<6>. -* django.contrib.sitemaps: django contrib sitemaps<3>. +* django.contrib.auth: django contrib auth<13>. +* django.contrib.gis: django contrib gis<20>. +* django.contrib.sessions: django contrib sessions<7>. +* django.contrib.sitemaps: django contrib sitemaps<4>. * django.contrib.sites: django contrib sites<3>. * Cache: Cache<10>. * Cryptography:: @@ -7065,13 +7573,13 @@ Minor features * Generic Views: Generic Views<7>. * Internationalization: Internationalization<9>. * Logging: Logging<6>. -* Management Commands: Management Commands<11>. +* Management Commands: Management Commands<13>. * Middleware: Middleware<5>. -* Migrations: Migrations<8>. +* Migrations: Migrations<9>. * Models: Models<17>. * Signals: Signals<6>. * System Check Framework:: -* Templates: Templates<14>. +* Templates: Templates<15>. * Requests and Responses: Requests and Responses<11>. * Tests: Tests<11>. * Validators: Validators<10>. @@ -7091,7 +7599,7 @@ Backwards incompatible changes in 1.8 * Support for Oracle versions older than 11.1: Support for Oracle versions older than 11 1. * Specific privileges used instead of roles for tests on Oracle:: * AbstractUser.last_login allows null values: AbstractUser last_login allows null values. -* django.contrib.gis: django contrib gis<20>. +* django.contrib.gis: django contrib gis<21>. * Priority of context processors for TemplateResponse brought in line with render:: * Overriding setUpClass / tearDownClass in test cases:: * Removal of django.contrib.formtools: Removal of django contrib formtools. @@ -7247,15 +7755,15 @@ Improvements to Form error handling Minor features * django.contrib.admin: django contrib admin<15>. -* django.contrib.auth: django contrib auth<13>. +* django.contrib.auth: django contrib auth<14>. * django.contrib.formtools: django contrib formtools. -* django.contrib.gis: django contrib gis<21>. +* django.contrib.gis: django contrib gis<22>. * django.contrib.messages: django contrib messages. * django.contrib.redirects: django contrib redirects. -* django.contrib.sessions: django contrib sessions<7>. -* django.contrib.sitemaps: django contrib sitemaps<4>. +* django.contrib.sessions: django contrib sessions<8>. +* django.contrib.sitemaps: django contrib sitemaps<5>. * django.contrib.sites: django contrib sites<4>. -* django.contrib.staticfiles: django contrib staticfiles<6>. +* django.contrib.staticfiles: django contrib staticfiles<7>. * django.contrib.syndication: django contrib syndication<4>. * Cache: Cache<11>. * Cross Site Request Forgery:: @@ -7264,10 +7772,10 @@ Minor features * File Uploads: File Uploads<3>. * Forms: Forms<14>. * Internationalization: Internationalization<10>. -* Management Commands: Management Commands<12>. +* Management Commands: Management Commands<14>. * Models: Models<18>. * Signals: Signals<7>. -* Templates: Templates<15>. +* Templates: Templates<16>. * Requests and Responses: Requests and Responses<12>. * Tests: Tests<12>. * Utilities: Utilities<4>. @@ -8075,7 +8583,7 @@ Django 1.1 release notes * Backwards-incompatible changes in 1.1: Backwards-incompatible changes in 1 1. * Features deprecated in 1.1: Features deprecated in 1 1. * What’s new in Django 1.1: What’s new in Django 1 1. -* What’s next?:: +* What’s next?: What’s next?<3>. Backwards-incompatible changes in 1.1 @@ -8156,7 +8664,7 @@ Common changes * The Admin:: * URLs: URLs<8>. * Views: Views<2>. -* Templates: Templates<16>. +* Templates: Templates<17>. Models @@ -8165,7 +8673,7 @@ Models * Remove prepopulated_from:: * Remove core:: * Replace class Admin; with admin.py: Replace class Admin with admin py. -* Example: Example<17>. +* Example: Example<18>. The Admin @@ -8190,17 +8698,17 @@ Templates Less-common changes * Signals: Signals<8>. -* Comments: Comments<3>. +* Comments: Comments<4>. * Template tags: Template tags<3>. * Local flavors:: * Sessions: Sessions<4>. * Fixtures: Fixtures<2>. -* Settings: Settings<9>. +* Settings: Settings<10>. * Smaller model changes:: * Internationalization: Internationalization<11>. * HTTP request/response objects:: * Generic relations: Generic relations<2>. -* Testing: Testing<5>. +* Testing: Testing<6>. * Management commands:: * Syndication:: * Data structures:: @@ -8254,7 +8762,7 @@ Testing Management commands -* Running management commands from your code:: +* Running management commands from your code: Running management commands from your code<2>. * Subcommands must now precede options:: Syndication @@ -8848,7 +9356,9 @@ Work on the Django framework * Reporting bugs and requesting features:: * Triaging tickets:: * Writing code:: +* Writing documentation:: * Localizing Django:: +* Committing code:: Advice for new contributors @@ -8895,8 +9405,58 @@ Other triage attributes Writing code +* Coding style:: +* Unit tests:: * Submitting patches:: * Working with Git and GitHub:: +* JavaScript:: + +Coding style + +* Pre-commit checks:: +* Python style:: +* Imports:: +* Template style:: +* View style:: +* Model style:: +* Use of django.conf.settings: Use of django conf settings. +* Miscellaneous: Miscellaneous<28>. +* JavaScript style:: + +Unit tests + +* Running the unit tests:: +* Contrib apps:: +* Troubleshooting: Troubleshooting<8>. +* Tips for writing tests:: + +Running the unit tests + +* Quickstart:: +* Running tests using tox:: +* Running tests using django-docker-box:: +* Using another settings module:: +* Running only some of the tests:: +* Running the Selenium tests:: +* Running all the tests:: +* Code coverage:: + +Running tests using tox + +* Testing other Python versions and database backends:: +* Running the JavaScript tests:: + +Troubleshooting + +* Test suite hangs or shows failures on main branch:: +* Many test failures with UnicodeEncodeError:: +* Tests that only fail in combination:: +* Seeing the SQL queries run during a test:: +* Seeing the full traceback of a test failure:: + +Tips for writing tests + +* Isolating model registration:: Submitting patches @@ -8924,7 +9484,7 @@ Patch review checklist Working with Git and GitHub -* Installing Git:: +* Installing Git: Installing Git<2>. * Setting up local repository:: * Working on a ticket:: * Working on a patch:: @@ -8937,12 +9497,52 @@ Working on a ticket * After upstream has changed:: * After review:: +JavaScript + +* Code style:: +* JavaScript patches: JavaScript patches<2>. +* JavaScript tests:: + +JavaScript tests + +* Writing tests: Writing tests<3>. +* Running tests: Running tests<3>. + +Running tests + +* Testing from a web browser:: +* Testing from the command line:: + +Writing documentation + +* Getting the raw documentation:: +* Getting started with Sphinx:: +* How the documentation is organized: How the documentation is organized<3>. +* Writing style:: +* Commonly used terms:: +* Django-specific terminology:: +* Guidelines for reStructuredText files:: +* Django-specific markup:: +* Documenting new features:: +* Minimizing images:: +* An example: An example<4>. +* Spelling check:: +* Link check:: +* Translating documentation:: +* django-admin man page:: + Localizing Django * Translations:: * Formats:: * Documentation: Documentation<2>. +Committing code + +* Handling pull requests:: +* Committing guidelines:: +* Reverting commits:: + Mailing lists * django-users:: @@ -9026,7 +9626,7 @@ The Django source code repository * High-level overview:: * The main branch:: * Stable branches:: -* Tags: Tags<2>. +* Tags: Tags<3>. Tags @@ -9081,15 +9681,16 @@ File: django.info, Node: First steps, Next: Getting help, Up: Django document Are you new to Django or to programming? This is the place to start! - * `From scratch:' Overview | *note Installation: 81. + * `From scratch:' *note Overview: 88. | *note Installation: 89. - * `Tutorial:' Part 1: Requests and responses | Part 2: Models and the - admin site | *note Part 3; Views and templates: 82. | *note Part 4; - Forms and generic views: 83. | Part 5: Testing | Part 6: Static - files | Part 7: Customizing the admin site + * `Tutorial:' *note Part 1; Requests and responses: 8a. | *note Part + 2; Models and the admin site: 8b. | *note Part 3; Views and + templates: 8c. | *note Part 4; Forms and generic views: 8d. | *note + Part 5; Testing: 8e. | *note Part 6; Static files: 8f. | *note Part + 7; Customizing the admin site: 90. - * `Advanced Tutorials:' *note How to write reusable apps: 84. | - Writing your first patch for Django + * `Advanced Tutorials:' *note How to write reusable apps: 91. | *note + Writing your first patch for Django: 92.  File: django.info, Node: Getting help, Next: How the documentation is organized, Prev: First steps, Up: Django documentation @@ -9099,12 +9700,12 @@ File: django.info, Node: Getting help, Next: How the documentation is organize Having trouble? We’d like to help! - * Try the *note FAQ: 86. – it’s got answers to many common questions. + * Try the *note FAQ: 94. – it’s got answers to many common questions. * Looking for specific information? Try the genindex, modindex or - the *note detailed table of contents: 7c. + the *note detailed table of contents: 83. - * Not found anything? See *note FAQ; Getting Help: 87. for + * Not found anything? See *note FAQ; Getting Help: 95. for information on getting support and asking questions to the community. @@ -9123,21 +9724,21 @@ File: django.info, Node: How the documentation is organized, Next: The model l Django has a lot of documentation. A high-level overview of how it’s organized will help you know where to look for certain things: - * *note Tutorials: 8a. take you by the hand through a series of steps + * *note Tutorials: 98. take you by the hand through a series of steps to create a web application. Start here if you’re new to Django or web application development. Also look at the “*note First steps: - 8b.”. + 99.”. - * *note Topic guides: 8c. discuss key topics and concepts at a fairly + * *note Topic guides: 9a. discuss key topics and concepts at a fairly high level and provide useful background information and explanation. - * *note Reference guides: 8d. contain technical reference for APIs + * *note Reference guides: 9b. contain technical reference for APIs and other aspects of Django’s machinery. They describe how it works and how to use it but assume that you have a basic understanding of key concepts. - * *note How-to guides: 8e. are recipes. They guide you through the + * *note How-to guides: 9c. are recipes. They guide you through the steps involved in addressing key problems and use-cases. They are more advanced than tutorials and assume some knowledge of how Django works. @@ -9152,29 +9753,29 @@ Django provides an abstraction layer (the “models”) for structuring and manipulating the data of your web application. Learn more about it below: - * `Models:' *note Introduction to models: 90. | *note Field types: - 91. | *note Indexes: 92. | *note Meta options: 93. | *note Model - class: 94. + * `Models:' *note Introduction to models: 9e. | *note Field types: + 9f. | *note Indexes: a0. | *note Meta options: a1. | *note Model + class: a2. - * `QuerySets:' *note Making queries: 95. | *note QuerySet method - reference: 96. | *note Lookup expressions: 97. + * `QuerySets:' *note Making queries: a3. | *note QuerySet method + reference: a4. | *note Lookup expressions: a5. - * `Model instances:' *note Instance methods: 98. | *note Accessing - related objects: 99. + * `Model instances:' *note Instance methods: a6. | *note Accessing + related objects: a7. - * `Migrations:' Introduction to Migrations | *note Operations - reference: 9a. | *note SchemaEditor: 9b. | *note Writing - migrations: 9c. + * `Migrations:' *note Introduction to Migrations: a8. | *note + Operations reference: a9. | *note SchemaEditor: aa. | *note Writing + migrations: ab. - * `Advanced:' *note Managers: 9d. | *note Raw SQL: 9e. | *note - Transactions: 9f. | *note Aggregation: a0. | *note Search: a1. | - *note Custom fields: a2. | *note Multiple databases: a3. | *note - Custom lookups: a4. | *note Query Expressions: a5. | *note - Conditional Expressions: a6. | *note Database Functions: a7. + * `Advanced:' *note Managers: ac. | *note Raw SQL: ad. | *note + Transactions: ae. | *note Aggregation: af. | *note Search: b0. | + *note Custom fields: b1. | *note Multiple databases: b2. | *note + Custom lookups: b3. | *note Query Expressions: b4. | *note + Conditional Expressions: b5. | *note Database Functions: b6. - * `Other:' *note Supported databases: a8. | *note Legacy databases: - a9. | *note Providing initial data: aa. | *note Optimize database - access: ab. | *note PostgreSQL specific features: ac. + * `Other:' *note Supported databases: b7. | *note Legacy databases: + b8. | *note Providing initial data: b9. | *note Optimize database + access: ba. | *note PostgreSQL specific features: bb.  File: django.info, Node: The view layer, Next: The template layer, Prev: The model layer, Up: Django documentation @@ -9186,25 +9787,25 @@ Django has the concept of “views” to encapsulate the logic responsible for processing a user’s request and for returning the response. Find all you need to know about views via the links below: - * `The basics:' *note URLconfs: ae. | *note View functions: af. | - *note Shortcuts: b0. | *note Decorators: b1. | *note Asynchronous - Support: b2. + * `The basics:' *note URLconfs: bd. | *note View functions: be. | + *note Shortcuts: bf. | *note Decorators: c0. | *note Asynchronous + Support: c1. - * `Reference:' *note Built-in Views: b3. | *note Request/response - objects: b4. | *note TemplateResponse objects: b5. + * `Reference:' *note Built-in Views: c2. | *note Request/response + objects: c3. | *note TemplateResponse objects: c4. - * `File uploads:' *note Overview: b6. | *note File objects: b7. | - *note Storage API: b8. | *note Managing files: b9. | *note Custom - storage: ba. + * `File uploads:' *note Overview: c5. | *note File objects: c6. | + *note Storage API: c7. | *note Managing files: c8. | *note Custom + storage: c9. - * `Class-based views:' *note Overview: bb. | *note Built-in display - views: bc. | *note Built-in editing views: bd. | *note Using - mixins: be. | *note API reference: bf. | *note Flattened index: c0. + * `Class-based views:' *note Overview: ca. | *note Built-in display + views: cb. | *note Built-in editing views: cc. | *note Using + mixins: cd. | *note API reference: ce. | *note Flattened index: cf. - * `Advanced:' *note Generating CSV: c1. | Generating PDF + * `Advanced:' *note Generating CSV: d0. | *note Generating PDF: d1. - * `Middleware:' *note Overview: c2. | *note Built-in middleware - classes: c3. + * `Middleware:' *note Overview: d2. | *note Built-in middleware + classes: d3.  File: django.info, Node: The template layer, Next: Forms, Prev: The view layer, Up: Django documentation @@ -9216,13 +9817,13 @@ The template layer provides a designer-friendly syntax for rendering the information to be presented to the user. Learn how this syntax can be used by designers and how it can be extended by programmers: - * `The basics:' Overview + * `The basics:' *note Overview: d5. - * `For designers:' *note Language overview: c5. | *note Built-in tags - and filters: c6. | *note Humanization: c7. + * `For designers:' *note Language overview: d6. | *note Built-in tags + and filters: d7. | *note Humanization: d8. - * `For programmers:' *note Template API: c8. | *note Custom tags and - filters: c9. | *note Custom template backend: ca. + * `For programmers:' *note Template API: d9. | *note Custom tags and + filters: da. | *note Custom template backend: db.  File: django.info, Node: Forms, Next: The development process, Prev: The template layer, Up: Django documentation @@ -9233,11 +9834,11 @@ File: django.info, Node: Forms, Next: The development process, Prev: The temp Django provides a rich framework to facilitate the creation of forms and the manipulation of form data. - * `The basics:' *note Overview: cc. | *note Form API: cd. | *note - Built-in fields: ce. | *note Built-in widgets: cf. + * `The basics:' *note Overview: dd. | *note Form API: de. | *note + Built-in fields: df. | *note Built-in widgets: e0. - * `Advanced:' *note Forms for models: d0. | *note Integrating media: - d1. | *note Formsets: d2. | *note Customizing validation: d3. + * `Advanced:' *note Forms for models: e1. | *note Integrating media: + e2. | *note Formsets: e3. | *note Customizing validation: e4.  File: django.info, Node: The development process, Next: The admin, Prev: Forms, Up: Django documentation @@ -9248,22 +9849,23 @@ File: django.info, Node: The development process, Next: The admin, Prev: Form Learn about the various components and tools to help you in the development and testing of Django applications: - * `Settings:' *note Overview: d5. | *note Full list of settings: d6. + * `Settings:' *note Overview: e6. | *note Full list of settings: e7. - * `Applications:' *note Overview: d7. + * `Applications:' *note Overview: e8. - * `Exceptions:' *note Overview: d8. + * `Exceptions:' *note Overview: e9. - * `django-admin and manage.py:' Overview | *note Adding custom - commands: d9. + * `django-admin and manage.py:' *note Overview: ea. | *note Adding + custom commands: eb. - * `Testing:' *note Introduction: da. | *note Writing and running - tests: db. | Included testing tools | *note Advanced topics: dc. + * `Testing:' *note Introduction: ec. | *note Writing and running + tests: ed. | *note Included testing tools: ee. | *note Advanced + topics: ef. - * `Deployment:' *note Overview: dd. | *note WSGI servers: de. | *note - ASGI servers: df. | *note Deploying static files: e0. | *note - Tracking code errors by email: e1. | *note Deployment checklist: - e2. + * `Deployment:' *note Overview: f0. | *note WSGI servers: f1. | *note + ASGI servers: f2. | *note Deploying static files: f3. | *note + Tracking code errors by email: f4. | *note Deployment checklist: + f5.  File: django.info, Node: The admin, Next: Security, Prev: The development process, Up: Django documentation @@ -9274,11 +9876,11 @@ File: django.info, Node: The admin, Next: Security, Prev: The development pro Find all you need to know about the automated admin interface, one of Django’s most popular features: - * *note Admin site: e4. + * *note Admin site: f7. - * *note Admin actions: e5. + * *note Admin actions: f8. - * *note Admin documentation generator: e6. + * *note Admin documentation generator: f9.  File: django.info, Node: Security, Next: Internationalization and localization, Prev: The admin, Up: Django documentation @@ -9290,17 +9892,17 @@ Security is a topic of paramount importance in the development of web applications and Django provides multiple protection tools and mechanisms: - * *note Security overview: e8. + * *note Security overview: fb. - * *note Disclosed security issues in Django: e9. + * *note Disclosed security issues in Django: fc. - * *note Clickjacking protection: ea. + * *note Clickjacking protection: fd. - * *note Cross Site Request Forgery protection: eb. + * *note Cross Site Request Forgery protection: fe. - * *note Cryptographic signing: ec. + * *note Cryptographic signing: ff. - * *note Security Middleware: ed. + * *note Security Middleware: 100.  File: django.info, Node: Internationalization and localization, Next: Performance and optimization, Prev: Security, Up: Django documentation @@ -9312,11 +9914,11 @@ Django offers a robust internationalization and localization framework to assist you in the development of applications for multiple languages and world regions: - * *note Overview: ef. | *note Internationalization: f0. | *note - Localization: f1. | *note Localized web UI formatting and form - input: f2. + * *note Overview: 102. | *note Internationalization: 103. | *note + Localization: 104. | *note Localized web UI formatting and form + input: 105. - * *note Time zones: f3. + * *note Time zones: 106.  File: django.info, Node: Performance and optimization, Next: Geographic framework, Prev: Internationalization and localization, Up: Django documentation @@ -9327,7 +9929,7 @@ File: django.info, Node: Performance and optimization, Next: Geographic framew There are a variety of techniques and tools that can help get your code running more efficiently - faster, and using fewer system resources. - * *note Performance and optimization overview: f5. + * *note Performance and optimization overview: 108.  File: django.info, Node: Geographic framework, Next: Common web application tools, Prev: Performance and optimization, Up: Django documentation @@ -9335,7 +9937,7 @@ File: django.info, Node: Geographic framework, Next: Common web application to 1.13 Geographic framework ========================= -*note GeoDjango: f7. intends to be a world-class geographic web +*note GeoDjango: 10a. intends to be a world-class geographic web framework. Its goal is to make it as easy as possible to build GIS web applications and harness the power of spatially enabled data. @@ -9348,31 +9950,31 @@ File: django.info, Node: Common web application tools, Next: Other core functi Django offers multiple tools commonly needed in the development of web applications: - * `Authentication:' *note Overview: f9. | *note Using the - authentication system: fa. | *note Password management: fb. | *note - Customizing authentication: fc. | *note API Reference: fd. + * `Authentication:' *note Overview: 10c. | *note Using the + authentication system: 10d. | *note Password management: 10e. | + *note Customizing authentication: 10f. | *note API Reference: 110. - * *note Caching: fe. + * *note Caching: 111. - * *note Logging: ff. + * *note Logging: 112. - * *note Sending emails: 100. + * *note Sending emails: 113. - * *note Syndication feeds (RSS/Atom): 101. + * *note Syndication feeds (RSS/Atom): 114. - * *note Pagination: 102. + * *note Pagination: 115. - * *note Messages framework: 103. + * *note Messages framework: 116. - * *note Serialization: 104. + * *note Serialization: 117. - * *note Sessions: 105. + * *note Sessions: 118. - * *note Sitemaps: 106. + * *note Sitemaps: 119. - * Static files management + * *note Static files management: 11a. - * *note Data validation: 107. + * *note Data validation: 11b.  File: django.info, Node: Other core functionalities, Next: The Django open-source project, Prev: Common web application tools, Up: Django documentation @@ -9382,21 +9984,21 @@ File: django.info, Node: Other core functionalities, Next: The Django open-sou Learn about some other core functionalities of the Django framework: - * *note Conditional content processing: 109. + * *note Conditional content processing: 11d. - * *note Content types and generic relations: 10a. + * *note Content types and generic relations: 11e. - * *note Flatpages: 10b. + * *note Flatpages: 11f. - * *note Redirects: 10c. + * *note Redirects: 120. - * *note Signals: 10d. + * *note Signals: 121. - * *note System check framework: 10e. + * *note System check framework: 122. - * *note The sites framework: 10f. + * *note The sites framework: 123. - * *note Unicode in Django: 110. + * *note Unicode in Django: 124.  File: django.info, Node: The Django open-source project, Prev: Other core functionalities, Up: Django documentation @@ -9407,19 +10009,19 @@ File: django.info, Node: The Django open-source project, Prev: Other core func Learn about the development process for the Django project itself and about how you can contribute: - * `Community:' *note How to get involved: 112. | *note The release - process: 113. | *note Team organization: 114. | *note The Django - source code repository: 115. | *note Security policies: 116. | - *note Mailing lists: 117. + * `Community:' *note How to get involved: 126. | *note The release + process: 127. | *note Team organization: 128. | *note The Django + source code repository: 129. | *note Security policies: 12a. | + *note Mailing lists: 12b. - * `Design philosophies:' *note Overview: 118. + * `Design philosophies:' *note Overview: 12c. - * `Documentation:' About this documentation + * `Documentation:' *note About this documentation: 12d. - * `Third-party distributions:' *note Overview: 119. + * `Third-party distributions:' *note Overview: 12e. - * `Django over time:' *note API stability: 11a. | *note Release notes - and upgrading instructions: 11b. | *note Deprecation Timeline: 11c. + * `Django over time:' *note API stability: 12f. | *note Release notes + and upgrading instructions: 130. | *note Deprecation Timeline: 131.  File: django.info, Node: Getting started, Next: Using Django, Prev: Django documentation, Up: Top @@ -9432,21 +10034,420 @@ right place: read this material to quickly get up and running. * Menu: +* Django at a glance:: * Quick install guide:: +* Writing your first Django app, part 1: Writing your first Django app part 1. +* Writing your first Django app, part 2: Writing your first Django app part 2. * Writing your first Django app, part 3: Writing your first Django app part 3. * Writing your first Django app, part 4: Writing your first Django app part 4. +* Writing your first Django app, part 5: Writing your first Django app part 5. +* Writing your first Django app, part 6: Writing your first Django app part 6. +* Writing your first Django app, part 7: Writing your first Django app part 7. * Advanced tutorial; How to write reusable apps: Advanced tutorial How to write reusable apps. +* What to read next:: +* Writing your first patch for Django::  -File: django.info, Node: Quick install guide, Next: Writing your first Django app part 3, Up: Getting started +File: django.info, Node: Django at a glance, Next: Quick install guide, Up: Getting started -2.1 Quick install guide +2.1 Django at a glance +====================== + +Because Django was developed in a fast-paced newsroom environment, it +was designed to make common web development tasks fast and easy. Here’s +an informal overview of how to write a database-driven web app with +Django. + +The goal of this document is to give you enough technical specifics to +understand how Django works, but this isn’t intended to be a tutorial or +reference – but we’ve got both! When you’re ready to start a project, +you can *note start with the tutorial: 8a. or *note dive right into more +detailed documentation: 9a. + +* Menu: + +* Design your model:: +* Install it:: +* Enjoy the free API:: +* A dynamic admin interface; it’s not just scaffolding – it’s the whole house: A dynamic admin interface it’s not just scaffolding – it’s the whole house. +* Design your URLs:: +* Write your views:: +* Design your templates:: +* This is just the surface:: + + +File: django.info, Node: Design your model, Next: Install it, Up: Django at a glance + +2.1.1 Design your model +----------------------- + +Although you can use Django without a database, it comes with an +object-relational mapper(1) in which you describe your database layout +in Python code. + +The *note data-model syntax: 9e. offers many rich ways of representing +your models – so far, it’s been solving many years’ worth of +database-schema problems. Here’s a quick example: + + from django.db import models + + class Reporter(models.Model): + full_name = models.CharField(max_length=70) + + def __str__(self): + return self.full_name + + class Article(models.Model): + pub_date = models.DateField() + headline = models.CharField(max_length=200) + content = models.TextField() + reporter = models.ForeignKey(Reporter, on_delete=models.CASCADE) + + def __str__(self): + return self.headline + +LiteralBlock: mysite/news/models.py + + ---------- Footnotes ---------- + + (1) https://en.wikipedia.org/wiki/Object-relational_mapping + + +File: django.info, Node: Install it, Next: Enjoy the free API, Prev: Design your model, Up: Django at a glance + +2.1.2 Install it +---------------- + +Next, run the Django command-line utilities to create the database +tables automatically: + + $ python manage.py makemigrations + $ python manage.py migrate + +The *note makemigrations: 136. command looks at all your available +models and creates migrations for whichever tables don’t already exist. +*note migrate: 137. runs the migrations and creates tables in your +database, as well as optionally providing *note much richer schema +control: a8. + + +File: django.info, Node: Enjoy the free API, Next: A dynamic admin interface it’s not just scaffolding – it’s the whole house, Prev: Install it, Up: Django at a glance + +2.1.3 Enjoy the free API +------------------------ + +With that, you’ve got a free, and rich, *note Python API: a3. to access +your data. The API is created on the fly, no code generation necessary: + + # Import the models we created from our "news" app + >>> from news.models import Article, Reporter + + # No reporters are in the system yet. + >>> Reporter.objects.all() + + + # Create a new Reporter. + >>> r = Reporter(full_name='John Smith') + + # Save the object into the database. You have to call save() explicitly. + >>> r.save() + + # Now it has an ID. + >>> r.id + 1 + + # Now the new reporter is in the database. + >>> Reporter.objects.all() + ]> + + # Fields are represented as attributes on the Python object. + >>> r.full_name + 'John Smith' + + # Django provides a rich database lookup API. + >>> Reporter.objects.get(id=1) + + >>> Reporter.objects.get(full_name__startswith='John') + + >>> Reporter.objects.get(full_name__contains='mith') + + >>> Reporter.objects.get(id=2) + Traceback (most recent call last): + ... + DoesNotExist: Reporter matching query does not exist. + + # Create an article. + >>> from datetime import date + >>> a = Article(pub_date=date.today(), headline='Django is cool', + ... content='Yeah.', reporter=r) + >>> a.save() + + # Now the article is in the database. + >>> Article.objects.all() + ]> + + # Article objects get API access to related Reporter objects. + >>> r = a.reporter + >>> r.full_name + 'John Smith' + + # And vice versa: Reporter objects get API access to Article objects. + >>> r.article_set.all() + ]> + + # The API follows relationships as far as you need, performing efficient + # JOINs for you behind the scenes. + # This finds all articles by a reporter whose name starts with "John". + >>> Article.objects.filter(reporter__full_name__startswith='John') + ]> + + # Change an object by altering its attributes and calling save(). + >>> r.full_name = 'Billy Goat' + >>> r.save() + + # Delete an object with delete(). + >>> r.delete() + + +File: django.info, Node: A dynamic admin interface it’s not just scaffolding – it’s the whole house, Next: Design your URLs, Prev: Enjoy the free API, Up: Django at a glance + +2.1.4 A dynamic admin interface: it’s not just scaffolding – it’s the whole house +--------------------------------------------------------------------------------- + +Once your models are defined, Django can automatically create a +professional, production ready *note administrative interface: f7. – a +website that lets authenticated users add, change and delete objects. +The only step required is to register your model in the admin site: + + from django.db import models + + class Article(models.Model): + pub_date = models.DateField() + headline = models.CharField(max_length=200) + content = models.TextField() + reporter = models.ForeignKey(Reporter, on_delete=models.CASCADE) + +LiteralBlock: mysite/news/models.py + + from django.contrib import admin + + from . import models + + admin.site.register(models.Article) + +LiteralBlock: mysite/news/admin.py + +The philosophy here is that your site is edited by a staff, or a client, +or maybe just you – and you don’t want to have to deal with creating +backend interfaces only to manage content. + +One typical workflow in creating Django apps is to create models and get +the admin sites up and running as fast as possible, so your staff (or +clients) can start populating data. Then, develop the way data is +presented to the public. + + +File: django.info, Node: Design your URLs, Next: Write your views, Prev: A dynamic admin interface it’s not just scaffolding – it’s the whole house, Up: Django at a glance + +2.1.5 Design your URLs +---------------------- + +A clean, elegant URL scheme is an important detail in a high-quality web +application. Django encourages beautiful URL design and doesn’t put any +cruft in URLs, like ‘.php’ or ‘.asp’. + +To design URLs for an app, you create a Python module called a *note +URLconf: bd. A table of contents for your app, it contains a mapping +between URL patterns and Python callback functions. URLconfs also serve +to decouple URLs from Python code. + +Here’s what a URLconf might look like for the ‘Reporter’/‘Article’ +example above: + + from django.urls import path + + from . import views + + urlpatterns = [ + path('articles//', views.year_archive), + path('articles///', views.month_archive), + path('articles////', views.article_detail), + ] + +LiteralBlock: mysite/news/urls.py + +The code above maps URL paths to Python callback functions (“views”). +The path strings use parameter tags to “capture” values from the URLs. +When a user requests a page, Django runs through each path, in order, +and stops at the first one that matches the requested URL. (If none of +them matches, Django calls a special-case 404 view.) This is blazingly +fast, because the paths are compiled into regular expressions at load +time. + +Once one of the URL patterns matches, Django calls the given view, which +is a Python function. Each view gets passed a request object – which +contains request metadata – and the values captured in the pattern. + +For example, if a user requested the URL “/articles/2005/05/39323/”, +Django would call the function ‘news.views.article_detail(request, +year=2005, month=5, pk=39323)’. + + +File: django.info, Node: Write your views, Next: Design your templates, Prev: Design your URLs, Up: Django at a glance + +2.1.6 Write your views +---------------------- + +Each view is responsible for doing one of two things: Returning an *note +HttpResponse: 13c. object containing the content for the requested page, +or raising an exception such as *note Http404: 13d. The rest is up to +you. + +Generally, a view retrieves data according to the parameters, loads a +template and renders the template with the retrieved data. Here’s an +example view for ‘year_archive’ from above: + + from django.shortcuts import render + + from .models import Article + + def year_archive(request, year): + a_list = Article.objects.filter(pub_date__year=year) + context = {'year': year, 'article_list': a_list} + return render(request, 'news/year_archive.html', context) + +LiteralBlock: mysite/news/views.py + +This example uses Django’s *note template system: d5, which has several +powerful features but strives to stay simple enough for non-programmers +to use. + + +File: django.info, Node: Design your templates, Next: This is just the surface, Prev: Write your views, Up: Django at a glance + +2.1.7 Design your templates +--------------------------- + +The code above loads the ‘news/year_archive.html’ template. + +Django has a template search path, which allows you to minimize +redundancy among templates. In your Django settings, you specify a list +of directories to check for templates with *note DIRS: 13f. If a +template doesn’t exist in the first directory, it checks the second, and +so on. + +Let’s say the ‘news/year_archive.html’ template was found. Here’s what +that might look like: + + {% extends "base.html" %} + + {% block title %}Articles for {{ year }}{% endblock %} + + {% block content %} +

Articles for {{ year }}

+ + {% for article in article_list %} +

{{ article.headline }}

+

By {{ article.reporter.full_name }}

+

Published {{ article.pub_date|date:"F j, Y" }}

+ {% endfor %} + {% endblock %} + +LiteralBlock: mysite/news/templates/news/year_archive.html + +Variables are surrounded by double-curly braces. ‘{{ article.headline +}}’ means “Output the value of the article’s headline attribute.” But +dots aren’t used only for attribute lookup. They also can do +dictionary-key lookup, index lookup and function calls. + +Note ‘{{ article.pub_date|date:"F j, Y" }}’ uses a Unix-style “pipe” +(the “|” character). This is called a template filter, and it’s a way +to filter the value of a variable. In this case, the date filter +formats a Python datetime object in the given format (as found in PHP’s +date function). + +You can chain together as many filters as you’d like. You can write +*note custom template filters: 140. You can write *note custom template +tags: da, which run custom Python code behind the scenes. + +Finally, Django uses the concept of “template inheritance”. That’s what +the ‘{% extends "base.html" %}’ does. It means “First load the template +called ‘base’, which has defined a bunch of blocks, and fill the blocks +with the following blocks.” In short, that lets you dramatically cut +down on redundancy in templates: each template has to define only what’s +unique to that template. + +Here’s what the “base.html” template, including the use of *note static +files: 141, might look like: + + {% load static %} + + + {% block title %}{% endblock %} + + + Logo + {% block content %}{% endblock %} + + + +LiteralBlock: mysite/templates/base.html + +Simplistically, it defines the look-and-feel of the site (with the +site’s logo), and provides “holes” for child templates to fill. This +means that a site redesign can be done by changing a single file – the +base template. + +It also lets you create multiple versions of a site, with different base +templates, while reusing child templates. Django’s creators have used +this technique to create strikingly different mobile versions of sites +by only creating a new base template. + +Note that you don’t have to use Django’s template system if you prefer +another system. While Django’s template system is particularly +well-integrated with Django’s model layer, nothing forces you to use it. +For that matter, you don’t have to use Django’s database API, either. +You can use another database abstraction layer, you can read XML files, +you can read files off disk, or anything you want. Each piece of Django +– models, views, templates – is decoupled from the next. + + +File: django.info, Node: This is just the surface, Prev: Design your templates, Up: Django at a glance + +2.1.8 This is just the surface +------------------------------ + +This has been only a quick overview of Django’s functionality. Some +more useful features: + + * A *note caching framework: 111. that integrates with memcached or + other backends. + + * A *note syndication framework: 114. that lets you create RSS and + Atom feeds by writing a small Python class. + + * More attractive automatically-generated admin features – this + overview barely scratched the surface. + +The next steps are for you to download Django(1), read *note the +tutorial: 8a. and join the community(2). Thanks for your interest! + + ---------- Footnotes ---------- + + (1) https://www.djangoproject.com/download/ + + (2) https://www.djangoproject.com/community/ + + +File: django.info, Node: Quick install guide, Next: Writing your first Django app part 1, Prev: Django at a glance, Up: Getting started + +2.2 Quick install guide ======================= Before you can use Django, you’ll need to get it installed. We have a -complete installation guide that covers all the possibilities; this -guide will guide you to a minimal installation that’ll work while you -walk through the introduction. +*note complete installation guide: 144. that covers all the +possibilities; this guide will guide you to a minimal installation +that’ll work while you walk through the introduction. * Menu: @@ -9459,11 +10460,11 @@ walk through the introduction.  File: django.info, Node: Install Python, Next: Set up a database, Up: Quick install guide -2.1.1 Install Python +2.2.1 Install Python -------------------- Being a Python web framework, Django requires Python. See *note What -Python version can I use with Django?: 120. for details. Python +Python version can I use with Django?: 146. for details. Python includes a lightweight database called SQLite(1) so you won’t need to set up a database just yet. @@ -9485,34 +10486,35 @@ shell; you should see something like:  File: django.info, Node: Set up a database, Next: Install Django, Prev: Install Python, Up: Quick install guide -2.1.2 Set up a database +2.2.2 Set up a database ----------------------- This step is only necessary if you’d like to work with a “large” database engine like PostgreSQL, MariaDB, MySQL, or Oracle. To install -such a database, consult the database installation information. +such a database, consult the *note database installation information: +148.  File: django.info, Node: Install Django, Next: Verifying, Prev: Set up a database, Up: Quick install guide -2.1.3 Install Django +2.2.3 Install Django -------------------- You’ve got three options to install Django: - * Install an official release. This is the best approach for most - users. + * *note Install an official release: 14a. This is the best approach + for most users. - * Install a version of Django provided by your operating system - distribution. + * Install a version of Django *note provided by your operating system + distribution: 14b. - * Install the latest development version. This option is for - enthusiasts who want the latest-and-greatest features and aren’t - afraid of running brand new code. You might encounter new bugs in - the development version, but reporting them helps the development - of Django. Also, releases of third-party packages are less likely - to be compatible with the development version than with the latest - stable release. + * *note Install the latest development version: 14c. This option is + for enthusiasts who want the latest-and-greatest features and + aren’t afraid of running brand new code. You might encounter new + bugs in the development version, but reporting them helps the + development of Django. Also, releases of third-party packages are + less likely to be compatible with the development version than with + the latest stable release. Always refer to the documentation that corresponds to the: version of Django you’re using! If you do either of the first two steps, @@ -9524,7 +10526,7 @@ You’ve got three options to install Django:  File: django.info, Node: Verifying, Next: That’s it!, Prev: Install Django, Up: Quick install guide -2.1.4 Verifying +2.2.4 Verifying --------------- To verify that Django can be seen by Python, type ‘python’ from your @@ -9539,23 +10541,1162 @@ You may have another version of Django installed.  File: django.info, Node: That’s it!, Prev: Verifying, Up: Quick install guide -2.1.5 That’s it! +2.2.5 That’s it! ---------------- -That’s it – you can now move onto the tutorial. +That’s it – you can now *note move onto the tutorial: 8a.  -File: django.info, Node: Writing your first Django app part 3, Next: Writing your first Django app part 4, Prev: Quick install guide, Up: Getting started +File: django.info, Node: Writing your first Django app part 1, Next: Writing your first Django app part 2, Prev: Quick install guide, Up: Getting started -2.2 Writing your first Django app, part 3 +2.3 Writing your first Django app, part 1 ========================================= -This tutorial begins where Tutorial 2 left off. We’re continuing the -web-poll application and will focus on creating the public interface – -“views.” +Let’s learn by example. + +Throughout this tutorial, we’ll walk you through the creation of a basic +poll application. + +It’ll consist of two parts: + + * A public site that lets people view polls and vote in them. + + * An admin site that lets you add, change, and delete polls. + +We’ll assume you have *note Django installed: 89. already. You can tell +Django is installed and which version by running the following command +in a shell prompt (indicated by the $ prefix): + + $ python -m django --version + +If Django is installed, you should see the version of your installation. +If it isn’t, you’ll get an error telling “No module named django”. + +This tutorial is written for Django 4.0, which supports Python 3.8 and +later. If the Django version doesn’t match, you can refer to the +tutorial for your version of Django by using the version switcher at the +bottom right corner of this page, or update Django to the newest +version. If you’re using an older version of Python, check *note What +Python version can I use with Django?: 146. to find a compatible version +of Django. + +See *note How to install Django: 144. for advice on how to remove older +versions of Django and install a newer one. Where to get help:: If you’re having trouble going through this - tutorial, please head over to the *note Getting Help: 87. section + tutorial, please head over to the *note Getting Help: 95. section + of the FAQ. + +* Menu: + +* Creating a project:: +* The development server:: +* Creating the Polls app:: +* Write your first view:: + + +File: django.info, Node: Creating a project, Next: The development server, Up: Writing your first Django app part 1 + +2.3.1 Creating a project +------------------------ + +If this is your first time using Django, you’ll have to take care of +some initial setup. Namely, you’ll need to auto-generate some code that +establishes a Django *note project: 151. – a collection of settings for +an instance of Django, including database configuration, Django-specific +options and application-specific settings. + +From the command line, ‘cd’ into a directory where you’d like to store +your code, then run the following command: + + $ django-admin startproject mysite + +This will create a ‘mysite’ directory in your current directory. If it +didn’t work, see *note Problems running django-admin: 152. + + Note: You’ll need to avoid naming projects after built-in Python or + Django components. In particular, this means you should avoid + using names like ‘django’ (which will conflict with Django itself) + or ‘test’ (which conflicts with a built-in Python package). + + Where should this code live?: If your background is in plain old + PHP (with no use of modern frameworks), you’re probably used to + putting code under the web server’s document root (in a place such + as ‘/var/www’). With Django, you don’t do that. It’s not a good + idea to put any of this Python code within your web server’s + document root, because it risks the possibility that people may be + able to view your code over the web. That’s not good for security. + + Put your code in some directory `outside' of the document root, + such as ‘/home/mycode’. + +Let’s look at what *note startproject: 153. created: + + mysite/ + manage.py + mysite/ + __init__.py + settings.py + urls.py + asgi.py + wsgi.py + +These files are: + + * The outer ‘mysite/’ root directory is a container for your project. + Its name doesn’t matter to Django; you can rename it to anything + you like. + + * ‘manage.py’: A command-line utility that lets you interact with + this Django project in various ways. You can read all the details + about ‘manage.py’ in *note django-admin and manage.py: ea. + + * The inner ‘mysite/’ directory is the actual Python package for your + project. Its name is the Python package name you’ll need to use to + import anything inside it (e.g. ‘mysite.urls’). + + * ‘mysite/__init__.py’: An empty file that tells Python that this + directory should be considered a Python package. If you’re a + Python beginner, read more about packages(1) in the official Python + docs. + + * ‘mysite/settings.py’: Settings/configuration for this Django + project. *note Django settings: e6. will tell you all about how + settings work. + + * ‘mysite/urls.py’: The URL declarations for this Django project; a + “table of contents” of your Django-powered site. You can read more + about URLs in *note URL dispatcher: bd. + + * ‘mysite/asgi.py’: An entry-point for ASGI-compatible web servers to + serve your project. See *note How to deploy with ASGI: f2. for + more details. + + * ‘mysite/wsgi.py’: An entry-point for WSGI-compatible web servers to + serve your project. See *note How to deploy with WSGI: f1. for + more details. + + ---------- Footnotes ---------- + + (1) https://docs.python.org/3/tutorial/modules.html#tut-packages + + +File: django.info, Node: The development server, Next: Creating the Polls app, Prev: Creating a project, Up: Writing your first Django app part 1 + +2.3.2 The development server +---------------------------- + +Let’s verify your Django project works. Change into the outer ‘mysite’ +directory, if you haven’t already, and run the following commands: + + $ python manage.py runserver + +You’ll see the following output on the command line: + + Performing system checks... + + System check identified no issues (0 silenced). + + You have unapplied migrations; your app may not work properly until they are applied. + Run 'python manage.py migrate' to apply them. + + March 29, 2022 - 15:50:53 + Django version 4.0, using settings 'mysite.settings' + Starting development server at ‘http://127.0.0.1:8000/’ + Quit the server with CONTROL-C. + + Note: Ignore the warning about unapplied database migrations for + now; we’ll deal with the database shortly. + +You’ve started the Django development server, a lightweight web server +written purely in Python. We’ve included this with Django so you can +develop things rapidly, without having to deal with configuring a +production server – such as Apache – until you’re ready for production. + +Now’s a good time to note: `don’t' use this server in anything +resembling a production environment. It’s intended only for use while +developing. (We’re in the business of making web frameworks, not web +servers.) + +Now that the server’s running, visit ‘http://127.0.0.1:8000/’ with your +web browser. You’ll see a “Congratulations!” page, with a rocket taking +off. It worked! + + Changing the port: By default, the *note runserver: 155. command + starts the development server on the internal IP at port 8000. + + If you want to change the server’s port, pass it as a command-line + argument. For instance, this command starts the server on port + 8080: + + $ python manage.py runserver 8080 + + If you want to change the server’s IP, pass it along with the port. + For example, to listen on all available public IPs (which is useful + if you are running Vagrant or want to show off your work on other + computers on the network), use: + + $ python manage.py runserver 0:8000 + + `0' is a shortcut for `0.0.0.0'. Full docs for the development + server can be found in the *note runserver: 155. reference. + + Automatic reloading of runserver: The development server + automatically reloads Python code for each request as needed. You + don’t need to restart the server for code changes to take effect. + However, some actions like adding files don’t trigger a restart, so + you’ll have to restart the server in these cases. + + +File: django.info, Node: Creating the Polls app, Next: Write your first view, Prev: The development server, Up: Writing your first Django app part 1 + +2.3.3 Creating the Polls app +---------------------------- + +Now that your environment – a “project” – is set up, you’re set to start +doing work. + +Each application you write in Django consists of a Python package that +follows a certain convention. Django comes with a utility that +automatically generates the basic directory structure of an app, so you +can focus on writing code rather than creating directories. + + Projects vs. apps: What’s the difference between a project and an + app? An app is a web application that does something – e.g., a + blog system, a database of public records or a small poll app. A + project is a collection of configuration and apps for a particular + website. A project can contain multiple apps. An app can be in + multiple projects. + +Your apps can live anywhere on your Python path(1). In this tutorial, +we’ll create our poll app in the same directory as your ‘manage.py’ file +so that it can be imported as its own top-level module, rather than a +submodule of ‘mysite’. + +To create your app, make sure you’re in the same directory as +‘manage.py’ and type this command: + + $ python manage.py startapp polls + +That’ll create a directory ‘polls’, which is laid out like this: + + polls/ + __init__.py + admin.py + apps.py + migrations/ + __init__.py + models.py + tests.py + views.py + +This directory structure will house the poll application. + + ---------- Footnotes ---------- + + (1) https://docs.python.org/3/tutorial/modules.html#tut-searchpath + + +File: django.info, Node: Write your first view, Prev: Creating the Polls app, Up: Writing your first Django app part 1 + +2.3.4 Write your first view +--------------------------- + +Let’s write the first view. Open the file ‘polls/views.py’ and put the +following Python code in it: + + from django.http import HttpResponse + + + def index(request): + return HttpResponse("Hello, world. You're at the polls index.") + +LiteralBlock: polls/views.py + +This is the simplest view possible in Django. To call the view, we need +to map it to a URL - and for this we need a URLconf. + +To create a URLconf in the polls directory, create a file called +‘urls.py’. Your app directory should now look like: + + polls/ + __init__.py + admin.py + apps.py + migrations/ + __init__.py + models.py + tests.py + urls.py + views.py + +In the ‘polls/urls.py’ file include the following code: + + from django.urls import path + + from . import views + + urlpatterns = [ + path('', views.index, name='index'), + ] + +LiteralBlock: polls/urls.py + +The next step is to point the root URLconf at the ‘polls.urls’ module. +In ‘mysite/urls.py’, add an import for ‘django.urls.include’ and insert +an *note include(): 158. in the ‘urlpatterns’ list, so you have: + + from django.contrib import admin + from django.urls import include, path + + urlpatterns = [ + path('polls/', include('polls.urls')), + path('admin/', admin.site.urls), + ] + +LiteralBlock: mysite/urls.py + +The *note include(): 158. function allows referencing other URLconfs. +Whenever Django encounters *note include(): 158, it chops off whatever +part of the URL matched up to that point and sends the remaining string +to the included URLconf for further processing. + +The idea behind *note include(): 158. is to make it easy to +plug-and-play URLs. Since polls are in their own URLconf +(‘polls/urls.py’), they can be placed under “/polls/”, or under +“/fun_polls/”, or under “/content/polls/”, or any other path root, and +the app will still work. + + When to use include(): You should always use ‘include()’ when you + include other URL patterns. ‘admin.site.urls’ is the only + exception to this. + +You have now wired an ‘index’ view into the URLconf. Verify it’s +working with the following command: + + $ python manage.py runserver + +Go to ‘http://localhost:8000/polls/’ in your browser, and you should see +the text “`Hello, world. You’re at the polls index.'”, which you +defined in the ‘index’ view. + + Page not found?: If you get an error page here, check that you’re + going to ‘http://localhost:8000/polls/’ and not + ‘http://localhost:8000/’. + +The *note path(): 159. function is passed four arguments, two required: +‘route’ and ‘view’, and two optional: ‘kwargs’, and ‘name’. At this +point, it’s worth reviewing what these arguments are for. + +* Menu: + +* path() argument; route: path argument route. +* path() argument; view: path argument view. +* path() argument; kwargs: path argument kwargs. +* path() argument; name: path argument name. + + +File: django.info, Node: path argument route, Next: path argument view, Up: Write your first view + +2.3.4.1 ‘path()’ argument: ‘route’ +.................................. + +‘route’ is a string that contains a URL pattern. When processing a +request, Django starts at the first pattern in ‘urlpatterns’ and makes +its way down the list, comparing the requested URL against each pattern +until it finds one that matches. + +Patterns don’t search GET and POST parameters, or the domain name. For +example, in a request to ‘https://www.example.com/myapp/’, the URLconf +will look for ‘myapp/’. In a request to +‘https://www.example.com/myapp/?page=3’, the URLconf will also look for +‘myapp/’. + + +File: django.info, Node: path argument view, Next: path argument kwargs, Prev: path argument route, Up: Write your first view + +2.3.4.2 ‘path()’ argument: ‘view’ +................................. + +When Django finds a matching pattern, it calls the specified view +function with an *note HttpRequest: 15c. object as the first argument +and any “captured” values from the route as keyword arguments. We’ll +give an example of this in a bit. + + +File: django.info, Node: path argument kwargs, Next: path argument name, Prev: path argument view, Up: Write your first view + +2.3.4.3 ‘path()’ argument: ‘kwargs’ +................................... + +Arbitrary keyword arguments can be passed in a dictionary to the target +view. We aren’t going to use this feature of Django in the tutorial. + + +File: django.info, Node: path argument name, Prev: path argument kwargs, Up: Write your first view + +2.3.4.4 ‘path()’ argument: ‘name’ +................................. + +Naming your URL lets you refer to it unambiguously from elsewhere in +Django, especially from within templates. This powerful feature allows +you to make global changes to the URL patterns of your project while +only touching a single file. + +When you’re comfortable with the basic request and response flow, read +*note part 2 of this tutorial: 8b. to start working with the database. + + +File: django.info, Node: Writing your first Django app part 2, Next: Writing your first Django app part 3, Prev: Writing your first Django app part 1, Up: Getting started + +2.4 Writing your first Django app, part 2 +========================================= + +This tutorial begins where *note Tutorial 1: 8a. left off. We’ll set up +the database, create your first model, and get a quick introduction to +Django’s automatically-generated admin site. + + Where to get help:: If you’re having trouble going through this + tutorial, please head over to the *note Getting Help: 95. section + of the FAQ. + +* Menu: + +* Database setup:: +* Creating models:: +* Activating models:: +* Playing with the API:: +* Introducing the Django Admin:: + + +File: django.info, Node: Database setup, Next: Creating models, Up: Writing your first Django app part 2 + +2.4.1 Database setup +-------------------- + +Now, open up ‘mysite/settings.py’. It’s a normal Python module with +module-level variables representing Django settings. + +By default, the configuration uses SQLite. If you’re new to databases, +or you’re just interested in trying Django, this is the easiest choice. +SQLite is included in Python, so you won’t need to install anything else +to support your database. When starting your first real project, +however, you may want to use a more scalable database like PostgreSQL, +to avoid database-switching headaches down the road. + +If you wish to use another database, install the appropriate *note +database bindings: 148. and change the following keys in the *note +DATABASES: 161. ‘'default'’ item to match your database connection +settings: + + * *note ENGINE: 162. – Either ‘'django.db.backends.sqlite3'’, + ‘'django.db.backends.postgresql'’, ‘'django.db.backends.mysql'’, or + ‘'django.db.backends.oracle'’. Other backends are *note also + available: 163. + + * *note NAME: 164. – The name of your database. If you’re using + SQLite, the database will be a file on your computer; in that case, + *note NAME: 164. should be the full absolute path, including + filename, of that file. The default value, ‘BASE_DIR / + 'db.sqlite3'’, will store the file in your project directory. + +If you are not using SQLite as your database, additional settings such +as *note USER: 165, *note PASSWORD: 166, and *note HOST: 167. must be +added. For more details, see the reference documentation for *note +DATABASES: 161. + + For databases other than SQLite: If you’re using a database besides + SQLite, make sure you’ve created a database by this point. Do that + with “‘CREATE DATABASE database_name;’” within your database’s + interactive prompt. + + Also make sure that the database user provided in + ‘mysite/settings.py’ has “create database” privileges. This allows + automatic creation of a *note test database: 168. which will be + needed in a later tutorial. + + If you’re using SQLite, you don’t need to create anything + beforehand - the database file will be created automatically when + it is needed. + +While you’re editing ‘mysite/settings.py’, set *note TIME_ZONE: 169. to +your time zone. + +Also, note the *note INSTALLED_APPS: 16a. setting at the top of the +file. That holds the names of all Django applications that are +activated in this Django instance. Apps can be used in multiple +projects, and you can package and distribute them for use by others in +their projects. + +By default, *note INSTALLED_APPS: 16a. contains the following apps, all +of which come with Django: + + * *note django.contrib.admin: 3. – The admin site. You’ll use it + shortly. + + * *note django.contrib.auth: 5. – An authentication system. + + * *note django.contrib.contenttypes: d. – A framework for content + types. + + * *note django.contrib.sessions: 2c. – A session framework. + + * *note django.contrib.messages: 23. – A messaging framework. + + * *note django.contrib.staticfiles: 31. – A framework for managing + static files. + +These applications are included by default as a convenience for the +common case. + +Some of these applications make use of at least one database table, +though, so we need to create the tables in the database before we can +use them. To do that, run the following command: + + $ python manage.py migrate + +The *note migrate: 137. command looks at the *note INSTALLED_APPS: 16a. +setting and creates any necessary database tables according to the +database settings in your ‘mysite/settings.py’ file and the database +migrations shipped with the app (we’ll cover those later). You’ll see a +message for each migration it applies. If you’re interested, run the +command-line client for your database and type ‘\dt’ (PostgreSQL), ‘SHOW +TABLES;’ (MariaDB, MySQL), ‘.tables’ (SQLite), or ‘SELECT TABLE_NAME +FROM USER_TABLES;’ (Oracle) to display the tables Django created. + + For the minimalists: Like we said above, the default applications + are included for the common case, but not everybody needs them. If + you don’t need any or all of them, feel free to comment-out or + delete the appropriate line(s) from *note INSTALLED_APPS: 16a. + before running *note migrate: 137. The *note migrate: 137. command + will only run migrations for apps in *note INSTALLED_APPS: 16a. + + +File: django.info, Node: Creating models, Next: Activating models, Prev: Database setup, Up: Writing your first Django app part 2 + +2.4.2 Creating models +--------------------- + +Now we’ll define your models – essentially, your database layout, with +additional metadata. + + Philosophy: A model is the single, definitive source of information + about your data. It contains the essential fields and behaviors of + the data you’re storing. Django follows the *note DRY Principle: + 16d. The goal is to define your data model in one place and + automatically derive things from it. + + This includes the migrations - unlike in Ruby On Rails, for + example, migrations are entirely derived from your models file, and + are essentially a history that Django can roll through to update + your database schema to match your current models. + +In our poll app, we’ll create two models: ‘Question’ and ‘Choice’. A +‘Question’ has a question and a publication date. A ‘Choice’ has two +fields: the text of the choice and a vote tally. Each ‘Choice’ is +associated with a ‘Question’. + +These concepts are represented by Python classes. Edit the +‘polls/models.py’ file so it looks like this: + + from django.db import models + + + class Question(models.Model): + question_text = models.CharField(max_length=200) + pub_date = models.DateTimeField('date published') + + + class Choice(models.Model): + question = models.ForeignKey(Question, on_delete=models.CASCADE) + choice_text = models.CharField(max_length=200) + votes = models.IntegerField(default=0) + +LiteralBlock: polls/models.py + +Here, each model is represented by a class that subclasses *note +django.db.models.Model: 16e. Each model has a number of class +variables, each of which represents a database field in the model. + +Each field is represented by an instance of a *note Field: 16f. class – +e.g., *note CharField: 170. for character fields and *note +DateTimeField: 171. for datetimes. This tells Django what type of data +each field holds. + +The name of each *note Field: 16f. instance (e.g. ‘question_text’ or +‘pub_date’) is the field’s name, in machine-friendly format. You’ll use +this value in your Python code, and your database will use it as the +column name. + +You can use an optional first positional argument to a *note Field: 16f. +to designate a human-readable name. That’s used in a couple of +introspective parts of Django, and it doubles as documentation. If this +field isn’t provided, Django will use the machine-readable name. In +this example, we’ve only defined a human-readable name for +‘Question.pub_date’. For all other fields in this model, the field’s +machine-readable name will suffice as its human-readable name. + +Some *note Field: 16f. classes have required arguments. *note +CharField: 170, for example, requires that you give it a *note +max_length: 172. That’s used not only in the database schema, but in +validation, as we’ll soon see. + +A *note Field: 16f. can also have various optional arguments; in this +case, we’ve set the *note default: 173. value of ‘votes’ to 0. + +Finally, note a relationship is defined, using *note ForeignKey: 174. +That tells Django each ‘Choice’ is related to a single ‘Question’. +Django supports all the common database relationships: many-to-one, +many-to-many, and one-to-one. + + +File: django.info, Node: Activating models, Next: Playing with the API, Prev: Creating models, Up: Writing your first Django app part 2 + +2.4.3 Activating models +----------------------- + +That small bit of model code gives Django a lot of information. With +it, Django is able to: + + * Create a database schema (‘CREATE TABLE’ statements) for this app. + + * Create a Python database-access API for accessing ‘Question’ and + ‘Choice’ objects. + +But first we need to tell our project that the ‘polls’ app is installed. + + Philosophy: Django apps are “pluggable”: You can use an app in + multiple projects, and you can distribute apps, because they don’t + have to be tied to a given Django installation. + +To include the app in our project, we need to add a reference to its +configuration class in the *note INSTALLED_APPS: 16a. setting. The +‘PollsConfig’ class is in the ‘polls/apps.py’ file, so its dotted path +is ‘'polls.apps.PollsConfig'’. Edit the ‘mysite/settings.py’ file and +add that dotted path to the *note INSTALLED_APPS: 16a. setting. It’ll +look like this: + + INSTALLED_APPS = [ + 'polls.apps.PollsConfig', + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + ] + +LiteralBlock: mysite/settings.py + +Now Django knows to include the ‘polls’ app. Let’s run another command: + + $ python manage.py makemigrations polls + +You should see something similar to the following: + + Migrations for 'polls': + polls/migrations/0001_initial.py + - Create model Question + - Create model Choice + +By running ‘makemigrations’, you’re telling Django that you’ve made some +changes to your models (in this case, you’ve made new ones) and that +you’d like the changes to be stored as a `migration'. + +Migrations are how Django stores changes to your models (and thus your +database schema) - they’re files on disk. You can read the migration +for your new model if you like; it’s the file +‘polls/migrations/0001_initial.py’. Don’t worry, you’re not expected to +read them every time Django makes one, but they’re designed to be +human-editable in case you want to manually tweak how Django changes +things. + +There’s a command that will run the migrations for you and manage your +database schema automatically - that’s called *note migrate: 137, and +we’ll come to it in a moment - but first, let’s see what SQL that +migration would run. The *note sqlmigrate: 176. command takes migration +names and returns their SQL: + + $ python manage.py sqlmigrate polls 0001 + +You should see something similar to the following (we’ve reformatted it +for readability): + + BEGIN; + -- + -- Create model Question + -- + CREATE TABLE "polls_question" ( + "id" serial NOT NULL PRIMARY KEY, + "question_text" varchar(200) NOT NULL, + "pub_date" timestamp with time zone NOT NULL + ); + -- + -- Create model Choice + -- + CREATE TABLE "polls_choice" ( + "id" serial NOT NULL PRIMARY KEY, + "choice_text" varchar(200) NOT NULL, + "votes" integer NOT NULL, + "question_id" integer NOT NULL + ); + ALTER TABLE "polls_choice" + ADD CONSTRAINT "polls_choice_question_id_c5b4b260_fk_polls_question_id" + FOREIGN KEY ("question_id") + REFERENCES "polls_question" ("id") + DEFERRABLE INITIALLY DEFERRED; + CREATE INDEX "polls_choice_question_id_c5b4b260" ON "polls_choice" ("question_id"); + + COMMIT; + +Note the following: + + * The exact output will vary depending on the database you are using. + The example above is generated for PostgreSQL. + + * Table names are automatically generated by combining the name of + the app (‘polls’) and the lowercase name of the model – ‘question’ + and ‘choice’. (You can override this behavior.) + + * Primary keys (IDs) are added automatically. (You can override + this, too.) + + * By convention, Django appends ‘"_id"’ to the foreign key field + name. (Yes, you can override this, as well.) + + * The foreign key relationship is made explicit by a ‘FOREIGN KEY’ + constraint. Don’t worry about the ‘DEFERRABLE’ parts; it’s telling + PostgreSQL to not enforce the foreign key until the end of the + transaction. + + * It’s tailored to the database you’re using, so database-specific + field types such as ‘auto_increment’ (MySQL), ‘serial’ + (PostgreSQL), or ‘integer primary key autoincrement’ (SQLite) are + handled for you automatically. Same goes for the quoting of field + names – e.g., using double quotes or single quotes. + + * The *note sqlmigrate: 176. command doesn’t actually run the + migration on your database - instead, it prints it to the screen so + that you can see what SQL Django thinks is required. It’s useful + for checking what Django is going to do or if you have database + administrators who require SQL scripts for changes. + +If you’re interested, you can also run *note python manage.py check: +177.; this checks for any problems in your project without making +migrations or touching the database. + +Now, run *note migrate: 137. again to create those model tables in your +database: + + $ python manage.py migrate + Operations to perform: + Apply all migrations: admin, auth, contenttypes, polls, sessions + Running migrations: + Rendering model states... DONE + Applying polls.0001_initial... OK + +The *note migrate: 137. command takes all the migrations that haven’t +been applied (Django tracks which ones are applied using a special table +in your database called ‘django_migrations’) and runs them against your +database - essentially, synchronizing the changes you made to your +models with the schema in the database. + +Migrations are very powerful and let you change your models over time, +as you develop your project, without the need to delete your database or +tables and make new ones - it specializes in upgrading your database +live, without losing data. We’ll cover them in more depth in a later +part of the tutorial, but for now, remember the three-step guide to +making model changes: + + * Change your models (in ‘models.py’). + + * Run *note python manage.py makemigrations: 136. to create + migrations for those changes + + * Run *note python manage.py migrate: 137. to apply those changes to + the database. + +The reason that there are separate commands to make and apply migrations +is because you’ll commit migrations to your version control system and +ship them with your app; they not only make your development easier, +they’re also usable by other developers and in production. + +Read the *note django-admin documentation: ea. for full information on +what the ‘manage.py’ utility can do. + + +File: django.info, Node: Playing with the API, Next: Introducing the Django Admin, Prev: Activating models, Up: Writing your first Django app part 2 + +2.4.4 Playing with the API +-------------------------- + +Now, let’s hop into the interactive Python shell and play around with +the free API Django gives you. To invoke the Python shell, use this +command: + + $ python manage.py shell + +We’re using this instead of simply typing “python”, because ‘manage.py’ +sets the *note DJANGO_SETTINGS_MODULE: 179. environment variable, which +gives Django the Python import path to your ‘mysite/settings.py’ file. + +Once you’re in the shell, explore the *note database API: a3.: + + >>> from polls.models import Choice, Question # Import the model classes we just wrote. + + # No questions are in the system yet. + >>> Question.objects.all() + + + # Create a new Question. + # Support for time zones is enabled in the default settings file, so + # Django expects a datetime with tzinfo for pub_date. Use timezone.now() + # instead of datetime.datetime.now() and it will do the right thing. + >>> from django.utils import timezone + >>> q = Question(question_text="What's new?", pub_date=timezone.now()) + + # Save the object into the database. You have to call save() explicitly. + >>> q.save() + + # Now it has an ID. + >>> q.id + 1 + + # Access model field values via Python attributes. + >>> q.question_text + "What's new?" + >>> q.pub_date + datetime.datetime(2012, 2, 26, 13, 0, 0, 775217, tzinfo=) + + # Change values by changing the attributes, then calling save(). + >>> q.question_text = "What's up?" + >>> q.save() + + # objects.all() displays all the questions in the database. + >>> Question.objects.all() + ]> + +Wait a minute. ‘’ isn’t a helpful +representation of this object. Let’s fix that by editing the ‘Question’ +model (in the ‘polls/models.py’ file) and adding a *note __str__(): 17a. +method to both ‘Question’ and ‘Choice’: + + from django.db import models + + class Question(models.Model): + # ... + def __str__(self): + return self.question_text + + class Choice(models.Model): + # ... + def __str__(self): + return self.choice_text + +LiteralBlock: polls/models.py + +It’s important to add *note __str__(): 17a. methods to your models, not +only for your own convenience when dealing with the interactive prompt, +but also because objects’ representations are used throughout Django’s +automatically-generated admin. Let’s also add a custom method to this +model: + + import datetime + + from django.db import models + from django.utils import timezone + + + class Question(models.Model): + # ... + def was_published_recently(self): + return self.pub_date >= timezone.now() - datetime.timedelta(days=1) + +LiteralBlock: polls/models.py + +Note the addition of ‘import datetime’ and ‘from django.utils import +timezone’, to reference Python’s standard datetime(1) module and +Django’s time-zone-related utilities in *note django.utils.timezone: 78, +respectively. If you aren’t familiar with time zone handling in Python, +you can learn more in the *note time zone support docs: 106. + +Save these changes and start a new Python interactive shell by running +‘python manage.py shell’ again: + + >>> from polls.models import Choice, Question + + # Make sure our __str__() addition worked. + >>> Question.objects.all() + ]> + + # Django provides a rich database lookup API that's entirely driven by + # keyword arguments. + >>> Question.objects.filter(id=1) + ]> + >>> Question.objects.filter(question_text__startswith='What') + ]> + + # Get the question that was published this year. + >>> from django.utils import timezone + >>> current_year = timezone.now().year + >>> Question.objects.get(pub_date__year=current_year) + + + # Request an ID that doesn't exist, this will raise an exception. + >>> Question.objects.get(id=2) + Traceback (most recent call last): + ... + DoesNotExist: Question matching query does not exist. + + # Lookup by a primary key is the most common case, so Django provides a + # shortcut for primary-key exact lookups. + # The following is identical to Question.objects.get(id=1). + >>> Question.objects.get(pk=1) + + + # Make sure our custom method worked. + >>> q = Question.objects.get(pk=1) + >>> q.was_published_recently() + True + + # Give the Question a couple of Choices. The create call constructs a new + # Choice object, does the INSERT statement, adds the choice to the set + # of available choices and returns the new Choice object. Django creates + # a set to hold the "other side" of a ForeignKey relation + # (e.g. a question's choice) which can be accessed via the API. + >>> q = Question.objects.get(pk=1) + + # Display any choices from the related object set -- none so far. + >>> q.choice_set.all() + + + # Create three choices. + >>> q.choice_set.create(choice_text='Not much', votes=0) + + >>> q.choice_set.create(choice_text='The sky', votes=0) + + >>> c = q.choice_set.create(choice_text='Just hacking again', votes=0) + + # Choice objects have API access to their related Question objects. + >>> c.question + + + # And vice versa: Question objects get access to Choice objects. + >>> q.choice_set.all() + , , ]> + >>> q.choice_set.count() + 3 + + # The API automatically follows relationships as far as you need. + # Use double underscores to separate relationships. + # This works as many levels deep as you want; there's no limit. + # Find all Choices for any question whose pub_date is in this year + # (reusing the 'current_year' variable we created above). + >>> Choice.objects.filter(question__pub_date__year=current_year) + , , ]> + + # Let's delete one of the choices. Use delete() for that. + >>> c = q.choice_set.filter(choice_text__startswith='Just hacking') + >>> c.delete() + +For more information on model relations, see *note Accessing related +objects: a7. For more on how to use double underscores to perform field +lookups via the API, see *note Field lookups: 17c. For full details on +the database API, see our *note Database API reference: a3. + + ---------- Footnotes ---------- + + (1) https://docs.python.org/3/library/datetime.html#module-datetime + + +File: django.info, Node: Introducing the Django Admin, Prev: Playing with the API, Up: Writing your first Django app part 2 + +2.4.5 Introducing the Django Admin +---------------------------------- + + Philosophy: Generating admin sites for your staff or clients to + add, change, and delete content is tedious work that doesn’t + require much creativity. For that reason, Django entirely + automates creation of admin interfaces for models. + + Django was written in a newsroom environment, with a very clear + separation between “content publishers” and the “public” site. + Site managers use the system to add news stories, events, sports + scores, etc., and that content is displayed on the public site. + Django solves the problem of creating a unified interface for site + administrators to edit content. + + The admin isn’t intended to be used by site visitors. It’s for + site managers. + +* Menu: + +* Creating an admin user:: +* Start the development server:: +* Enter the admin site:: +* Make the poll app modifiable in the admin:: +* Explore the free admin functionality:: + + +File: django.info, Node: Creating an admin user, Next: Start the development server, Up: Introducing the Django Admin + +2.4.5.1 Creating an admin user +.............................. + +First we’ll need to create a user who can login to the admin site. Run +the following command: + + $ python manage.py createsuperuser + +Enter your desired username and press enter. + + Username: admin + +You will then be prompted for your desired email address: + + Email address: admin@example.com + +The final step is to enter your password. You will be asked to enter +your password twice, the second time as a confirmation of the first. + + Password: ********** + Password (again): ********* + Superuser created successfully. + + +File: django.info, Node: Start the development server, Next: Enter the admin site, Prev: Creating an admin user, Up: Introducing the Django Admin + +2.4.5.2 Start the development server +.................................... + +The Django admin site is activated by default. Let’s start the +development server and explore it. + +If the server is not running start it like so: + + $ python manage.py runserver + +Now, open a web browser and go to “/admin/” on your local domain – e.g., +‘http://127.0.0.1:8000/admin/’. You should see the admin’s login +screen: + +[image src="django-figures/admin01.png" alt="Django admin login screen"] + +Since *note translation: 103. is turned on by default, if you set *note +LANGUAGE_CODE: 180, the login screen will be displayed in the given +language (if Django has appropriate translations). + + +File: django.info, Node: Enter the admin site, Next: Make the poll app modifiable in the admin, Prev: Start the development server, Up: Introducing the Django Admin + +2.4.5.3 Enter the admin site +............................ + +Now, try logging in with the superuser account you created in the +previous step. You should see the Django admin index page: + +[image src="django-figures/admin02.png" alt="Django admin index page"] + +You should see a few types of editable content: groups and users. They +are provided by *note django.contrib.auth: 5, the authentication +framework shipped by Django. + + +File: django.info, Node: Make the poll app modifiable in the admin, Next: Explore the free admin functionality, Prev: Enter the admin site, Up: Introducing the Django Admin + +2.4.5.4 Make the poll app modifiable in the admin +................................................. + +But where’s our poll app? It’s not displayed on the admin index page. + +Only one more thing to do: we need to tell the admin that ‘Question’ +objects have an admin interface. To do this, open the ‘polls/admin.py’ +file, and edit it to look like this: + + from django.contrib import admin + + from .models import Question + + admin.site.register(Question) + +LiteralBlock: polls/admin.py + + +File: django.info, Node: Explore the free admin functionality, Prev: Make the poll app modifiable in the admin, Up: Introducing the Django Admin + +2.4.5.5 Explore the free admin functionality +............................................ + +Now that we’ve registered ‘Question’, Django knows that it should be +displayed on the admin index page: + +[image src="django-figures/admin03t.png" alt="Django admin index page, now with polls displayed"] + +Click “Questions”. Now you’re at the “change list” page for questions. +This page displays all the questions in the database and lets you choose +one to change it. There’s the “What’s up?” question we created earlier: + +[image src="django-figures/admin04t.png" alt="Polls change list page"] + +Click the “What’s up?” question to edit it: + +[image src="django-figures/admin05t.png" alt="Editing form for question object"] + +Things to note here: + + * The form is automatically generated from the ‘Question’ model. + + * The different model field types (*note DateTimeField: 171, *note + CharField: 170.) correspond to the appropriate HTML input widget. + Each type of field knows how to display itself in the Django admin. + + * Each *note DateTimeField: 171. gets free JavaScript shortcuts. + Dates get a “Today” shortcut and calendar popup, and times get a + “Now” shortcut and a convenient popup that lists commonly entered + times. + +The bottom part of the page gives you a couple of options: + + * Save – Saves changes and returns to the change-list page for this + type of object. + + * Save and continue editing – Saves changes and reloads the admin + page for this object. + + * Save and add another – Saves changes and loads a new, blank form + for this type of object. + + * Delete – Displays a delete confirmation page. + +If the value of “Date published” doesn’t match the time when you created +the question in *note Tutorial 1: 8a, it probably means you forgot to +set the correct value for the *note TIME_ZONE: 169. setting. Change it, +reload the page and check that the correct value appears. + +Change the “Date published” by clicking the “Today” and “Now” shortcuts. +Then click “Save and continue editing.” Then click “History” in the +upper right. You’ll see a page listing all changes made to this object +via the Django admin, with the timestamp and username of the person who +made the change: + +[image src="django-figures/admin06t.png" alt="History page for question object"] + +When you’re comfortable with the models API and have familiarized +yourself with the admin site, read *note part 3 of this tutorial: 8c. to +learn about how to add more views to our polls app. + + +File: django.info, Node: Writing your first Django app part 3, Next: Writing your first Django app part 4, Prev: Writing your first Django app part 2, Up: Getting started + +2.5 Writing your first Django app, part 3 +========================================= + +This tutorial begins where *note Tutorial 2: 8b. left off. We’re +continuing the web-poll application and will focus on creating the +public interface – “views.” + + Where to get help:: If you’re having trouble going through this + tutorial, please head over to the *note Getting Help: 95. section of the FAQ. * Menu: @@ -9571,7 +11712,7 @@ web-poll application and will focus on creating the public interface –  File: django.info, Node: Overview, Next: Writing more views, Up: Writing your first Django app part 3 -2.2.1 Overview +2.5.1 Overview -------------- A view is a “type” of web page in your Django application that generally @@ -9623,12 +11764,12 @@ To get from a URL to a view, Django uses what are known as ‘URLconfs’. A URLconf maps URL patterns to views. This tutorial provides basic instruction in the use of URLconfs, and you -can refer to *note URL dispatcher: ae. for more information. +can refer to *note URL dispatcher: bd. for more information.  File: django.info, Node: Writing more views, Next: Write views that actually do something, Prev: Overview, Up: Writing your first Django app part 3 -2.2.2 Writing more views +2.5.2 Writing more views ------------------------ Now let’s add a few more views to ‘polls/views.py’. These views are @@ -9647,7 +11788,7 @@ slightly different, because they take an argument: LiteralBlock: polls/views.py Wire these new views into the ‘polls.urls’ module by adding the -following *note path(): 128. calls: +following *note path(): 159. calls: from django.urls import path @@ -9673,7 +11814,7 @@ placeholder results and voting pages. When somebody requests a page from your website – say, “/polls/34/”, Django will load the ‘mysite.urls’ Python module because it’s pointed to -by the *note ROOT_URLCONF: 129. setting. It finds the variable named +by the *note ROOT_URLCONF: 187. setting. It finds the variable named ‘urlpatterns’ and traverses the patterns in order. After finding the match at ‘'polls/'’, it strips off the matching text (‘"polls/"’) and sends the remaining text – ‘"34/"’ – to the ‘polls.urls’ URLconf for @@ -9693,12 +11834,12 @@ name.  File: django.info, Node: Write views that actually do something, Next: Raising a 404 error, Prev: Writing more views, Up: Writing your first Django app part 3 -2.2.3 Write views that actually do something +2.5.3 Write views that actually do something -------------------------------------------- Each view is responsible for doing one of two things: returning an *note -HttpResponse: 12b. object containing the content for the requested page, -or raising an exception such as *note Http404: 12c. The rest is up to +HttpResponse: 13c. object containing the content for the requested page, +or raising an exception such as *note Http404: 13d. The rest is up to you. Your view can read records from a database, or not. It can use a @@ -9707,12 +11848,12 @@ system – or not. It can generate a PDF file, output XML, create a ZIP file on the fly, anything you want, using whatever Python libraries you want. -All Django wants is that *note HttpResponse: 12b. Or an exception. +All Django wants is that *note HttpResponse: 13c. Or an exception. Because it’s convenient, let’s use Django’s own database API, which we -covered in Tutorial 2. Here’s one stab at a new ‘index()’ view, which -displays the latest 5 poll questions in the system, separated by commas, -according to publication date: +covered in *note Tutorial 2: 8b. Here’s one stab at a new ‘index()’ +view, which displays the latest 5 poll questions in the system, +separated by commas, according to publication date: from django.http import HttpResponse @@ -9736,11 +11877,11 @@ design from Python by creating a template that the view can use. First, create a directory called ‘templates’ in your ‘polls’ directory. Django will look for templates in there. -Your project’s *note TEMPLATES: 12d. setting describes how Django will +Your project’s *note TEMPLATES: 189. setting describes how Django will load and render templates. The default settings file configures a -‘DjangoTemplates’ backend whose *note APP_DIRS: 12e. option is set to +‘DjangoTemplates’ backend whose *note APP_DIRS: 18a. option is set to ‘True’. By convention ‘DjangoTemplates’ looks for a “templates” -subdirectory in each of the *note INSTALLED_APPS: 12f. +subdirectory in each of the *note INSTALLED_APPS: 16a. Within the ‘templates’ directory you have just created, create another directory called ‘polls’, and within that create a file called @@ -9802,8 +11943,8 @@ context. The context is a dictionary mapping template variable names to Python objects. Load the page by pointing your browser at “/polls/”, and you should see -a bulleted-list containing the “What’s up” question from Tutorial 2. -The link points to the question’s detail page. +a bulleted-list containing the “What’s up” question from *note Tutorial +2: 8b. The link points to the question’s detail page. * Menu: @@ -9817,11 +11958,11 @@ https://developer.mozilla.org/en-US/docs/Learn/HTML/Introduction_to_HTML/Getting  File: django.info, Node: A shortcut render, Up: Write views that actually do something -2.2.3.1 A shortcut: ‘render()’ +2.5.3.1 A shortcut: ‘render()’ .............................. It’s a very common idiom to load a template, fill a context and return -an *note HttpResponse: 12b. object with the result of the rendered +an *note HttpResponse: 13c. object with the result of the rendered template. Django provides a shortcut. Here’s the full ‘index()’ view, rewritten: @@ -9838,19 +11979,19 @@ rewritten: LiteralBlock: polls/views.py Note that once we’ve done this in all these views, we no longer need to -import ‘loader’ and *note HttpResponse: 12b. (you’ll want to keep -‘HttpResponse’ if you still have the stub methods for ‘detail’, +import *note loader: 64. and *note HttpResponse: 13c. (you’ll want to +keep ‘HttpResponse’ if you still have the stub methods for ‘detail’, ‘results’, and ‘vote’). -The *note render(): 131. function takes the request object as its first +The *note render(): 18c. function takes the request object as its first argument, a template name as its second argument and a dictionary as its -optional third argument. It returns an *note HttpResponse: 12b. object +optional third argument. It returns an *note HttpResponse: 13c. object of the given template rendered with the given context.  File: django.info, Node: Raising a 404 error, Next: Use the template system, Prev: Write views that actually do something, Up: Writing your first Django app part 3 -2.2.4 Raising a 404 error +2.5.4 Raising a 404 error ------------------------- Now, let’s tackle the question detail view – the page that displays the @@ -9870,7 +12011,7 @@ question text for a given poll. Here’s the view: LiteralBlock: polls/views.py -The new concept here: The view raises the *note Http404: 12c. exception +The new concept here: The view raises the *note Http404: 13d. exception if a question with the requested ID doesn’t exist. We’ll discuss what you could put in that ‘polls/detail.html’ template a @@ -9890,11 +12031,11 @@ will get you started for now.  File: django.info, Node: A shortcut get_object_or_404, Up: Raising a 404 error -2.2.4.1 A shortcut: ‘get_object_or_404()’ +2.5.4.1 A shortcut: ‘get_object_or_404()’ ......................................... -It’s a very common idiom to use *note get(): 134. and raise *note -Http404: 12c. if the object doesn’t exist. Django provides a shortcut. +It’s a very common idiom to use *note get(): 18f. and raise *note +Http404: 13d. if the object doesn’t exist. Django provides a shortcut. Here’s the ‘detail()’ view, rewritten: from django.shortcuts import get_object_or_404, render @@ -9907,31 +12048,31 @@ Here’s the ‘detail()’ view, rewritten: LiteralBlock: polls/views.py -The *note get_object_or_404(): 135. function takes a Django model as its +The *note get_object_or_404(): 190. function takes a Django model as its first argument and an arbitrary number of keyword arguments, which it -passes to the *note get(): 134. function of the model’s manager. It -raises *note Http404: 12c. if the object doesn’t exist. +passes to the *note get(): 18f. function of the model’s manager. It +raises *note Http404: 13d. if the object doesn’t exist. Philosophy: Why do we use a helper function *note - get_object_or_404(): 135. instead of automatically catching the - *note ObjectDoesNotExist: 136. exceptions at a higher level, or - having the model API raise *note Http404: 12c. instead of *note - ObjectDoesNotExist: 136.? + get_object_or_404(): 190. instead of automatically catching the + *note ObjectDoesNotExist: 191. exceptions at a higher level, or + having the model API raise *note Http404: 13d. instead of *note + ObjectDoesNotExist: 191.? Because that would couple the model layer to the view layer. One of the foremost design goals of Django is to maintain loose coupling. Some controlled coupling is introduced in the *note - django.shortcuts: 5d. module. + django.shortcuts: 5f. module. -There’s also a *note get_list_or_404(): 137. function, which works just -as *note get_object_or_404(): 135. – except using *note filter(): 138. -instead of *note get(): 134. It raises *note Http404: 12c. if the list +There’s also a *note get_list_or_404(): 192. function, which works just +as *note get_object_or_404(): 190. – except using *note filter(): 193. +instead of *note get(): 18f. It raises *note Http404: 13d. if the list is empty.  File: django.info, Node: Use the template system, Next: Removing hardcoded URLs in templates, Prev: Raising a 404 error, Up: Writing your first Django app part 3 -2.2.5 Use the template system +2.5.5 Use the template system ----------------------------- Back to the ‘detail()’ view for our poll application. Given the context @@ -9953,17 +12094,17 @@ Django does a dictionary lookup on the object ‘question’. Failing that, it tries an attribute lookup – which works, in this case. If attribute lookup had failed, it would’ve tried a list-index lookup. -Method-calling happens in the *note {% for %}: 13a. loop: +Method-calling happens in the *note {% for %}: 195. loop: ‘question.choice_set.all’ is interpreted as the Python code ‘question.choice_set.all()’, which returns an iterable of ‘Choice’ -objects and is suitable for use in the *note {% for %}: 13a. tag. +objects and is suitable for use in the *note {% for %}: 195. tag. -See the template guide for more about templates. +See the *note template guide: d5. for more about templates.  File: django.info, Node: Removing hardcoded URLs in templates, Next: Namespacing URL names, Prev: Use the template system, Up: Writing your first Django app part 3 -2.2.6 Removing hardcoded URLs in templates +2.5.6 Removing hardcoded URLs in templates ------------------------------------------ Remember, when we wrote the link to a question in the ‘polls/index.html’ @@ -9973,7 +12114,7 @@ template, the link was partially hardcoded like this: The problem with this hardcoded, tightly-coupled approach is that it becomes challenging to change URLs on projects with a lot of templates. -However, since you defined the name argument in the *note path(): 128. +However, since you defined the name argument in the *note path(): 159. functions in the ‘polls.urls’ module, you can remove a reliance on specific URL paths defined in your url configurations by using the ‘{% url %}’ template tag: @@ -10002,7 +12143,7 @@ it in the template (or templates) you would change it in  File: django.info, Node: Namespacing URL names, Prev: Removing hardcoded URLs in templates, Up: Writing your first Django app part 3 -2.2.7 Namespacing URL names +2.5.7 Namespacing URL names --------------------------- The tutorial project has just one app, ‘polls’. In real Django @@ -10042,21 +12183,21 @@ to point at the namespaced detail view: LiteralBlock: polls/templates/polls/index.html When you’re comfortable with writing views, read *note part 4 of this -tutorial: 83. to learn the basics about form processing and generic +tutorial: 8d. to learn the basics about form processing and generic views.  -File: django.info, Node: Writing your first Django app part 4, Next: Advanced tutorial How to write reusable apps, Prev: Writing your first Django app part 3, Up: Getting started +File: django.info, Node: Writing your first Django app part 4, Next: Writing your first Django app part 5, Prev: Writing your first Django app part 3, Up: Getting started -2.3 Writing your first Django app, part 4 +2.6 Writing your first Django app, part 4 ========================================= -This tutorial begins where *note Tutorial 3: 82. left off. We’re +This tutorial begins where *note Tutorial 3: 8c. left off. We’re continuing the web-poll application and will focus on form processing and cutting down our code. Where to get help:: If you’re having trouble going through this - tutorial, please head over to the *note Getting Help: 87. section + tutorial, please head over to the *note Getting Help: 95. section of the FAQ. * Menu: @@ -10067,7 +12208,7 @@ and cutting down our code.  File: django.info, Node: Write a minimal form, Next: Use generic views Less code is better, Up: Writing your first Django app part 4 -2.3.1 Write a minimal form +2.6.1 Write a minimal form -------------------------- Let’s update our poll detail template (“polls/detail.html”) from the @@ -10105,7 +12246,7 @@ A quick rundown: that alters data server-side, use ‘method="post"’. This tip isn’t specific to Django; it’s good web development practice in general. - * ‘forloop.counter’ indicates how many times the *note for: 13a. tag + * ‘forloop.counter’ indicates how many times the *note for: 195. tag has gone through its loop * Since we’re creating a POST form (which can have the effect of @@ -10113,10 +12254,10 @@ A quick rundown: Forgeries. Thankfully, you don’t have to worry too hard, because Django comes with a helpful system for protecting against it. In short, all POST forms that are targeted at internal URLs should use - the *note {% csrf_token %}: 13f. template tag. + the *note {% csrf_token %}: 19a. template tag. Now, let’s create a Django view that handles the submitted data and does -something with it. Remember, in *note Tutorial 3: 82, we created a +something with it. Remember, in *note Tutorial 3: 8c, we created a URLconf for the polls application that includes this line: path('/vote/', views.vote, name='vote'), @@ -10154,14 +12295,14 @@ LiteralBlock: polls/views.py This code includes a few things we haven’t covered yet in this tutorial: - * *note request.POST: 140. is a dictionary-like object that lets you + * *note request.POST: 19b. is a dictionary-like object that lets you access submitted data by key name. In this case, ‘request.POST['choice']’ returns the ID of the selected choice, as - a string. *note request.POST: 140. values are always strings. + a string. *note request.POST: 19b. values are always strings. - Note that Django also provides *note request.GET: 141. for + Note that Django also provides *note request.GET: 19c. for accessing GET data in the same way – but we’re explicitly using - *note request.POST: 140. in our code, to ensure that data is only + *note request.POST: 19b. in our code, to ensure that data is only altered via a POST call. * ‘request.POST['choice']’ will raise KeyError(1) if ‘choice’ wasn’t @@ -10170,32 +12311,32 @@ This code includes a few things we haven’t covered yet in this tutorial: isn’t given. * After incrementing the choice count, the code returns an *note - HttpResponseRedirect: 142. rather than a normal *note HttpResponse: - 12b. *note HttpResponseRedirect: 142. takes a single argument: the + HttpResponseRedirect: 19d. rather than a normal *note HttpResponse: + 13c. *note HttpResponseRedirect: 19d. takes a single argument: the URL to which the user will be redirected (see the following point for how we construct the URL in this case). As the Python comment above points out, you should always return an - *note HttpResponseRedirect: 142. after successfully dealing with + *note HttpResponseRedirect: 19d. after successfully dealing with POST data. This tip isn’t specific to Django; it’s good web development practice in general. - * We are using the *note reverse(): 143. function in the *note - HttpResponseRedirect: 142. constructor in this example. This + * We are using the *note reverse(): 19e. function in the *note + HttpResponseRedirect: 19d. constructor in this example. This function helps avoid having to hardcode a URL in the view function. It is given the name of the view that we want to pass control to and the variable portion of the URL pattern that points to that view. In this case, using the URLconf we set up in *note Tutorial - 3: 82, this *note reverse(): 143. call will return a string like + 3: 8c, this *note reverse(): 19e. call will return a string like '/polls/3/results/' where the ‘3’ is the value of ‘question.id’. This redirected URL will then call the ‘'results'’ view to display the final page. -As mentioned in *note Tutorial 3: 82, ‘request’ is an *note HttpRequest: -144. object. For more on *note HttpRequest: 144. objects, see the *note -request and response documentation: b4. +As mentioned in *note Tutorial 3: 8c, ‘request’ is an *note HttpRequest: +15c. object. For more on *note HttpRequest: 15c. objects, see the *note +request and response documentation: c3. After somebody votes in a question, the ‘vote()’ view redirects to the results page for the question. Let’s write that view: @@ -10210,7 +12351,7 @@ results page for the question. Let’s write that view: LiteralBlock: polls/views.py This is almost exactly the same as the ‘detail()’ view from *note -Tutorial 3: 82. The only difference is the template name. We’ll fix +Tutorial 3: 8c. The only difference is the template name. We’ll fix this redundancy later. Now, create a ‘polls/results.html’ template: @@ -10241,7 +12382,7 @@ message. is computed and saved, but 44 would be the expected value. This is called a `race condition'. If you are interested, you can - read *note Avoiding race conditions using F(): 145. to learn how + read *note Avoiding race conditions using F(): 19f. to learn how you can solve this issue. ---------- Footnotes ---------- @@ -10253,10 +12394,10 @@ message.  File: django.info, Node: Use generic views Less code is better, Prev: Write a minimal form, Up: Writing your first Django app part 4 -2.3.2 Use generic views: Less code is better +2.6.2 Use generic views: Less code is better -------------------------------------------- -The ‘detail()’ (from *note Tutorial 3: 82.) and ‘results()’ views are +The ‘detail()’ (from *note Tutorial 3: 8c.) and ‘results()’ views are very short – and, as mentioned above, redundant. The ‘index()’ view, which displays a list of polls, is similar. @@ -10298,7 +12439,7 @@ Read on for details.  File: django.info, Node: Amend URLconf, Next: Amend views, Up: Use generic views Less code is better -2.3.2.1 Amend URLconf +2.6.2.1 Amend URLconf ..................... First, open the ‘polls/urls.py’ URLconf and change it like so: @@ -10323,7 +12464,7 @@ second and third patterns has changed from ‘’ to ‘’.  File: django.info, Node: Amend views, Prev: Amend URLconf, Up: Use generic views Less code is better -2.3.2.2 Amend views +2.6.2.2 Amend views ................... Next, we’re going to remove our old ‘index’, ‘detail’, and ‘results’ @@ -10362,31 +12503,31 @@ views and use Django’s generic views instead. To do so, open the LiteralBlock: polls/views.py -We’re using two generic views here: *note ListView: 149. and *note -DetailView: 14a. Respectively, those two views abstract the concepts of +We’re using two generic views here: *note ListView: 1a3. and *note +DetailView: 1a4. Respectively, those two views abstract the concepts of “display a list of objects” and “display a detail page for a particular type of object.” * Each generic view needs to know what model it will be acting upon. This is provided using the ‘model’ attribute. - * The *note DetailView: 14a. generic view expects the primary key + * The *note DetailView: 1a4. generic view expects the primary key value captured from the URL to be called ‘"pk"’, so we’ve changed ‘question_id’ to ‘pk’ for the generic views. -By default, the *note DetailView: 14a. generic view uses a template +By default, the *note DetailView: 1a4. generic view uses a template called ‘/_detail.html’. In our case, it would use the template ‘"polls/question_detail.html"’. The ‘template_name’ attribute is used to tell Django to use a specific template name instead of the autogenerated default template name. We also specify the ‘template_name’ for the ‘results’ list view – this ensures that the results view and the detail view have a different appearance when -rendered, even though they’re both a *note DetailView: 14a. behind the +rendered, even though they’re both a *note DetailView: 1a4. behind the scenes. -Similarly, the *note ListView: 149. generic view uses a default template +Similarly, the *note ListView: 1a3. generic view uses a default template called ‘/_list.html’; we use ‘template_name’ to -tell *note ListView: 149. to use our existing ‘"polls/index.html"’ +tell *note ListView: 1a3. to use our existing ‘"polls/index.html"’ template. In previous parts of the tutorial, the templates have been provided with @@ -10404,20 +12545,1427 @@ Django to use the variable you want. Run the server, and use your new polling app based on generic views. For full details on generic views, see the *note generic views -documentation: bb. +documentation: ca. -When you’re comfortable with forms and generic views, read part 5 of -this tutorial to learn about testing our polls app. +When you’re comfortable with forms and generic views, read *note part 5 +of this tutorial: 8e. to learn about testing our polls app.  -File: django.info, Node: Advanced tutorial How to write reusable apps, Prev: Writing your first Django app part 4, Up: Getting started +File: django.info, Node: Writing your first Django app part 5, Next: Writing your first Django app part 6, Prev: Writing your first Django app part 4, Up: Getting started -2.4 Advanced tutorial: How to write reusable apps -================================================= +2.7 Writing your first Django app, part 5 +========================================= -This advanced tutorial begins where Tutorial 7 left off. We’ll be -turning our web-poll into a standalone Python package you can reuse in -new projects and share with other people. +This tutorial begins where *note Tutorial 4: 8d. left off. We’ve built +a web-poll application, and we’ll now create some automated tests for +it. + + Where to get help:: If you’re having trouble going through this + tutorial, please head over to the *note Getting Help: 95. section + of the FAQ. + +* Menu: + +* Introducing automated testing:: +* Basic testing strategies:: +* Writing our first test:: +* Test a view:: +* When testing, more is better: When testing more is better. +* Further testing:: +* What’s next?:: + + +File: django.info, Node: Introducing automated testing, Next: Basic testing strategies, Up: Writing your first Django app part 5 + +2.7.1 Introducing automated testing +----------------------------------- + +* Menu: + +* What are automated tests?:: +* Why you need to create tests:: + + +File: django.info, Node: What are automated tests?, Next: Why you need to create tests, Up: Introducing automated testing + +2.7.1.1 What are automated tests? +................................. + +Tests are routines that check the operation of your code. + +Testing operates at different levels. Some tests might apply to a tiny +detail (`does a particular model method return values as expected?') +while others examine the overall operation of the software (`does a +sequence of user inputs on the site produce the desired result?'). +That’s no different from the kind of testing you did earlier in *note +Tutorial 2: 8b, using the *note shell: 1a8. to examine the behavior of a +method, or running the application and entering data to check how it +behaves. + +What’s different in `automated' tests is that the testing work is done +for you by the system. You create a set of tests once, and then as you +make changes to your app, you can check that your code still works as +you originally intended, without having to perform time consuming manual +testing. + + +File: django.info, Node: Why you need to create tests, Prev: What are automated tests?, Up: Introducing automated testing + +2.7.1.2 Why you need to create tests +.................................... + +So why create tests, and why now? + +You may feel that you have quite enough on your plate just learning +Python/Django, and having yet another thing to learn and do may seem +overwhelming and perhaps unnecessary. After all, our polls application +is working quite happily now; going through the trouble of creating +automated tests is not going to make it work any better. If creating +the polls application is the last bit of Django programming you will +ever do, then true, you don’t need to know how to create automated +tests. But, if that’s not the case, now is an excellent time to learn. + +* Menu: + +* Tests will save you time:: +* Tests don’t just identify problems, they prevent them: Tests don’t just identify problems they prevent them. +* Tests make your code more attractive:: +* Tests help teams work together:: + + +File: django.info, Node: Tests will save you time, Next: Tests don’t just identify problems they prevent them, Up: Why you need to create tests + +2.7.1.3 Tests will save you time +................................ + +Up to a certain point, ‘checking that it seems to work’ will be a +satisfactory test. In a more sophisticated application, you might have +dozens of complex interactions between components. + +A change in any of those components could have unexpected consequences +on the application’s behavior. Checking that it still ‘seems to work’ +could mean running through your code’s functionality with twenty +different variations of your test data to make sure you haven’t broken +something - not a good use of your time. + +That’s especially true when automated tests could do this for you in +seconds. If something’s gone wrong, tests will also assist in +identifying the code that’s causing the unexpected behavior. + +Sometimes it may seem a chore to tear yourself away from your +productive, creative programming work to face the unglamorous and +unexciting business of writing tests, particularly when you know your +code is working properly. + +However, the task of writing tests is a lot more fulfilling than +spending hours testing your application manually or trying to identify +the cause of a newly-introduced problem. + + +File: django.info, Node: Tests don’t just identify problems they prevent them, Next: Tests make your code more attractive, Prev: Tests will save you time, Up: Why you need to create tests + +2.7.1.4 Tests don’t just identify problems, they prevent them +............................................................. + +It’s a mistake to think of tests merely as a negative aspect of +development. + +Without tests, the purpose or intended behavior of an application might +be rather opaque. Even when it’s your own code, you will sometimes find +yourself poking around in it trying to find out what exactly it’s doing. + +Tests change that; they light up your code from the inside, and when +something goes wrong, they focus light on the part that has gone wrong - +`even if you hadn’t even realized it had gone wrong'. + + +File: django.info, Node: Tests make your code more attractive, Next: Tests help teams work together, Prev: Tests don’t just identify problems they prevent them, Up: Why you need to create tests + +2.7.1.5 Tests make your code more attractive +............................................ + +You might have created a brilliant piece of software, but you will find +that many other developers will refuse to look at it because it lacks +tests; without tests, they won’t trust it. Jacob Kaplan-Moss, one of +Django’s original developers, says “Code without tests is broken by +design.” + +That other developers want to see tests in your software before they +take it seriously is yet another reason for you to start writing tests. + + +File: django.info, Node: Tests help teams work together, Prev: Tests make your code more attractive, Up: Why you need to create tests + +2.7.1.6 Tests help teams work together +...................................... + +The previous points are written from the point of view of a single +developer maintaining an application. Complex applications will be +maintained by teams. Tests guarantee that colleagues don’t +inadvertently break your code (and that you don’t break theirs without +knowing). If you want to make a living as a Django programmer, you must +be good at writing tests! + + +File: django.info, Node: Basic testing strategies, Next: Writing our first test, Prev: Introducing automated testing, Up: Writing your first Django app part 5 + +2.7.2 Basic testing strategies +------------------------------ + +There are many ways to approach writing tests. + +Some programmers follow a discipline called “test-driven +development(1)”; they actually write their tests before they write their +code. This might seem counter-intuitive, but in fact it’s similar to +what most people will often do anyway: they describe a problem, then +create some code to solve it. Test-driven development formalizes the +problem in a Python test case. + +More often, a newcomer to testing will create some code and later decide +that it should have some tests. Perhaps it would have been better to +write some tests earlier, but it’s never too late to get started. + +Sometimes it’s difficult to figure out where to get started with writing +tests. If you have written several thousand lines of Python, choosing +something to test might not be easy. In such a case, it’s fruitful to +write your first test the next time you make a change, either when you +add a new feature or fix a bug. + +So let’s do that right away. + + ---------- Footnotes ---------- + + (1) https://en.wikipedia.org/wiki/Test-driven_development + + +File: django.info, Node: Writing our first test, Next: Test a view, Prev: Basic testing strategies, Up: Writing your first Django app part 5 + +2.7.3 Writing our first test +---------------------------- + +* Menu: + +* We identify a bug:: +* Create a test to expose the bug:: +* Running tests:: +* Fixing the bug:: +* More comprehensive tests:: + + +File: django.info, Node: We identify a bug, Next: Create a test to expose the bug, Up: Writing our first test + +2.7.3.1 We identify a bug +......................... + +Fortunately, there’s a little bug in the ‘polls’ application for us to +fix right away: the ‘Question.was_published_recently()’ method returns +‘True’ if the ‘Question’ was published within the last day (which is +correct) but also if the ‘Question’’s ‘pub_date’ field is in the future +(which certainly isn’t). + +Confirm the bug by using the *note shell: 1a8. to check the method on a +question whose date lies in the future: + + $ python manage.py shell + + >>> import datetime + >>> from django.utils import timezone + >>> from polls.models import Question + >>> # create a Question instance with pub_date 30 days in the future + >>> future_question = Question(pub_date=timezone.now() + datetime.timedelta(days=30)) + >>> # was it published recently? + >>> future_question.was_published_recently() + True + +Since things in the future are not ‘recent’, this is clearly wrong. + + +File: django.info, Node: Create a test to expose the bug, Next: Running tests, Prev: We identify a bug, Up: Writing our first test + +2.7.3.2 Create a test to expose the bug +....................................... + +What we’ve just done in the *note shell: 1a8. to test for the problem is +exactly what we can do in an automated test, so let’s turn that into an +automated test. + +A conventional place for an application’s tests is in the application’s +‘tests.py’ file; the testing system will automatically find tests in any +file whose name begins with ‘test’. + +Put the following in the ‘tests.py’ file in the ‘polls’ application: + + import datetime + + from django.test import TestCase + from django.utils import timezone + + from .models import Question + + + class QuestionModelTests(TestCase): + + def test_was_published_recently_with_future_question(self): + """ + was_published_recently() returns False for questions whose pub_date + is in the future. + """ + time = timezone.now() + datetime.timedelta(days=30) + future_question = Question(pub_date=time) + self.assertIs(future_question.was_published_recently(), False) + +LiteralBlock: polls/tests.py + +Here we have created a *note django.test.TestCase: 1b3. subclass with a +method that creates a ‘Question’ instance with a ‘pub_date’ in the +future. We then check the output of ‘was_published_recently()’ - which +`ought' to be False. + + +File: django.info, Node: Running tests, Next: Fixing the bug, Prev: Create a test to expose the bug, Up: Writing our first test + +2.7.3.3 Running tests +..................... + +In the terminal, we can run our test: + + $ python manage.py test polls + +and you’ll see something like: + + Creating test database for alias 'default'... + System check identified no issues (0 silenced). + F + ====================================================================== + FAIL: test_was_published_recently_with_future_question (polls.tests.QuestionModelTests) + ---------------------------------------------------------------------- + Traceback (most recent call last): + File "/path/to/mysite/polls/tests.py", line 16, in test_was_published_recently_with_future_question + self.assertIs(future_question.was_published_recently(), False) + AssertionError: True is not False + + ---------------------------------------------------------------------- + Ran 1 test in 0.001s + + FAILED (failures=1) + Destroying test database for alias 'default'... + + Different error?: If instead you’re getting a ‘NameError’ here, you + may have missed a step in *note Part 2: 17b. where we added imports + of ‘datetime’ and ‘timezone’ to ‘polls/models.py’. Copy the + imports from that section, and try running your tests again. + +What happened is this: + + * ‘manage.py test polls’ looked for tests in the ‘polls’ application + + * it found a subclass of the *note django.test.TestCase: 1b3. class + + * it created a special database for the purpose of testing + + * it looked for test methods - ones whose names begin with ‘test’ + + * in ‘test_was_published_recently_with_future_question’ it created a + ‘Question’ instance whose ‘pub_date’ field is 30 days in the future + + * … and using the ‘assertIs()’ method, it discovered that its + ‘was_published_recently()’ returns ‘True’, though we wanted it to + return ‘False’ + +The test informs us which test failed and even the line on which the +failure occurred. + + +File: django.info, Node: Fixing the bug, Next: More comprehensive tests, Prev: Running tests, Up: Writing our first test + +2.7.3.4 Fixing the bug +...................... + +We already know what the problem is: ‘Question.was_published_recently()’ +should return ‘False’ if its ‘pub_date’ is in the future. Amend the +method in ‘models.py’, so that it will only return ‘True’ if the date is +also in the past: + + def was_published_recently(self): + now = timezone.now() + return now - datetime.timedelta(days=1) <= self.pub_date <= now + +LiteralBlock: polls/models.py + +and run the test again: + + Creating test database for alias 'default'... + System check identified no issues (0 silenced). + . + ---------------------------------------------------------------------- + Ran 1 test in 0.001s + + OK + Destroying test database for alias 'default'... + +After identifying a bug, we wrote a test that exposes it and corrected +the bug in the code so our test passes. + +Many other things might go wrong with our application in the future, but +we can be sure that we won’t inadvertently reintroduce this bug, because +running the test will warn us immediately. We can consider this little +portion of the application pinned down safely forever. + + +File: django.info, Node: More comprehensive tests, Prev: Fixing the bug, Up: Writing our first test + +2.7.3.5 More comprehensive tests +................................ + +While we’re here, we can further pin down the ‘was_published_recently()’ +method; in fact, it would be positively embarrassing if in fixing one +bug we had introduced another. + +Add two more test methods to the same class, to test the behavior of the +method more comprehensively: + + def test_was_published_recently_with_old_question(self): + """ + was_published_recently() returns False for questions whose pub_date + is older than 1 day. + """ + time = timezone.now() - datetime.timedelta(days=1, seconds=1) + old_question = Question(pub_date=time) + self.assertIs(old_question.was_published_recently(), False) + + def test_was_published_recently_with_recent_question(self): + """ + was_published_recently() returns True for questions whose pub_date + is within the last day. + """ + time = timezone.now() - datetime.timedelta(hours=23, minutes=59, seconds=59) + recent_question = Question(pub_date=time) + self.assertIs(recent_question.was_published_recently(), True) + +LiteralBlock: polls/tests.py + +And now we have three tests that confirm that +‘Question.was_published_recently()’ returns sensible values for past, +recent, and future questions. + +Again, ‘polls’ is a minimal application, but however complex it grows in +the future and whatever other code it interacts with, we now have some +guarantee that the method we have written tests for will behave in +expected ways. + + +File: django.info, Node: Test a view, Next: When testing more is better, Prev: Writing our first test, Up: Writing your first Django app part 5 + +2.7.4 Test a view +----------------- + +The polls application is fairly undiscriminating: it will publish any +question, including ones whose ‘pub_date’ field lies in the future. We +should improve this. Setting a ‘pub_date’ in the future should mean +that the Question is published at that moment, but invisible until then. + +* Menu: + +* A test for a view:: +* The Django test client:: +* Improving our view:: +* Testing our new view:: +* Testing the DetailView:: +* Ideas for more tests:: + + +File: django.info, Node: A test for a view, Next: The Django test client, Up: Test a view + +2.7.4.1 A test for a view +......................... + +When we fixed the bug above, we wrote the test first and then the code +to fix it. In fact that was an example of test-driven development, but +it doesn’t really matter in which order we do the work. + +In our first test, we focused closely on the internal behavior of the +code. For this test, we want to check its behavior as it would be +experienced by a user through a web browser. + +Before we try to fix anything, let’s have a look at the tools at our +disposal. + + +File: django.info, Node: The Django test client, Next: Improving our view, Prev: A test for a view, Up: Test a view + +2.7.4.2 The Django test client +.............................. + +Django provides a test *note Client: 1ba. to simulate a user interacting +with the code at the view level. We can use it in ‘tests.py’ or even in +the *note shell: 1a8. + +We will start again with the *note shell: 1a8, where we need to do a +couple of things that won’t be necessary in ‘tests.py’. The first is to +set up the test environment in the *note shell: 1a8.: + + $ python manage.py shell + + >>> from django.test.utils import setup_test_environment + >>> setup_test_environment() + +*note setup_test_environment(): 1bb. installs a template renderer which +will allow us to examine some additional attributes on responses such as +‘response.context’ that otherwise wouldn’t be available. Note that this +method `does not' set up a test database, so the following will be run +against the existing database and the output may differ slightly +depending on what questions you already created. You might get +unexpected results if your ‘TIME_ZONE’ in ‘settings.py’ isn’t correct. +If you don’t remember setting it earlier, check it before continuing. + +Next we need to import the test client class (later in ‘tests.py’ we +will use the *note django.test.TestCase: 1b3. class, which comes with +its own client, so this won’t be required): + + >>> from django.test import Client + >>> # create an instance of the client for our use + >>> client = Client() + +With that ready, we can ask the client to do some work for us: + + >>> # get a response from '/' + >>> response = client.get('/') + Not Found: / + >>> # we should expect a 404 from that address; if you instead see an + >>> # "Invalid HTTP_HOST header" error and a 400 response, you probably + >>> # omitted the setup_test_environment() call described earlier. + >>> response.status_code + 404 + >>> # on the other hand we should expect to find something at '/polls/' + >>> # we'll use 'reverse()' rather than a hardcoded URL + >>> from django.urls import reverse + >>> response = client.get(reverse('polls:index')) + >>> response.status_code + 200 + >>> response.content + b'\n \n\n' + >>> response.context['latest_question_list'] + ]> + + +File: django.info, Node: Improving our view, Next: Testing our new view, Prev: The Django test client, Up: Test a view + +2.7.4.3 Improving our view +.......................... + +The list of polls shows polls that aren’t published yet (i.e. those +that have a ‘pub_date’ in the future). Let’s fix that. + +In *note Tutorial 4: 8d. we introduced a class-based view, based on +*note ListView: 1a3.: + + class IndexView(generic.ListView): + template_name = 'polls/index.html' + context_object_name = 'latest_question_list' + + def get_queryset(self): + """Return the last five published questions.""" + return Question.objects.order_by('-pub_date')[:5] + +LiteralBlock: polls/views.py + +We need to amend the ‘get_queryset()’ method and change it so that it +also checks the date by comparing it with ‘timezone.now()’. First we +need to add an import: + + from django.utils import timezone + +LiteralBlock: polls/views.py + +and then we must amend the ‘get_queryset’ method like so: + + def get_queryset(self): + """ + Return the last five published questions (not including those set to be + published in the future). + """ + return Question.objects.filter( + pub_date__lte=timezone.now() + ).order_by('-pub_date')[:5] + +LiteralBlock: polls/views.py + +‘Question.objects.filter(pub_date__lte=timezone.now())’ returns a +queryset containing ‘Question’s whose ‘pub_date’ is less than or equal +to - that is, earlier than or equal to - ‘timezone.now’. + + +File: django.info, Node: Testing our new view, Next: Testing the DetailView, Prev: Improving our view, Up: Test a view + +2.7.4.4 Testing our new view +............................ + +Now you can satisfy yourself that this behaves as expected by firing up +‘runserver’, loading the site in your browser, creating ‘Questions’ with +dates in the past and future, and checking that only those that have +been published are listed. You don’t want to have to do that `every +single time you make any change that might affect this' - so let’s also +create a test, based on our *note shell: 1a8. session above. + +Add the following to ‘polls/tests.py’: + + from django.urls import reverse + +LiteralBlock: polls/tests.py + +and we’ll create a shortcut function to create questions as well as a +new test class: + + def create_question(question_text, days): + """ + Create a question with the given `question_text` and published the + given number of `days` offset to now (negative for questions published + in the past, positive for questions that have yet to be published). + """ + time = timezone.now() + datetime.timedelta(days=days) + return Question.objects.create(question_text=question_text, pub_date=time) + + + class QuestionIndexViewTests(TestCase): + def test_no_questions(self): + """ + If no questions exist, an appropriate message is displayed. + """ + response = self.client.get(reverse('polls:index')) + self.assertEqual(response.status_code, 200) + self.assertContains(response, "No polls are available.") + self.assertQuerysetEqual(response.context['latest_question_list'], []) + + def test_past_question(self): + """ + Questions with a pub_date in the past are displayed on the + index page. + """ + question = create_question(question_text="Past question.", days=-30) + response = self.client.get(reverse('polls:index')) + self.assertQuerysetEqual( + response.context['latest_question_list'], + [question], + ) + + def test_future_question(self): + """ + Questions with a pub_date in the future aren't displayed on + the index page. + """ + create_question(question_text="Future question.", days=30) + response = self.client.get(reverse('polls:index')) + self.assertContains(response, "No polls are available.") + self.assertQuerysetEqual(response.context['latest_question_list'], []) + + def test_future_question_and_past_question(self): + """ + Even if both past and future questions exist, only past questions + are displayed. + """ + question = create_question(question_text="Past question.", days=-30) + create_question(question_text="Future question.", days=30) + response = self.client.get(reverse('polls:index')) + self.assertQuerysetEqual( + response.context['latest_question_list'], + [question], + ) + + def test_two_past_questions(self): + """ + The questions index page may display multiple questions. + """ + question1 = create_question(question_text="Past question 1.", days=-30) + question2 = create_question(question_text="Past question 2.", days=-5) + response = self.client.get(reverse('polls:index')) + self.assertQuerysetEqual( + response.context['latest_question_list'], + [question2, question1], + ) + +LiteralBlock: polls/tests.py + +Let’s look at some of these more closely. + +First is a question shortcut function, ‘create_question’, to take some +repetition out of the process of creating questions. + +‘test_no_questions’ doesn’t create any questions, but checks the +message: “No polls are available.” and verifies the +‘latest_question_list’ is empty. Note that the *note +django.test.TestCase: 1b3. class provides some additional assertion +methods. In these examples, we use *note assertContains(): 1be. and +*note assertQuerysetEqual(): 1bf. + +In ‘test_past_question’, we create a question and verify that it appears +in the list. + +In ‘test_future_question’, we create a question with a ‘pub_date’ in the +future. The database is reset for each test method, so the first +question is no longer there, and so again the index shouldn’t have any +questions in it. + +And so on. In effect, we are using the tests to tell a story of admin +input and user experience on the site, and checking that at every state +and for every new change in the state of the system, the expected +results are published. + + +File: django.info, Node: Testing the DetailView, Next: Ideas for more tests, Prev: Testing our new view, Up: Test a view + +2.7.4.5 Testing the ‘DetailView’ +................................ + +What we have works well; however, even though future questions don’t +appear in the `index', users can still reach them if they know or guess +the right URL. So we need to add a similar constraint to ‘DetailView’: + + class DetailView(generic.DetailView): + ... + def get_queryset(self): + """ + Excludes any questions that aren't published yet. + """ + return Question.objects.filter(pub_date__lte=timezone.now()) + +LiteralBlock: polls/views.py + +We should then add some tests, to check that a ‘Question’ whose +‘pub_date’ is in the past can be displayed, and that one with a +‘pub_date’ in the future is not: + + class QuestionDetailViewTests(TestCase): + def test_future_question(self): + """ + The detail view of a question with a pub_date in the future + returns a 404 not found. + """ + future_question = create_question(question_text='Future question.', days=5) + url = reverse('polls:detail', args=(future_question.id,)) + response = self.client.get(url) + self.assertEqual(response.status_code, 404) + + def test_past_question(self): + """ + The detail view of a question with a pub_date in the past + displays the question's text. + """ + past_question = create_question(question_text='Past Question.', days=-5) + url = reverse('polls:detail', args=(past_question.id,)) + response = self.client.get(url) + self.assertContains(response, past_question.question_text) + +LiteralBlock: polls/tests.py + + +File: django.info, Node: Ideas for more tests, Prev: Testing the DetailView, Up: Test a view + +2.7.4.6 Ideas for more tests +............................ + +We ought to add a similar ‘get_queryset’ method to ‘ResultsView’ and +create a new test class for that view. It’ll be very similar to what we +have just created; in fact there will be a lot of repetition. + +We could also improve our application in other ways, adding tests along +the way. For example, it’s silly that ‘Questions’ can be published on +the site that have no ‘Choices’. So, our views could check for this, +and exclude such ‘Questions’. Our tests would create a ‘Question’ +without ‘Choices’ and then test that it’s not published, as well as +create a similar ‘Question’ `with' ‘Choices’, and test that it `is' +published. + +Perhaps logged-in admin users should be allowed to see unpublished +‘Questions’, but not ordinary visitors. Again: whatever needs to be +added to the software to accomplish this should be accompanied by a +test, whether you write the test first and then make the code pass the +test, or work out the logic in your code first and then write a test to +prove it. + +At a certain point you are bound to look at your tests and wonder +whether your code is suffering from test bloat, which brings us to: + + +File: django.info, Node: When testing more is better, Next: Further testing, Prev: Test a view, Up: Writing your first Django app part 5 + +2.7.5 When testing, more is better +---------------------------------- + +It might seem that our tests are growing out of control. At this rate +there will soon be more code in our tests than in our application, and +the repetition is unaesthetic, compared to the elegant conciseness of +the rest of our code. + +`It doesn’t matter'. Let them grow. For the most part, you can write a +test once and then forget about it. It will continue performing its +useful function as you continue to develop your program. + +Sometimes tests will need to be updated. Suppose that we amend our +views so that only ‘Questions’ with ‘Choices’ are published. In that +case, many of our existing tests will fail - `telling us exactly which +tests need to be amended to bring them up to date', so to that extent +tests help look after themselves. + +At worst, as you continue developing, you might find that you have some +tests that are now redundant. Even that’s not a problem; in testing +redundancy is a `good' thing. + +As long as your tests are sensibly arranged, they won’t become +unmanageable. Good rules-of-thumb include having: + + * a separate ‘TestClass’ for each model or view + + * a separate test method for each set of conditions you want to test + + * test method names that describe their function + + +File: django.info, Node: Further testing, Next: What’s next?, Prev: When testing more is better, Up: Writing your first Django app part 5 + +2.7.6 Further testing +--------------------- + +This tutorial only introduces some of the basics of testing. There’s a +great deal more you can do, and a number of very useful tools at your +disposal to achieve some very clever things. + +For example, while our tests here have covered some of the internal +logic of a model and the way our views publish information, you can use +an “in-browser” framework such as Selenium(1) to test the way your HTML +actually renders in a browser. These tools allow you to check not just +the behavior of your Django code, but also, for example, of your +JavaScript. It’s quite something to see the tests launch a browser, and +start interacting with your site, as if a human being were driving it! +Django includes *note LiveServerTestCase: 1c4. to facilitate integration +with tools like Selenium. + +If you have a complex application, you may want to run tests +automatically with every commit for the purposes of continuous +integration(2), so that quality control is itself - at least partially - +automated. + +A good way to spot untested parts of your application is to check code +coverage. This also helps identify fragile or even dead code. If you +can’t test a piece of code, it usually means that code should be +refactored or removed. Coverage will help to identify dead code. See +*note Integration with coverage.py: 1c5. for details. + +*note Testing in Django: ec. has comprehensive information about +testing. + + ---------- Footnotes ---------- + + (1) https://www.selenium.dev/ + + (2) https://en.wikipedia.org/wiki/Continuous_integration + + +File: django.info, Node: What’s next?, Prev: Further testing, Up: Writing your first Django app part 5 + +2.7.7 What’s next? +------------------ + +For full details on testing, see *note Testing in Django: ec. + +When you’re comfortable with testing Django views, read *note part 6 of +this tutorial: 8f. to learn about static files management. + + +File: django.info, Node: Writing your first Django app part 6, Next: Writing your first Django app part 7, Prev: Writing your first Django app part 5, Up: Getting started + +2.8 Writing your first Django app, part 6 +========================================= + +This tutorial begins where *note Tutorial 5: 8e. left off. We’ve built +a tested web-poll application, and we’ll now add a stylesheet and an +image. + +Aside from the HTML generated by the server, web applications generally +need to serve additional files — such as images, JavaScript, or CSS — +necessary to render the complete web page. In Django, we refer to these +files as “static files”. + +For small projects, this isn’t a big deal, because you can keep the +static files somewhere your web server can find it. However, in bigger +projects – especially those comprised of multiple apps – dealing with +the multiple sets of static files provided by each application starts to +get tricky. + +That’s what ‘django.contrib.staticfiles’ is for: it collects static +files from each of your applications (and any other places you specify) +into a single location that can easily be served in production. + + Where to get help:: If you’re having trouble going through this + tutorial, please head over to the *note Getting Help: 95. section + of the FAQ. + +* Menu: + +* Customize your app’s look and feel:: +* Adding a background-image:: + + +File: django.info, Node: Customize your app’s look and feel, Next: Adding a background-image, Up: Writing your first Django app part 6 + +2.8.1 Customize your `app’s' look and feel +------------------------------------------ + +First, create a directory called ‘static’ in your ‘polls’ directory. +Django will look for static files there, similarly to how Django finds +templates inside ‘polls/templates/’. + +Django’s *note STATICFILES_FINDERS: 1ca. setting contains a list of +finders that know how to discover static files from various sources. +One of the defaults is ‘AppDirectoriesFinder’ which looks for a “static” +subdirectory in each of the *note INSTALLED_APPS: 16a, like the one in +‘polls’ we just created. The admin site uses the same directory +structure for its static files. + +Within the ‘static’ directory you have just created, create another +directory called ‘polls’ and within that create a file called +‘style.css’. In other words, your stylesheet should be at +‘polls/static/polls/style.css’. Because of how the +‘AppDirectoriesFinder’ staticfile finder works, you can refer to this +static file in Django as ‘polls/style.css’, similar to how you reference +the path for templates. + + Static file namespacing: Just like templates, we `might' be able to + get away with putting our static files directly in ‘polls/static’ + (rather than creating another ‘polls’ subdirectory), but it would + actually be a bad idea. Django will choose the first static file + it finds whose name matches, and if you had a static file with the + same name in a `different' application, Django would be unable to + distinguish between them. We need to be able to point Django at + the right one, and the best way to ensure this is by `namespacing' + them. That is, by putting those static files inside `another' + directory named for the application itself. + +Put the following code in that stylesheet +(‘polls/static/polls/style.css’): + + li a { + color: green; + } + +LiteralBlock: polls/static/polls/style.css + +Next, add the following at the top of +‘polls/templates/polls/index.html’: + + {% load static %} + + + +LiteralBlock: polls/templates/polls/index.html + +The ‘{% static %}’ template tag generates the absolute URL of static +files. + +That’s all you need to do for development. + +Start the server (or restart it if it’s already running): + + $ python manage.py runserver + +Reload ‘http://localhost:8000/polls/’ and you should see that the +question links are green (Django style!) which means that your +stylesheet was properly loaded. + + +File: django.info, Node: Adding a background-image, Prev: Customize your app’s look and feel, Up: Writing your first Django app part 6 + +2.8.2 Adding a background-image +------------------------------- + +Next, we’ll create a subdirectory for images. Create an ‘images’ +subdirectory in the ‘polls/static/polls/’ directory. Inside this +directory, put an image called ‘background.gif’. In other words, put +your image in ‘polls/static/polls/images/background.gif’. + +Then, add to your stylesheet (‘polls/static/polls/style.css’): + + body { + background: white url("images/background.gif") no-repeat; + } + +LiteralBlock: polls/static/polls/style.css + +Reload ‘http://localhost:8000/polls/’ and you should see the background +loaded in the top left of the screen. + + Warning: The ‘{% static %}’ template tag is not available for use + in static files which aren’t generated by Django, like your + stylesheet. You should always use `relative paths' to link your + static files between each other, because then you can change *note + STATIC_URL: 1cc. (used by the *note static: 1cd. template tag to + generate its URLs) without having to modify a bunch of paths in + your static files as well. + +These are the `basics'. For more details on settings and other bits +included with the framework see *note the static files howto: 141. and +*note the staticfiles reference: 11a. *note Deploying static files: f3. +discusses how to use static files on a real server. + +When you’re comfortable with the static files, read *note part 7 of this +tutorial: 90. to learn how to customize Django’s automatically-generated +admin site. + + +File: django.info, Node: Writing your first Django app part 7, Next: Advanced tutorial How to write reusable apps, Prev: Writing your first Django app part 6, Up: Getting started + +2.9 Writing your first Django app, part 7 +========================================= + +This tutorial begins where *note Tutorial 6: 8f. left off. We’re +continuing the web-poll application and will focus on customizing +Django’s automatically-generated admin site that we first explored in +*note Tutorial 2: 8b. + + Where to get help:: If you’re having trouble going through this + tutorial, please head over to the *note Getting Help: 95. section + of the FAQ. + +* Menu: + +* Customize the admin form:: +* Adding related objects:: +* Customize the admin change list:: +* Customize the admin look and feel:: +* Customize the admin index page:: +* What’s next?: What’s next?<2>. + + +File: django.info, Node: Customize the admin form, Next: Adding related objects, Up: Writing your first Django app part 7 + +2.9.1 Customize the admin form +------------------------------ + +By registering the ‘Question’ model with +‘admin.site.register(Question)’, Django was able to construct a default +form representation. Often, you’ll want to customize how the admin form +looks and works. You’ll do this by telling Django the options you want +when you register the object. + +Let’s see how this works by reordering the fields on the edit form. +Replace the ‘admin.site.register(Question)’ line with: + + from django.contrib import admin + + from .models import Question + + + class QuestionAdmin(admin.ModelAdmin): + fields = ['pub_date', 'question_text'] + + admin.site.register(Question, QuestionAdmin) + +LiteralBlock: polls/admin.py + +You’ll follow this pattern – create a model admin class, then pass it as +the second argument to ‘admin.site.register()’ – any time you need to +change the admin options for a model. + +This particular change above makes the “Publication date” come before +the “Question” field: + +[image src="django-figures/admin07.png" alt="Fields have been reordered"] + +This isn’t impressive with only two fields, but for admin forms with +dozens of fields, choosing an intuitive order is an important usability +detail. + +And speaking of forms with dozens of fields, you might want to split the +form up into fieldsets: + + from django.contrib import admin + + from .models import Question + + + class QuestionAdmin(admin.ModelAdmin): + fieldsets = [ + (None, {'fields': ['question_text']}), + ('Date information', {'fields': ['pub_date']}), + ] + + admin.site.register(Question, QuestionAdmin) + +LiteralBlock: polls/admin.py + +The first element of each tuple in *note fieldsets: 1d0. is the title of +the fieldset. Here’s what our form looks like now: + +[image src="django-figures/admin08t.png" alt="Form has fieldsets now"] + + +File: django.info, Node: Adding related objects, Next: Customize the admin change list, Prev: Customize the admin form, Up: Writing your first Django app part 7 + +2.9.2 Adding related objects +---------------------------- + +OK, we have our Question admin page, but a ‘Question’ has multiple +‘Choice’s, and the admin page doesn’t display choices. + +Yet. + +There are two ways to solve this problem. The first is to register +‘Choice’ with the admin just as we did with ‘Question’: + + from django.contrib import admin + + from .models import Choice, Question + # ... + admin.site.register(Choice) + +LiteralBlock: polls/admin.py + +Now “Choices” is an available option in the Django admin. The “Add +choice” form looks like this: + +[image src="django-figures/admin09.png" alt="Choice admin page"] + +In that form, the “Question” field is a select box containing every +question in the database. Django knows that a *note ForeignKey: 174. +should be represented in the admin as a ‘’, ‘’ elements. (A *note -ModelForm: 3a2. maps a model class’s fields to HTML form ‘’ -elements via a *note Form: 44b.; this is what the Django admin is based +ModelForm: 480. maps a model class’s fields to HTML form ‘’ +elements via a *note Form: 52a.; this is what the Django admin is based upon.) A form’s fields are themselves classes; they manage form data and -perform validation when a form is submitted. A *note DateField: 44d. -and a *note FileField: 39c. handle very different kinds of data and have +perform validation when a form is submitted. A *note DateField: 52c. +and a *note FileField: 47a. handle very different kinds of data and have to do different things with it. A form field is represented to a user in the browser as an HTML “widget” - a piece of user interface machinery. Each field type has an -appropriate default *note Widget class: cf, but these can be overridden +appropriate default *note Widget class: e0, but these can be overridden as required.  File: django.info, Node: Instantiating processing and rendering forms, Prev: The Django Form class, Up: Forms in Django -3.3.3.2 Instantiating, processing, and rendering forms +3.4.3.2 Instantiating, processing, and rendering forms ...................................................... When rendering an object in Django, we generally: @@ -23144,7 +27974,7 @@ information back to it too.  File: django.info, Node: Building a form, Next: More about Django Form classes, Prev: Forms in Django, Up: Working with forms -3.3.4 Building a form +3.4.4 Building a form --------------------- * Menu: @@ -23155,7 +27985,7 @@ File: django.info, Node: Building a form, Next: More about Django Form classes  File: django.info, Node: The work that needs to be done, Next: Building a form in Django, Up: Building a form -3.3.4.1 The work that needs to be done +3.4.4.1 The work that needs to be done ...................................... Suppose you want to create a simple form on your website, in order to @@ -23200,7 +28030,7 @@ us.  File: django.info, Node: Building a form in Django, Prev: The work that needs to be done, Up: Building a form -3.3.4.2 Building a form in Django +3.4.4.2 Building a form in Django ................................. * Menu: @@ -23212,7 +28042,7 @@ File: django.info, Node: Building a form in Django, Prev: The work that needs  File: django.info, Node: The Form class, Next: The view, Up: Building a form in Django -3.3.4.3 The ‘Form’ class +3.4.4.3 The ‘Form’ class ........................ We already know what we want our HTML form to look like. Our starting @@ -23225,26 +28055,26 @@ point for it in Django is this: LiteralBlock: forms.py -This defines a *note Form: 44b. class with a single field (‘your_name’). +This defines a *note Form: 52a. class with a single field (‘your_name’). We’ve applied a human-friendly label to the field, which will appear in the ‘