Django Unleashed

Book description

Django is an amazingly powerful system for creating modern, dynamic websites. But programming Django hasn’t always been easy–until now. Django Unleashed is your step-by-step, beginner-friendly guide to leveraging Django’s core capabilities and its powerful contributed library. You’ll learn in the most effective way possible: hands on, by building a fully functional Django website from scratch. You’ll even deploy the website to the cloud.

As you build your website, expert Django consultant and trainer Andrew Pinkham reveals how websites operate; how Django makes building websites easy; how to write Python code that leverages its immense capabilities; and how to build solutions that are robust, reliable, and secure. You’ll start simply and learn to solve increasingly challenging problems: mastering new features and understanding how Django’s architecture shapes their behavior, and gaining essential knowledge for working with any web framework, not just Django.

Drawing on his extensive experience teaching Django, Pinkham answers the key questions beginners ask most often. And as you gain experience, you’ll learn advanced techniques for enhancing site functionality and performance, strengthening security, promoting code reuse, and much more.

Detailed information on how to…

  • Quickly start a new Django project and establish a strong foundation for a growing site

  • Define how your data is organized and create a SQLite database to manage it

  • Quickly produce HTML with Django templates

  • Create dynamic webpages with Django’s URL patterns and views, including function views, class-based views, and generic views

  • Enable efficient, reliable data input with Django Forms and custom form validations

  • Understand the Model-View-Controller (MVC) architecture, compare it to Model-Template-Views, and gain a holistic understanding of Django’s structure

  • Write as little code as possible, simplify code reuse, and mitigate software decay by adhering to the Don’t Repeat Yourself paradigm.

  • Dive into Django source code to troubleshoot problems

  • Extend site functionality with Django’s contributed library

  • Protect your site with user authentication and permissions

  • Avoid security pitfalls such as SQL Injection, XSS, and CSRF

  • Optimize site performance

  • Deploy your site to a managed cloud service and to a PostgreSQL database

  • Table of contents

    1. Title Page
    2. Copyright Page
    3. Contents
    4. Preface
      1. Is This Book for Me?
      2. What This Book Contains
      3. Conventions Used in This Book
    5. Acknowledgments
    6. About the Author
    7. We Want to Hear from You!
    8. Reader Services
    9. I: Django’s Core Features
      1. 1. Starting a New Django Project: Building a Startup Categorizer with Blog
        1. 1.1 Introduction
        2. 1.2 Website Basics
        3. 1.3 Understanding Modern Websites
        4. 1.4 Building Modern Websites: The Problems That Frameworks Solve and Their Caveats
        5. 1.5 Django: Python Web Framework
        6. 1.6 Defining the Project in Part I
          1. 1.6.1 Selecting Django and Python Versions
          2. 1.6.2 Project Specifications
        7. 1.7 Creating a New Django Project and Django Apps
          1. 1.7.1 Generating the Project Structure
          2. 1.7.2 Checking Our Installation by Invoking Django’s runserver via manage.py
          3. 1.7.3 Creating New Django Apps with manage.py
          4. 1.7.4 Connecting Our New Django Apps to Our Django Project in settings.py
        8. 1.8 Putting It All Together
      2. 2. Hello World: Building a Basic Webpage in Django
        1. 2.1 Introduction
        2. 2.2 Creating and Integrating a New App
        3. 2.3 Building Hello World
          1. 2.3.1 Webpage Data
          2. 2.3.2 Webpage URL
        4. 2.4 Displaying Hello World
        5. 2.5 Controller Limitations: The Advantages of Models and Views
        6. 2.6 Removing Our Helloworld App from Our Project
        7. 2.7 Putting It All Together
      3. 3. Programming Django Models and Creating a SQLite Database
        1. 3.1 Introduction
        2. 3.2 Why Use a Database?
        3. 3.3 Organizing Our Data
          1. 3.3.1 Accessing Data: Understanding Django’s Slug
        4. 3.4 Specifying and Organizing Data in Django Using Models
          1. 3.4.1 A First Look at Django Models and Fields
          2. 3.4.2 Completing Our Django Models
          3. 3.4.3 Adding Relational Fields to Our Models
          4. 3.4.4 Controlling Model Field Behavior with Field Options
          5. 3.4.5 Adding Methods to Django Models
          6. 3.4.6 Controlling Model Behavior with Nested Meta Classes
        5. 3.5 Using Django to Automatically Create a SQLite Database with manage.py
          1. 3.5.1 Understanding Migrations
          2. 3.5.2 Creating Migrations
          3. 3.5.3 Applying Migrations to Create or Modify a Database
        6. 3.6 Manipulating Data in the Database: Managers and QuerySets
          1. 3.6.1 Basic Database Interaction via Models
          2. 3.6.2 Database Interaction via Managers
        7. 3.7 String Case Ordering
        8. 3.8 Putting It All Together
      4. 4. Rapidly Producing Flexible HTML with Django Templates
        1. 4.1 Introduction
        2. 4.2 Revisiting Hello World: The Advantages of Templates
        3. 4.3 Understanding Django Templates and Their Goals
        4. 4.4 Choosing a Format, an Engine, and a Location for Templates
        5. 4.5 Building a First Template: A Single Tag Object
          1. 4.5.1 Coding the Foundation of the Template in HTML
          2. 4.5.2 Filling in Content with Template Variables
          3. 4.5.3 Adding Logic with Template Tags
          4. 4.5.4 Controlling the Output of Variables with Template Filters title, length, and pluralize
        6. 4.6 Building the Rest of Our App Templates
          1. 4.6.1 Template for a List of Tag objects
          2. 4.6.2 Template for a Single Startup Object
          3. 4.6.3 Template for a List of Startup Objects
          4. 4.6.4 Template for a Single Blog Post
          5. 4.6.5 Template for a List of Blog Posts
        7. 4.7 Using Template Inheritance for Design Consistency
          1. 4.7.1 Informing Django of the Existence of Site-wide Templates
          2. 4.7.2 Building the Site-wide Generic Template
          3. 4.7.3 Using the Generic Template in Our Tag List Template
          4. 4.7.4 Building the App-Generic Templates
          5. 4.7.5 Using the Generic Templates in the Rest of the App Templates
        8. 4.8 Using Templates in Python with the Template, Context, and loader Classes
          1. 4.8.1 Using Templates in the Shell
          2. 4.8.2 Using Templates in Views
        9. 4.9 Putting It All Together
      5. 5. Creating Webpages with Controllers in Django: Views and URL Configurations
        1. 5.1 Introduction
        2. 5.2 The Purpose of Views and URL Configurations
          1. 5.2.1 Django URL Configurations
          2. 5.2.2 Django Views
        3. 5.3 Step-by-Step Examination of Django’s Use of Views and URL Configurations
        4. 5.4 Building Tag Detail Webpage
          1. 5.4.1 Coding the tag_detail() Function View
          2. 5.4.2 Adding a URL Pattern for tag_detail
        5. 5.5 Generating 404 Errors for Invalid Queries
        6. 5.6 Shortening the Development Process with Django View Shortcuts
          1. 5.6.1 Shortening Code with get_object_or_404()
          2. 5.6.2 Shortening Code with render_to_response()
          3. 5.6.3 Shortening Code with render()
        7. 5.7 URL Configuration Internals: Adhering to App Encapsulation
          1. 5.7.1 Introspecting URL Patterns
          2. 5.7.2 Using include to Create a Hierarchy of URL Configurations
        8. 5.8 Implementing the Views and URL Configurations to the Rest of the Site
          1. 5.8.1 Restructuring Our homepage() View
          2. 5.8.2 Building a Startup List Page
          3. 5.8.3 Building a Startup Detail Page
          4. 5.8.4 Connecting the URL Configuration to Our Blog App
          5. 5.8.5 Building a Post List Page
          6. 5.8.6 Building a Post Detail Page
        9. 5.9 Class-Based Views
          1. 5.9.1 Comparing Class-Based Views to Functions Views
          2. 5.9.2 Advantages of Class-Based Views
          3. 5.9.3 View Internals
          4. 5.9.4 Class-Based Views Review
        10. 5.10 Redirecting the Homepage
          1. 5.10.1 Directing the Homepage with URL Configurations
          2. 5.10.2 Redirecting the Homepage with Views
        11. 5.11 Putting It All Together
      6. 6. Integrating Models, Templates, Views, and URL Configurations to Create Links between Webpages
        1. 6.1 Introduction
        2. 6.2 Generating URLs in Python and Django Templates
          1. 6.2.1 Reversing URL Patterns
          2. 6.2.2 Reversing Regular Expression Patterns with Character Sets
          3. 6.2.3 Canonical Model URLs
          4. 6.2.4 The NoReverseMatch Exception
        3. 6.3 Using the url Template Tag to Build a Navigation Menu
          1. 6.3.1 Building the <nav> Menu in HTML and Hardcoding Our Links
          2. 6.3.2 Using the url Template Tag to Create URL Paths for the Navigation Menu
        4. 6.4 Linking List Pages to Detail Pages
          1. 6.4.1 Using url to Create Detail Page Links
          2. 6.4.2 Replacing Detail Page Links with get_absolute_url()
        5. 6.5 Creating Links on the Object Detail Pages
        6. 6.6 Revisiting Homepage Redirection
        7. 6.7 Putting It All Together
      7. 7. Allowing User Input with Forms
        1. 7.1 Introduction
        2. 7.2 Django Forms as State Machines
        3. 7.3 Creating TagForm, a Form for Tag Objects
          1. 7.3.1 Implementing the save() Method for TagForm
          2. 7.3.2 Using TagForm in the Django Shell
          3. 7.3.3 Form Validation Techniques in Django
          4. 7.3.4 Creating a Clean Method for the Tag Model name Field
          5. 7.3.5 Preparing to Build a Clean Method for the Tag Model slug Field
          6. 7.3.6 Creating a Clean Method for the Tag Model slug Field
          7. 7.3.7 Using ModelForm Inheritance to Connect TagForm to Tag
          8. 7.3.8 Understanding ModelForm Validation
          9. 7.3.9 Updating Objects with ModelForm
        4. 7.4 Building the Forms for Startup, Newslink, and Post Models
          1. 7.4.1 Creating PostForm
          2. 7.4.2 Creating StartupForm and NewsLinkForm
        5. 7.5 Putting It All Together
      8. 8. Displaying Forms in Templates
        1. 8.1 Introduction
        2. 8.2 Creating a New Template to Create Tag Objects
          1. 8.2.1 Using Template Variables to Make the TagForm Template Dynamic
          2. 8.2.2 Displaying Form Errors in tag_form.html
          3. 8.2.3 Redisplaying Bound Form Values in tag_form.html
          4. 8.2.4 Maintaining the DRY Principle in tag_form.html
          5. 8.2.5 Looping over Form Fields
          6. 8.2.6 Printing Forms Directly
        3. 8.3 Creating a New Template to Update Tag Objects
        4. 8.4 Creating a New Template to Delete Tag Objects
        5. 8.5 Creating Templates for StartupForm, NewsLinkForm, and PostForm
        6. 8.6 Reconsidering Template Inheritance
        7. 8.7 Putting It All Together
      9. 9. Controlling Forms in Views
        1. 9.1 Introduction
        2. 9.2 Webpages for Creating Objects
          1. 9.2.1 Understanding Expected Form Behavior
          2. 9.2.2 Implementing a Webpage to Create Tags
          3. 9.2.3 Creating Post Objects in a View with PostForm
          4. 9.2.4 Creating Startup Objects in a View with StartupForm
          5. 9.2.5 Creating NewsLink Objects in a View with NewsLinkForm
          6. 9.2.6 Shortening Organizer Views
        3. 9.3 Webpages for Updating Objects
          1. 9.3.1 Creating a View to Modify Post Objects
          2. 9.3.2 Creating a View to Modify NewsLink Objects
          3. 9.3.3 Webpages to Update Startup and Tag Objects
        4. 9.4 Webpages for Deleting Objects
          1. 9.4.1 Creating a Webpage to Delete Post Objects
          2. 9.4.2 Creating a Webpage to Delete NewsLink Objects
          3. 9.4.3 Webpages to Delete Startup and Tag Objects
        5. 9.5 Putting It All Together
      10. 10. Revisiting Migrations
        1. 10.1 Introduction
        2. 10.2 Last Week’s Episode (Reviewing Chapter 3)
        3. 10.3 Data Migrations
          1. 10.3.1 Tag Data
          2. 10.3.2 Startup Data
          3. 10.3.3 Post Data
        4. 10.4 Schema Migrations
          1. 10.4.1 Making Our Lives Difficult with a Data Migration
          2. 10.4.2 Adding a slug to NewsLink
          3. 10.4.3 Ensuring a Unique Identifier for NewsLink
          4. 10.4.4 Making Relations Optional in Forms
        5. 10.5 Putting It All Together
      11. 11. Bending the Rules: The Contact Us Webpage
        1. 11.1 Introduction
        2. 11.2 Creating a contact App
        3. 11.3 Creating the Contact Webpage
          1. 11.3.1 Contact Form
          2. 11.3.2 Contact URL Pattern and View
          3. 11.3.3 Contact Templates
        4. 11.4 Splitting Organizer urls.py
        5. 11.5 Putting It All Together
      12. 12. The Big Picture
        1. 12.1 Introduction
        2. 12.2 Django’s Core
        3. 12.3 Webpages with Views and URL Configurations
          1. 12.3.1 Views
          2. 12.3.2 URL Patterns and Configurations
        4. 12.4 Generating Webpages Thanks to Models and Templates
          1. 12.4.1 Structuring and Storing Data in Models
          2. 12.4.2 Controlling Markup with Django Templates
        5. 12.5 Interacting with Data via Forms
        6. 12.6 Intervening in Control Flow
        7. 12.7 Moving Forward
    10. II: Django’s Contributed Libraries
      1. 13. Django’s Contributed Library
        1. 13.1 Introduction
        2. 13.2 Django’s Source Code (and Versioning)
        3. 13.3 Django’s contrib Code
        4. 13.4 Content (Not) Covered
        5. 13.5 Translation
        6. 13.6 Putting It All Together
      2. 14. Pagination: A Tool for Navigation
        1. 14.1 Introduction
        2. 14.2 A Word about URLs: Query versus Path
        3. 14.3 Discovering Django Pagination in the Shell
        4. 14.4 Paginating the Startup List Webpage
        5. 14.5 Pagination of Tag List Webpage Using the URL Path
        6. 14.6 Putting It All Together
      3. 15. Creating Webpages with Django Flatpages
        1. 15.1 Introduction
        2. 15.2 Enabling Flatpages
        3. 15.3 Anatomy of the App
        4. 15.4 Building an About Webpage
          1. 15.4.1 Creating a Template
          2. 15.4.2 Creating the About FlatPage
          3. 15.4.3 Displaying FlatPage Objects via the URL Configuration
          4. 15.4.4 Displaying FlatPage Objects via Middleware
          5. 15.4.5 Switching Back to a URL Configuration
        5. 15.5 Linking to FlatPage Objects
        6. 15.6 Security Implications of FlatPages
        7. 15.7 Migrations for Sites and Flatpages
          1. 15.7.1 The Core App
          2. 15.7.2 Data Migration for Site
          3. 15.7.3 Data Migration for FlatPage
        8. 15.8 Putting It All Together
      4. 16. Serving Static Content with Django
        1. 16.1 Introduction
        2. 16.2 Adding Static Content for Apps
        3. 16.3 Adding Static Content for the Project
        4. 16.4 Integrating Real CSS Content
        5. 16.5 Putting It All Together
      5. 17. Understanding Generic Class-Based Views
        1. 17.1 Introduction
        2. 17.2 Building Generic Object Detail Pages
          1. 17.2.1 Converting to Class-Based Views
          2. 17.2.2 Generic Behavior
          3. 17.2.3 Anticipating Behavior Overrides
          4. 17.2.4 Switching to Django’s GCBV
        3. 17.3 Why Use Classes for Generic Views?
        4. 17.4 Building Generic Object Create Pages
        5. 17.5 Replacing CBVs with GCBVs
          1. 17.5.1 Organizer Views
          2. 17.5.2 Blog Views
          3. 17.5.3 Returning to Redirection
          4. 17.5.4 Replacing Flatpages
          5. 17.5.5 Overriding Methods (in NewsLinkDelete)
        6. 17.6 Forgoing GCBVs
        7. 17.7 Adding Behavior with GCBV
          1. 17.7.1 Yearly Archive for Post
          2. 17.7.2 Monthly Archive for Post
          3. 17.7.3 Creating ArchiveIndexView
        8. 17.8 Putting It All Together
      6. 18. Advanced Generic Class-Based View Usage
        1. 18.1 Introduction
        2. 18.2 Rapid Review of GCBV
        3. 18.3 Globally Setting Template Suffix for Update Views
        4. 18.4 Generating Pagination Links
          1. 18.4.1 StartupList Pagination
          2. 18.4.2 TagList Pagination
          3. 18.4.3 Pagination Links
          4. 18.4.4 Extending Pagination Behavior Further
        5. 18.5 Re-creating PostDetail with DateDetailView
        6. 18.6 Switching to GCBVs with PostGetMixin in Post Views
        7. 18.7 Making PostGetMixin Generic
        8. 18.8 Fixing NewsLink URL Patterns and Form Behavior
          1. 18.8.1 NewsLink URL patterns
          2. 18.8.2 Automating Startup Selection in NewsLink Forms
        9. 18.9 Putting It All Together
      7. 19. Basic Authentication
        1. 19.1 Introduction
        2. 19.2 Configuring Logging
        3. 19.3 Sessions and Cookies
        4. 19.4 auth App Anatomy: The Basics
        5. 19.5 Adding Login and Logout Features
          1. 19.5.1 User in the Shell
          2. 19.5.2 Creating a User App
          3. 19.5.3 Using Django’s Views to Make Login and Logout Pages
          4. 19.5.4 Post-Authentication Redirection
        6. 19.6 Putting It All Together
      8. 20. Integrating Permissions
        1. 20.1 Introduction
        2. 20.2 Understanding contenttypes and Generic Relations
        3. 20.3 auth App Anatomy: Permission and Group Models
          1. 20.3.1 Permissions in the Shell
          2. 20.3.2 Groups in the Shell
          3. 20.3.3 Object-Level Permissions
        4. 20.4 Protecting Views with Permissions
          1. 20.4.1 Custom Decorators
          2. 20.4.2 Future Posts Mixin
        5. 20.5 Conditionally Displaying Template Links
        6. 20.6 Displaying Future Posts in the Template
        7. 20.7 Putting It All Together
      9. 21. Extending Authentication
        1. 21.1 Introduction
        2. 21.2 auth App Anatomy: Password Views
        3. 21.3 Changing Passwords
        4. 21.4 Resetting Passwords
        5. 21.5 Disabling Accounts
        6. 21.6 Creating Accounts
          1. 21.6.1 Mixins for Sending and Logging Emails
          2. 21.6.2 Creation Form
          3. 21.6.3 Views for Creating and Activating Accounts
          4. 21.6.4 Account Creation Templates
          5. 21.6.5 Resending Activation
        7. 21.7 URL Cleanup
        8. 21.8 Anatomy of the App: Full Dissection
        9. 21.9 Putting It All Together
      10. 22. Overriding Django’s Authentication with a Custom User
        1. 22.1 Introduction
        2. 22.2 Creating a User Profile
          1. 22.2.1 The Profile Model
          2. 22.2.2 Implementing ProfileDetail
          3. 22.2.3 Profile Update
          4. 22.2.4 Public Profile
        3. 22.3 Custom User
          1. 22.3.1 Creating a Custom Manager for User
          2. 22.3.2 Swapping the User Model
          3. 22.3.3 Integrating Forms and Templates
        4. 22.4 Data Migrations
        5. 22.5 Adding an Author to Blog Posts
        6. 22.6 Putting It All Together
      11. 23. The Admin Library
        1. 23.1 Introduction
        2. 23.2 A First Look
        3. 23.3 Modifying the Admin Controls for Blog Posts
          1. 23.3.1 Configuring the List of Post Objects
          2. 23.3.2 Configuring the Add and Edit Pages
          3. 23.3.3 Adding Extra Information to the List View
        4. 23.4 Configuring the Admin for the User Model
          1. 23.4.1 Configuring the List Page
          2. 23.4.2 Configuring the Add and Edit Pages
          3. 23.4.3 Adding a Change Password Page
          4. 23.4.4 Adding Profile to UserAdmin Thanks to Inline Instances
        5. 23.5 Creating Admin Actions
        6. 23.6 Putting It All Together
    11. III: Advanced Core Features
      1. 24. Creating Custom Managers and Querysets
        1. 24.1 Introduction to Part III
        2. 24.2 Introduction to Chapter 24
        3. 24.3 Custom Managers and Querysets
        4. 24.4 Fixtures
        5. 24.5 Management Commands
          1. 24.5.1 The createtag Management Command
          2. 24.5.2 The createuser and createsuperuser Commands
        6. 24.6 Putting It All Together
      2. 25. Handling Behavior with Signals
        1. 25.1 Introduction
        2. 25.2 Apps and AppConfig
        3. 25.3 Signals
          1. 25.3.1 Informing the User of Login/Logout Actions
          2. 25.3.2 Automatically Assigning Tag Objects to Post Instances
        4. 25.4 Putting It All Together
      3. 26. Optimizing Our Site for Speed
        1. 26.1 Introduction
        2. 26.2 Profiling
        3. 26.3 Limiting Database Queries
          1. 26.3.1 Understanding the Problem
          2. 26.3.2 Template Short-Circuiting
          3. 26.3.3 Caching Properties
          4. 26.3.4 Caching Template Variables
          5. 26.3.5 Introspecting Optimization in the Shell
          6. 26.3.6 Using Migrations to Learn about Optimization
          7. 26.3.7 Optimizing Views with Related Content
          8. 26.3.8 Optimizing Manager and QuerySet Classes Directly
          9. 26.3.9 Optimizing Admin Pages
        4. 26.4 Changing Database Behavior Internally
        5. 26.5 Changing Performance Globally
          1. 26.5.1 Caching Template Files
          2. 26.5.2 Caching Entire Webpages
          3. 26.5.3 Development
        6. 26.6 Putting It All Together
      4. 27. Building Custom Template Tags
        1. 27.1 Introduction
        2. 27.2 Custom Template Filters
        3. 27.3 Custom Template Tags
          1. 27.3.1 Displaying Related Posts
          2. 27.3.2 Displaying Create and Update Forms
          3. 27.3.3 Displaying Delete Confirmation Forms
          4. 27.3.4 Listing the Latest Blog Posts
        4. 27.4 Putting It All Together
      5. 28. Adding RSS and Atom Feeds and a Sitemap
        1. 28.1 Introduction
        2. 28.2 RSS and Atom Feeds
        3. 28.3 Sitemaps
          1. 28.3.1 Post Sitemap
          2. 28.3.2 Tag Sitemap
          3. 28.3.3 Startup Sitemap
          4. 28.3.4 Blog Post Archive Sitemap
          5. 28.3.5 Other Pages Sitemap
        4. 28.4 Putting It All Together
      6. 29. Deploy!
        1. 29.1 Introduction: Understanding Modern Deployments
        2. 29.2 Preparing for Deployment
          1. 29.2.1 Creating Error Pages
          2. 29.2.2 Deployment Tools
          3. 29.2.3 Preparing Django Settings
          4. 29.2.4 Running Django’s Development Server
          5. 29.2.5 Running Foreman’s Server
          6. 29.2.6 Checking Our Production Settings
        3. 29.3 Deploying to Heroku
        4. 29.4 Adding Backing Services
          1. 29.4.1 Logging with Papertrail
          2. 29.4.2 Sending Emails with Postmark
          3. 29.4.3 Caching with Memcache
        5. 29.5 Putting It All Together
      7. 30. Starting a New Project Correctly
        1. 30.1 Introduction
        2. 30.2 Preparing a Project
          1. 30.2.1 Project Specification
          2. 30.2.2 Picking Third-Party Apps
          3. 30.2.3 The User Model
        3. 30.3 Building the Project
          1. 30.3.1 Testing
          2. 30.3.2 PostgreSQL
          3. 30.3.3 Starting with Generic Views
          4. 30.3.4 Reconsidering Reverse Methods
          5. 30.3.5 Optimization
          6. 30.3.6 Building REST APIs
        4. 30.4 The Road Ahead
    12. IV: Appendixes
      1. A. HTTP
      2. B. Python Primer
        1. B.1 Decorators
        2. B.2 Multiple Inheritance
      3. C. Relational Database Basics
      4. D. Security Basics
      5. E. Regular Expressions
      6. F. Compilation Basics
      7. G. Installing Python, Django, and Your Tools
        1. G.1 Package Management
        2. G.2 Version Control
        3. G.3 Python
        4. G.4 Virtual Environments
        5. G.5 Django
        6. G.6 Syntax Tools and Testing
    13. Index
    14. Code Snippets

    Product information

    • Title: Django Unleashed
    • Author(s):
    • Release date: November 2015
    • Publisher(s): Sams
    • ISBN: 9780133812497