最全DRF开发手册

Django框架使用指南

基于python3.6 和 django2.1

创建项目和应用

新建一个项目

django-admin startproject back
cd back # 进入到该项目的文件夹
django-admin startapp people # 新建一个 people 应用(app)
urls.py
    网址入口,关联到对应的views.py中的一个函数(或者generic类),访问网址就对应一个函数。

views.py
    处理用户发出的请求,从urls.py中对应过来, 通过Response()将json格式数据返回给前端

models.py
    与数据库操作相关,存入或读取数据时用到这个,当然用不到数据库的时候 你可以不使用。

serializer.py
    用于序列化数据, 验证数据

templates
    放置html模板, drf一般用不到

filter.py
    用于过滤, 有需求时候会用上

admin.py
    后台,可以用很少量的代码就拥有一个强大的后台。

settings.py
    Django 的设置,配置文件,比如 DEBUG 的开关,静态文件的位置等。

django常用命令

  • python manage.py runserver 0.0.0.0:80000 启动服务器
  • python manage.py makemigrations 生成迁移文件
  • python manage.py migrate 迁移数据库
  • python manage.py migrate --fake 迁移数据库遇到冲突
  • python manage.py inspectdb 反向生模型(models)
  • python manage.py collectstatic 收集静态文件
  • python manage.py createsuperuser 创建管理员
  • python manage.py flush 清空数据库

第三方包管理


pip install xxx 可以安装第三方库
安装的第三方库可以导出到一个文件里面

pip freeze > requirements.txt

通过requirements.txt安装第三方包

pip install -r requirments.txt

配置

配置都是在setting.py

数据库

django默认数据库是sqllite, mysql等数据库需要改相应的配置
修改DjangoBlog/setting.py 修改数据库配置,如下所示:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'grocerdb',
        'USER': 'root',
        'PASSWORD': '123456',
        'HOST': '127.0.0.1',
        'PORT': '3306',
        "OPTIONS": {
            'charset': 'utf8mb4',
            "init_command": "SET default_storage_engine=INNODB;"
        },
    }
}

ldap配置

# ### ldap configuration ###
import ldap
from django_auth_ldap.config import LDAPSearch, PosixGroupType

base_dn = ''
AUTH_LDAP_SERVER_URI = ''
AUTH_LDAP_BIND_DN = ''
AUTH_LDAP_BIND_PASSWORD = ''
AUTH_LDAP_USER_SEARCH = LDAPSearch(base_dn, ldap.SCOPE_SUBTREE, "(uid=%(user)s)")
AUTH_LDAP_ALWAYS_UPDATE_USER = True

AUTH_LDAP_USER_ATTR_MAP = {  # key为数据库字段名,value为ldap中字段名,此字典解决django model与ldap字段名可能出现的不一致问题
    "username": "uid",
    "first_name": "givenName",
    "last_name": "sn",
    "email": "mail"
}


AUTHENTICATION_BACKENDS = (
    'django_auth_ldap.backend.LDAPBackend',   # 配置为先使用LDAP认证,如通过认证则不再使用后面的认证方式
    'django.contrib.auth.backends.ModelBackend',
)

邮箱配置

# Email configuration
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = ''
EMAIL_PORT = 25
EMAIL_HOST_USER = ''
EMAIL_HOST_PASSWORD = ''
EMAIL_SUBJECT_PREFIX = '[] '
EMAIL_USE_TLS = False  # 与SMTP服务器通信时,是否启动TLS链接(安全链接)port: EMAIL_PORT
EMAIL_USE_SSL = False  # 与SMTP服务器通信时,是否启动TLS链接(安全链接)port: EMAIL_PORT
SERVER_EMAIL = EMAIL_HOST_USER
DEFAULT_FROM_EMAIL = EMAIL_HOST_USER

开发流程

前端发送请求首先会由back目录下的urls.py分发到各个View, 底层view实现了http的get, post, delete, patch, update, 等方法drf框架对这些方法进行了最基本的实现, 只需要继承相应的mixin就可以, 比如post方法要继承CreateModelMixin, serializer是用来序列化数据, 验证数据的, 下面是一个restful风格的api具体实现:

首先定义一个model:

from django.db import models


class Opid(models.Model):
    eng = models.TextField(blank=True, null=True)
    jpn = models.TextField(blank=True, null=True)

Setting.py 里配置app

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework',
    'opid'
]

迁移数据库

python manage.py makemigrations
python manage.py migrate

View

业务逻辑放在view层

from rest_framework.viewsets import ModelViewSet
from .models import Opid
from .serializer import OpidSerializer


class OpidViewSet(ModelViewSet):
    """
    ModelViewSet 方法继承了全部的http方法
    """
    serializer_class = OpidSerializer
    queryset = Opid.objects.all()

Serializer

serializer主要是用来序列化数据成json, 验证等功能
opid目录下新建serializer.py文件

from rest_framework import serializers
from .models import Opid
  

class OpidSerializer(serializers.ModelSerializer):

    class Meta:
        model = Opid
        fields = '__all__'

urls

opid目录下新建urls.py用于路由分发

from .views import OpidViewSet
from rest_framework.routers import DefaultRouter

router = DefaultRouter()

router.register(r'opid', OpidViewSet, base_name='opid')

根目录的urls文件

from django.contrib import admin
from django.urls import path
from django.conf.urls import url, include
from rest_framework.documentation import include_docs_urls
from rest_framework.routers import DefaultRouter

router = DefaultRouter()

urlpatterns = [
    # 后台地址
    path('admin/', admin.site.urls),
    path('fz/api/v1/opid/', include('opid.urls')),
    # 接口文档地址
    url(r'docs/', include_docs_urls(title="API文档")),
]

前端请求方法对应的url

  • get /opid/ 获取opid列表
  • get /opid/1/ 获取id为1的opid详细
  • post /opid/ 新规一个opid
  • delete /opid/1/ 删除id为1的opid
  • update /opid/1/ 完全更新id为1的opid
  • patch /opid/1 局部更新opid为1的opid

过滤

前端可以这样搜索 /opid/?englishstring=xx&japanese=xx

from .filters import OpidFilter
from django_filters.rest_framework import DjangoFilterBackend


class OpidViewSet(ModelViewSet):
    serializer_class = OpidSerializer
    queryset = Opid.objects.all()
    filter_backends = (DjangoFilterBackend,)
    filter_class = OpidFilter

filters.py

import django_filters
from .models import Opid
from django.db.models import Q


class OpidFilter(django_filters.rest_framework.FilterSet):

    englishstring = django_filters.CharFilter(field_name='eng')
    japanese = django_filters.CharFilter(field_name='jpn')
    japanese_english_opid = django_filters.CharFilter(method='japaneseOrEnglishOrOpidFilter', help_text='英语日语搜索')

    def japaneseOrEnglishOrOpidFilter(self, queryset, name, value):
        return Opid.objects.filter(Q(jpn__contains=value) | Q(eng__contains=value)| Q(opid__contains=value))
    class Meta:
        model = Opid
        fields = ['englishstring', 'japanese', 'product']

分页

前端可能发出这样的请求 opid/?pageNo=1&pageSize=10 pageNo是当前页码, pageSize是一页有多少条数据, drf自带的分页不是这种格式就需要自己重写方法

view
from .filters import OpidFilter
from django_filters.rest_framework import DjangoFilterBackend


class OpidViewSet(ModelViewSet):
    serializer_class = OpidSerializer
    queryset = Opid.objects.all()
    filter_backends = (DjangoFilterBackend,)
    filter_class = OpidFilter
    pagination_class = Pagination
from collections import OrderedDict
from rest_framework.response import Response
from rest_framework.pagination import LimitOffsetPagination


class Pagination(LimitOffsetPagination):
    # 默认每页显示的数据条数
    # default_limit = 20
    # URL中传入的显示数据条数的参数
    limit_query_param = 'pageSize'
    # URL中传入的数据位置的参数
    offset_query_param = 'pageNo'

    def paginate_queryset(self, queryset, request, view=None):
        self.count = self.get_count(queryset)
        self.limit = self.get_limit(request)
        if self.limit is None:
            return queryset
        _offset = self.get_offset(request)
        if _offset == 1:
            self.offset = 0
        elif _offset == 0:
            self.offset = _offset
        else:
            self.offset = (_offset - 1) * self.limit
        self.request = request
        if self.count > self.limit and self.template is not None:
            self.display_page_controls = True

        if self.count == 0 or self.offset > self.count:
            return []
        return list(queryset[self.offset:self.offset + self.limit])

    def get_paginated_response(self, data):
        return Response(OrderedDict([('count', self.count), ('results', data)]))

错误消息通知

Sentry官网
Sentry是一个实时事件的日志聚合平台。它专门监测错误并提取所有有用信息用于分析,不再麻烦地依赖用户反馈来定位问题。

Sentry发展多年,几乎没有同类产品可与其媲美。它能覆盖大部分的主流编程语言与框架,很适合应用到实际生产环境中采集异常日志。

公司可以自己安装服务器,也可以在它官网上注册账号(量大收费)
安装sentry-sdk:

$ pip install --upgrade 'sentry-sdk==0.13.2'

setting.py中配置

import sentry_sdk
from sentry_sdk.integrations.django import DjangoIntegration

sentry_sdk.init(
    dsn="https://<key>@sentry.io/<project>",
    integrations=[DjangoIntegration()]
)

更多功能请看这里

api指南

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,219评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,363评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,933评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,020评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,400评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,640评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,896评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,597评论 0 199
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,327评论 1 244
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,581评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,072评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,399评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,054评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,083评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,849评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,672评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,585评论 2 270

推荐阅读更多精彩内容

  • 上面这两个图片是ORM对象关系映射的关系理解。 django框架 一、简介 web框架 具体介绍django之前,...
    AAA年华阅读 2,293评论 0 2
  • Migrate不生成表 makemigrations 和 migrate ,新加的这两个实体无法生成表。 1, 删...
    7d4b0b51c9d4阅读 830评论 0 0
  • 新手求助,windows版本的python没有termios这个模块是没有。如果想在windows下跑,得装cyg...
    夏天夏星阅读 2,510评论 0 1
  • 还有一天,2018就要来临了,2017也要过去了,总觉得该写些什么,要不心里会不舒服的! 朋友圈...
    我就是陌沫阅读 225评论 2 2
  • @亲爱的家人 这些年出去上很多课,收获很多。今天想和你们聊聊。七年前我是个容易生气的人。但我不敢在外人面前表现生...
    拭去心灵的尘埃阅读 156评论 0 1