(随意摘抄向)two-scoops-of-django 1.8

two-scoops-of-django 1.8 豆瓣读书

这样也不能算读书笔记(并且未完成)

很久以前就开始看这本书,但是英语渣一直看的磕磕巴巴,但是最坑的是慢慢的发现我只是期望Django作为提供API的后端,对这个大而全的框架并不需要了解这么多……暂时的总结发出来吧,慢慢填坑(完全没有什么参考价值,除了这本书值得一看)

Chapter 0: Introduction

Core Concepts

  • Keep It Simple, Stupid
  • Fat Models, Utility Modules, Thin Views, Stupid Templates
    在MVT架构中,View和Template应该尽可能的简单(Template甚至由前端接管)。大部分后端逻辑应该在Model层,或是在Model和View中间抽象出的层级。
    本书后面几章会详细讲解。
  • Start With Django by Default
  • Be Familiar with Django’s Design Philosophies
  • The Twelve-Factor App

Chapter 1: Coding Style

1.1 The Importance of Making Your Code Readable

  • Avoid abbreviating variable names. 避免有歧义的简写命名
  • Write out your function argument names. 列出方法的参数
  • Document your classes and methods.
  • Comment your code.
  • Refactor repeated lines of code into reusable functions or methods.
  • Keep functions and methods short. A good rule of thumb is that scrolling should not be nec-

essary to read an entire function or method.

1.2 PEP8

作者也对其中某一点提出了反对:虽说愚蠢的一致性是没有脑袋的妖怪,但是在一个某些地方不遵循PEP8的项目中,最好还是保持和之前代码的风格一致。
可以使用如flake8之类工具自动检查项目是否遵循PEP8

1.3 The Word on Imports

  1. 标准库
  2. 第三方库
  3. Django核心库
  4. Django第三方库
  5. 自己写的代码

1.4 Use Explicit Relative Imports

这里给出了三种import方法

  • absolute import 绝对引用
    引用其他App中的代码
  • explicit relative import 显示相对引用
    引用当前App中其他模块的方法
  • implicit relative import 隐式相对引用
    不推荐
Code Import Type Usage
from core.views import FoodMixin absolute import Use when importing from outside the current app
from .models import WaffleCone explicit relative Use when importing from another module in the current app
from models import WaffleCone implicit relative Often used when importing from another module in the current app, but not a good idea

相关文章:《编写高质量代码:改善Python的91个建议》 19 && 20 节

1.6 Django Coding Style

  • 函数或URL pattern name单词间的链接使用下划线而不是连字符。url中使用连字符

1.8 Never Code to the IDE (Or Text Editor)

不要依赖IDE吗(没看懂)

Chapter 2: The Optimal Django Environment Setup

2.1 Use the Same Database Engine Everywhere

在开发和生产环境使用相同的数据库引擎。有如下的好处

  • 方便复制线上数据到本地(方便Debug)
  • 不同的数据库有不同的字段类型和参数

推荐PostgreSQL(然而国内变有没有多少人用)

2.2 Use Pip and Virtualenv

还有个好用的工具 virtualenvwrapper

2.4 Use a Version Control System

2.5 Optional: Identical Environments

Vagrant or Docker

Chapter 3: How to Lay Out Django Projects

3.1 Django’s Default Project Layout

1
2
3
$ django-admin.py startproject mysite
$ cd mysite
$ django-admin.py startapp my_app

Cookiecutter Django

一个看起来很强大的一直在更新的项目模版

django-kevin

和本书配套的方案

django-admin.py startproject --template=https://github.com/imkevinxu/django-kevin/archive/master.zip --extension=py,md,html,json,coveragerc PROJECT_NAME

Chapter 4: Fundamentals of Django App Design

4.1 The Golden Rule of Django App Design

Unix philosophy: Write programs that do one thing and do it well. – 每一个App只专注于一件事

4.2 What to Name Your Django Apps

  • 一个单词
  • 复数形式
  • 尽可能和url保持一致
  • 遵照PEP8

4.3 When in Doubt, Keep Apps Small

4.4 What Modules Belong in an App?

除了标准的模块,本书还提供了一些别的惯用模块命名

behaviors.py : An option for locating model mixins per subsection 6.5.1.
constants.py :A good name for placement of app-level settings.If there are enough of them involved in an app, breaking them out into their own module can add clarity to a project.
decorators.py Where we like to locate our decorators. For more information on decorators, see section 9.3.
db/ Used in many projects for any custom model fields or components.
fields.py is commonly used for form fields, but is sometimes used for model fields when there isn’t enough field code to justify creating a db/ package.
factories.py Where we like to place our test data factories. Described in brief in subsection 22.3.5
helpers.py What we call helper functions. These are where we put code extracted from views (sub-section 16.3.3) and models (section 6.5) to make them lighter. Synonymous with utils.py
managers.py When models.py grows too large, a common remedy is to move any custom model managers to this module.
signals.py While we argue against providing custom signals (see chapter 28), this can be a useful place to put them.
utils.py Synonymous with helpers.py
viewmixins.py View modules and packages can be thinned by moving any view mixins to this module. See section 10.2.

Chapter 5: Settings and Requirements Files

基本原则:

  • 每个环境有自己的配置文件
  • 所有配置文件走版本控制
  • 密码(各种数据库信息、第三方服务的key,SECRET KEY)不走版本控制

对于配置文件,一个常见做法是使用一个不走版本控制的local_settings.py文件。但是这样做有如下坏处:

  • 每台机器都有未追踪的代码
  • 无法在本地复现一个生产环境的bug时,难以判断问题是代码逻辑引起的还是配置文件引起的
  • 由配置文件引起的bug(或者要更改配置文件的格式)难以修复
  • 到处复制的local_settings.py文件不符合 不要重复自己的代码 这一原则

我们可以使用多个互相继承的配置文件来适应本地,测试,生产环境。使用django-environ 这个包来保存数据库地址等信息

当然,不想引入第三方库的话,json,xml,yaml都可以取代env文件

最后,不要对目录进行硬编码→_→

Chapter 6: Model Best Practices

使用以下工具

  • django-model-utils
  • django-extensions

6.1 Basics

6.1.1 单个App不应该有太多的Models,如果超过了20个就应该思考下是不是要拆分App了

6.1.2 Model继承的三种方式

  • No model inheritance

不继承,写多遍

优点是简单明了

缺点是非常多的重复代码,难以维护

1
2
3
class Person(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
  • Abstract base classes

抽象基类继承,子类有基类的所有属性和方法

优点是抽象程度高,不需要引入外键

缺点是基类不能直接拿来用

1
2
3
4
5
6
7
8
9
class CommonInfo(models.Model):
name = models.CharField(max_length=100)
age = models.PositiveIntegerField()

class Meta:
abstract = True

class Student(CommonInfo):
home_group = models.CharField(max_length=5)
  • Multi-table inheritance

多表继承, 子类有一个基类的外键

引入外键带来的查询效率变低

并不推荐

1
2
3
4
5
6
7
class Place(models.Model):
name = models.CharField(max_length=50)
address = models.CharField(max_length=80)

class Restaurant(Place):
serves_hot_dogs = models.BooleanField(default=False)
serves_pizza = models.BooleanField(default=False)
  • Proxy models

为一个类扩展方法(并不知道怎么翻译

不同的数据被映射到一个类的时候用

1
2
3
4
5
6
7
8
9
10
11
12
13
from django.db import models

class Person(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)

class MyPerson(Person):
class Meta:
proxy = True

def do_something(self):
# ...
pass
如何选择类继承
  • 如果只有一两个字段在两个类中相同,可以不使用继承而是直接复制字段
  • 如果相同的字段足够多而且可能同时修改(多处修改维护困难)的话可以使用抽象基类继承
  • 同一个类对应着两套方法时使用Proxy Models
  • 任何时候都要避免多表继承

6.1.4 数据库迁移

6.2 Django 数据库设计

Normalization and Denormalization (数据库的标准化和非标准化)

这是两种设计数据库表的模式,Normalization对应的数据属于干净非冗余型,而Denormalization则允许数据冗余或者同样的数据存储于多处。下面主要列出了Normalization的优点和缺点,

优点:

  1. 数据更新更迅速;
  2. 数据存储空见通常更小;
  3. 在查询时减少了distinct和group by的使用

缺点:

  1. 查询时可能需要设计多个表,增加了join的使用;
  2. 一些并要的值需要在每次查询时计算(比如各种率值)

综合以上的优缺点,Normalization模式比较适合的场合是更新操作比较频繁的应用,即write-heavy。同样的Denormalization则适合于read-heavy。

6.2.1 数据库规范化(满足范式)

6.2.2 Cache Before Denormalizing(先考虑缓存再考虑反序列化)

6.2.3 再遇到瓶颈时在进行反序列化(增加冗余)

6.2.4 何时使用NullBlank

Field Type Setting null=True Setting blank=True
CharField, TextField,SlugField,EmailField,CommaSeparatedInteger-Field,UUIDField 不推荐,Django默认是空字符串 如果期望允许空值,可以使用
FileField, ImageField 不推荐,Django以MEDIA_ROOT配置为默认路径 同上
BooleanField 使用NullBooleanField 不推荐
IntegerField, FloatField, DecimalField, DurationField 可以 可以
DateTimeField, DateField, TimeField 可以 可以
ForeignKey,ManyToManyField,OneToOneField 可以 可以

6.2.6 避免通用外键(Generic Relations)

6.3 _meta API

6.4 Model Managers

Chapter 7: Queries and the Database Layer

7.1 Use get_object_or_404() for Single Objects 然而只能再View里面用

7.2 Be Careful With Queries That Might Throw Exceptions

get()找不到数据的时候

1
2
3
from flavors.models import Flavor 
except Flavor.DoesNotExist
except ObjectDoesNotExist

get()找到多个的时候

1
except Flavor.MultipleObjectsReturned:

7.3 Use Lazy Evaluation to Make Queries Legible ???

7.4 Lean on Advanced Query Tools

1
2
3
4
5
6
7
8
9
10
from django.db.models import F
from models.customers import Customer .

customers = Customer.objects.filter(scoops_ordered__gt=F('store_visits'))

# 可以代替下面的语句
customers = []
for customer in Customer.objects.iterate():
if customer.scoops_ordered > customer.store_visits:
customers.append(customer)

7.5 Don’t Drop Down to Raw SQL Until It’s Necessary

7.6 Add Indexes as Needed

  • The index is used frequently, as in 10-25% of all queries.
  • There is real data, or something that approximates real data, so we can analyze the results of indexing.
  • We can run tests to determine if indexing generates an improvement in results.

7.7 Transactions ???

Chapter 8: Function- and Class-Based Views

8.1 When to Use FBVs or CBVs

8.2 Keep View Logic Out of URLConfs

不要把模版加载等东西写在url配置里面

Chapter 9: Best Practices for Function-Based Views

9.1 Advantages of FBVs

遵循以下规则

  • 使View层代码更少
  • View里面的代码不重复??(Never repeat code in views)
  • 把数据处理逻辑包含于Model层
  • 保持View层精简
  • 抛出标准的403 404 500 HTTP头

装饰器

Chapter 10: Best Practices for Class-Based Views

遵循以上规则

  • 前四条和FBV一样
  • 不要抛出标准403 404 500 HTTP头,如果需要的话使用FBV
  • 保持mixin精简

10.3 Which Django GCBV Should Be Used for What Task?

讲道理在提供API的情况下并不需要这些标准View(时代的眼泪

附录


(随意摘抄向)two-scoops-of-django 1.8
https://blog.kdwycz.com/archives/book-002/
作者
kdwycz
发布于
2017年2月26日
许可协议