Another good book of Django for the beginner

A Wedge of Django
A Wedge of Django: Covers Python 3.8 and Django 3.x
We also get some points from this book…

  • Terminology “Wire in the URL”, meaning to associate the Django view with a web location on the site.
  • Python List: a list consists of comma-separated values wrapped in square brackets
    ['Abc', 2, 'Fine', 3, 4]
  • Python Dictionary: A set of key: value pairs
    {
        'a1': 'Model A',
        'B3': 'Color 1',
        'coffee': 'cafe',
    }
  • <p>{{ my_statement }}</p>
    The curly braces around my_statement mean that it won’t be displayed on the page as-is.
    It’ll be evaluated on the Python side and then the result will be displayed. It can be any of the following:

    • A Python expression, e.g., string, number, or instantiated object
    • A function or method call
  • Create a PostgreSQL database and add the database configuration in config\settings\base.py
    Setting the environment variable: DATABASE_URL environment variable
    DATABASES = {
        # Raises ImproperlyConfigured Exception
        # if DATABASE_URL Not in os.environ
        "default": env.db(
            "DATABASE_URL", default="postgres://db_username:[email protected]:5432/db_name",
        )
    }
  • <p>{{ object.bio|linebreaksbr }}<p>
    The “|” or “pipe” symbol in a template is a “filter”. Filters are used to modify variables in Django Templates.
    The “linebreakbr” filter modifies text to replace every carriage return with the HTML <br> tag in teh page being rendered.
  • assert key, is used when debugging code. It lets you test if a condition in your code
    returns True, if not, the program will raise an AssertionError.
    x = 1
     
    #if condition returns True, then nothing happens:
    assert x == 1
     
    #if condition returns False, AssertionError is raised:
    assert x == 2
  • It is a common practice in the Django world to keep all our Django apps inside one directory.
  • A good rule of thumb is to use TextField rather than CharField whenever there might be a need for more than 255 characters.
  • Don’t Use list_editable.
    As records are tracked not by primary keys but by their position in a displayed list.
  • CBV (Class-based View)
    from django.http import HttpResponse
    from django.views.generic import View
     
    class MyView(View):
     
        def get(self, request, *args, **kwargs):
            return HttpResponse('Response to GET request')
     
        def post(self, request, *args, **kwargs):
            return HttpResponse('Response to POST request')
     
        def delete(self, request, *args, **kwargs):
            return HttpResponse('Response to DELETE request')

    FBV (Function-based View)
    def my_view(request, *args, **kwargs):
        if request.method == 'POST':
            return HttpResponse('Response POST request')
        elif request.method == 'DELETE':
            return HttpResponse('Response DELETE request')
        return HttpResponse('Response GET request')

    or this FBV approach:
    def my_view(request, *args, **kwargs):
        METHOD_DISPATCH = {
          'POST': HttpResponse('Response POST request'),
          'DELETE': HttpResponse('Response DELETE request'),
        }
        DEFAULT = HttpResponse('Response GET request')
        return METHOD_DISPATCH.get(request.method, DEFAULT)
  • HTTP methods used by clients (web browsers) to access application servers (Django).
    GET: Used to read web pages
    POST: Used to submit forms
    DELETE: Used with an API to delete a resource such as a web page
  • In a DetailView’s template, the object is accessible as the lowercased model name.
  • get_FOO_display() is a utility method created automatically for any Django model field.
  • We set blank=True for the optional field. But we don’t set null=True because Django’s convention is to store empty values as the empty string, and to retrieve NULL/empty values as the empty string.
  • To be continued…


Readings:
บล็อกของ phyblas
Qiita (@phyblas)
django-braces’s documentation
Class-based View
What is a REPL?
How to configure your Django project for multiple environments?
Deploy A Django Project
Deploying a Django application in Windows with Apache and mod_wsgi
How to Remove Services in Windows 10
Anaconda + Django + Apache Webserver
How to run Django on Apache using Windows 10, Virtualenv Python and mod_wsgi
Manage your Python Virtual Environment with Conda
Deploying Django on Windows Server 2019 and Apache with MOD_WSGI

Two Scoops of Django 3.x: Best Practices for the Django Web Framework

Just bought this book from feldroy.com.
Two-Scoops-of-Django
GitHub for Two-Scoop-of-Django-3.x

Key Points:

  • Keep It Simple, Stupid
  • Fat Models, Utility Modules, Thin Views, Stupid Templates
  • Follow the PEP8;
    • Use 4 spaces per indentation level.
    • Separate top-level function and class definitions with two blank lines.
    • Method definitions inside a class are separated by a single blank line.
  • Limit of text per line is 79 characters (for private projects, it is relaxed to 99 characters).
  • The imports should be grouped in the following order:
    • Standard library imports
    • Core Django imports
    • Related third-party imports
    • Local application or library-specific imports
  • Using aliases to avoid Python Module collisions
    from django.db.models import CharField as ModelCharField
    from django.forms import CharField as FormCharField
  • Use underscores in URL Pattern Names rather than dashes
    patterns = [
        path(route='add/',
            view=views.add_topping,
            name='toppings:add_topping'),
        ]

    Dashes in actual URLs are fine (e.g. route=‘add-topping/’).
  • Using static/ for the (non-user-generated) static media directory.
  • A Django project is a web application powered by the Django web framework.
    Django apps are small libraries designed to represent a single aspect of a project. A Django project is made up of many Django apps. Some of those apps are internal to the project and will never be reused; others are third-party Django packages.
    INSTALLED_APPS is the list of Django apps used by a given project available in its INSTALLED_APPS setting.
    Third-party Django packages are simply reusable Django apps that have been packaged with the Python packaging tools.
  • Each app should be tightly focused on its task.
    James Bennett: “The art of creating and maintaining a good Django app is that it should follow the truncated Unix philosophy according to Douglas McIlroy: ‘Write programs that do one thing and do it well.’
  • Name the Django Apps
    • Keep to single word names, like flavors, animals, blog, and finances.
    • The app’s name should be a plural version of the app’s main model. There are many good exceptions, blog is the example.
    • Consider naming the app according to the URLs to be appeared. For example, http://www.example.com/weblog/, then consider naming your app weblog rather than blog, posts, or blogposts, even if the main model is Post.
    • Use PEP8-compliant, importable Python package names: short, all-lowercase names without numbers, dashes, periods, spaces, or special characters. Using underscores to separate words, although the use of underscores is discouraged.
  • Try to keep your apps small.
  • Sample Project Layout (any module ending with a slash (‘/’) represents a Python package)
    yourprojname_reporoot #This is the <repository_root>.
    |--config/
    |  |--settings/
    |  |--__init__.py
    |  |--asgi.py
    |  |--urls.py
    |  |--wsgi.py
    |--docs/
    |--yourprojname_project/ #The <django_project_root> of the project.
    |  |--media/ #development only!
    |  |--apps1/
    |  |--apps2/
    |  |--apps3/
    |  |--static/ #Non-user-generated static media assets (CSS, JavaScript, and images).
    |  |--templates/ #Your site-wide Django templates
    |--.gitignore
    |--Makefile
    |--README.md
    |--manage.py
    |--requirements.txt #Current dependencies ($ pip freeze > requirements.txt)
  • When coding in Django, the classic example is the process of creating user objects and related data cross multiple models and apps.
  • Service layer example

    apps1/
    |--api/
    |--models.py
    |--services.py #Service layer location for business logic
    |--selectors.py #Service layer location for queries
    |--tests/
  • Each Django app should be tightly-focused on its own task and possess a simple, easy-to-remember name. If an app seems too complex, it should be broken up into smaller apps.
  • Settings module is loaded when your server starts up.
  • Instead of having one settings.py file, you have settings/ directory containing your settings files.
    (Each settings module should have its own corresponding requirements file.)
    settings/
    |--__init__.py
    |--base.py #Settings common to all instances of the project.
    |--local.py #Settings file when working on the project locally.
    |--staging.py #Staging version for running a semi-private version of the site on a production server.
    |--test.py #Settings for running tests including test runners, in-memory database definitions, and log settings.
    |--production.py #Settings file used by your live production server(s). Sometimes called prod.py.

    To start Python interactive interpreter with Django, using your settings/local.py settings file:
    python manage.py shell --settings=config.settings.local

    To run the local development server with your settings/local.py settings file:
    python manage.py runserver --settings=config.settings.local
  • Never hardcoding file paths in Django settings files.
  • The golden rule of Web application security is to never trust data from untrusted sources.
  • Everything except for passwords and API keys ought to be tracked in version control.
  • If there are 20+ models in a single app, break it down into smaller apps, as it probably means the app is doing too much.
    In practice, no more than five to ten models per app.
  • Simple rules of thumb for knowing which type of inheritance to use and when:
    • If the overlap between models is minimal, there might not be needed for model inheritance.
      Just add the fields to both models.
    • If there is enough overlap between models, the code should be refactored so that
      the common fields are in an abstract base model.
    • Proxy models are an occasionally-useful convenient feature, but they’re very different from
      the other two model inheritance styles.
    • Avoid multi-table inheritance. Instead of multi-table inheritance, use explicit OneToOneFields and ForeignKeys
      between models so you can control when joins are traversed.
  • It’s very common in Django projects to include a created and modified timestamp field on all models.

To be continued…


Further readings:
The Twelve-Factor App
PEP8 — Style Guide for Python Code