Django开发准则与最佳实践

最近在网易云课堂学习一门django高级实战教程,本文是学习课时1四、15的一些笔记html

Django开发准则与最佳实践

1、优先使用自定义用户模型

继承BaseUserManagerAbstractBaseUser,指定AUTH_USER_MODEL配置项python

看一下cookiecutter给咱们生成的项目结构下的mydjango/users/models.py
自定义的User继承了AbstractUsergit

class User(AbstractUser):
    # First Name and Last Name do not cover name patterns
    # around the globe.
    name = CharField(_("Name of User"), blank=True, max_length=255)
    def get_absolute_url(self):
        return reverse("users:detail", kwargs={"username": self.username})

AbstractUser里的定义(~/anaconda3/envs/djg22env/lib/python3.7/site-packages/django/contrib/auth/base.py)web

class AbstractUser(AbstractBaseUser, PermissionsMixin):
    """ An abstract base class implementing a fully featured User model with admin-compliant permissions. Username and password are required. Other fields are optional. """
    username_validator = UnicodeUsernameValidator()

    username = models.CharField(
        _('username'),
        max_length=150,
        unique=True,
        help_text=_('Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.'),
        validators=[username_validator],
        error_messages={
            'unique': _("A user with that username already exists."),
        },
    )
    first_name = models.CharField(_('first name'), max_length=30, blank=True)
    last_name = models.CharField(_('last name'), max_length=150, blank=True)
    email = models.EmailField(_('email address'), blank=True)
    is_staff = models.BooleanField(
        _('staff status'),
        default=False,
        help_text=_('Designates whether the user can log into this admin site.'),
    )
    is_active = models.BooleanField(
        _('active'),
        default=True,
        help_text=_(
            'Designates whether this user should be treated as active. '
            'Unselect this instead of deleting accounts.'
        ),
    )
    date_joined = models.DateTimeField(_('date joined'), default=timezone.now)

    objects = UserManager()

    EMAIL_FIELD = 'email'
    USERNAME_FIELD = 'username'
    REQUIRED_FIELDS = ['email']

    class Meta:
        verbose_name = _('user')
        verbose_name_plural = _('users')
        abstract = True

    def clean(self):
        super().clean()
        self.email = self.__class__.objects.normalize_email(self.email)

    def get_full_name(self):
        """ Return the first_name plus the last_name, with a space in between. """
        full_name = '%s %s' % (self.first_name, self.last_name)
        return full_name.strip()

    def get_short_name(self):
        """Return the short name for the user."""
        return self.first_name

    def email_user(self, subject, message, from_email=None, **kwargs):
        """Send an email to this user."""
        send_mail(subject, message, from_email, [self.email], **kwargs)

已经有username ,first_name,last_name,email,is_staff,is_active,date_joined这些字段,因此咱们本身定义User的时候,继承AbstractUser,而后加入另外的字段就好了。再经过config/settings/base.py中的AUTH_USER_MODEL = "users.User"将本身定义的User指定上去
本来默认的User是这个
(~/anaconda3/envs/djg22env/lib/python3.7/site-packages/django/contrib/auth/base.py)数据库

class User(AbstractUser):
    """ Users within the Django authentication system are represented by this model. Username and password are required. Other fields are optional. """
    class Meta(AbstractUser.Meta):
        swappable = 'AUTH_USER_MODEL'

2、使用通用类视图FBV->CBV->CBGV

继承CreateViewUpdateViewListViewDetailViewDeleteView
官方文档-基于类的视图django

基于类的视图

基于类的视图提供另外一种将视图实现为 Python 对象而不是函数的方法。它们不能替代基于函数的视图,但与基于函数的视图相比,它们是有某些不一样和优点的。
与特定的 HTTP 方法(GET, POST, 等等)关联的代码组织能经过单独的方法替代条件分支来解决。
面向对象技术(好比 mixins 多重继承)可用于将代码分解为可重用组件。后端

基于类的视图容许你使用不一样的类实例方法响应不一样 HTTP 请求方法缓存

from django.http import HttpResponse
from django.views import View

class MyView(View):
    def get(self, request):
        # <view logic>
        return HttpResponse('result')

使用基于类的视图处理表单bash

from django.http import HttpResponseRedirect
from django.shortcuts import render
from django.views import View

from .forms import MyForm

class MyFormView(View):
    form_class = MyForm
    initial = {'key': 'value'}
    template_name = 'form_template.html'

    def get(self, request, *args, **kwargs):
        form = self.form_class(initial=self.initial)
        return render(request, self.template_name, {'form': form})

    def post(self, request, *args, **kwargs):
        form = self.form_class(request.POST)
        if form.is_valid():
            # <process form cleaned data>
            return HttpResponseRedirect('/success/')

        return render(request, self.template_name, {'form': form})

基于类的通用视图

具体请参考官方文档
Django 附带一些内置的通用视图,它们生成列表和对象的详情视图极为方便。服务器

模型

# models.py
from django.db import models

class Publisher(models.Model):
    name = models.CharField(max_length=30)
    address = models.CharField(max_length=50)
    city = models.CharField(max_length=60)
    state_province = models.CharField(max_length=30)
    country = models.CharField(max_length=50)
    website = models.URLField()

    class Meta:
        ordering = ["-name"]

    def __str__(self):
        return self.name

class Author(models.Model):
    salutation = models.CharField(max_length=10)
    name = models.CharField(max_length=200)
    email = models.EmailField()
    headshot = models.ImageField(upload_to='author_headshots')

    def __str__(self):
        return self.name

class Book(models.Model):
    title = models.CharField(max_length=100)
    authors = models.ManyToManyField('Author')
    publisher = models.ForeignKey(Publisher, on_delete=models.CASCADE)
    publication_date = models.DateField()

视图

# views.py
from django.views.generic import ListView
from books.models import Publisher

class PublisherList(ListView):
    model = Publisher

URLS

# urls.py
from django.urls import path
from books.views import PublisherList

urlpatterns = [
    path('publishers/', PublisherList.as_view()),
]

这就是咱们须要编写的全部代码。尽管咱们仍然须要编写一个模板。咱们能够给视图添加 template_name 属性来告诉视图使用哪一个模板,但若是没有明确的模板,Django 将从对象名称中推断一个。在这个例子中,推断模板将是 "books/publisher_list.html" —— “books” 部分来自定义模型的 app 名称,而 “publisher” 必须是模型名称的小写。

模板

{% extends "base.html" %}

{% block content %}
    <h2>Publishers</h2>
    <ul>
        {% for publisher in object_list %}
            <li>{{ publisher.name }}</li>
        {% endfor %}
    </ul>
{% endblock %}

3、根据不一样环境分别配置settings

根据不一样的场合(开发、测试、部署)配置不一样的选项

4、对网站各个系统功能进行完整测试

编写测试用例,生成测试覆盖度报告

5、方法论:12factors

参考文档

简介

现在,软件一般会做为一种服务来交付,它们被称为网络应用程序,或软件即服务(SaaS)。12-Factor 为构建以下的 SaaS 应用提供了方法论:

  • 使用标准化流程自动配置,从而使新的开发者花费最少的学习成本加入这个项目。
  • 和操做系统之间尽量的划清界限,在各个系统中提供最大的可移植性。
  • 适合部署在现代的云计算平台,从而在服务器和系统管理方面节省资源。
  • 将开发环境和生产环境的差别降至最低,并使用持续交付实施敏捷开发。
  • 能够在工具、架构和开发流程不发生明显变化的前提下实现扩展。 这套理论适用于任意语言和后端服务(数据库、消息队列、缓存等)开发的应用程序。