Django 初认识。mac使用Django搭建后台服务器并加加实时报道功能。

要注意的是要根据自己的Python 版本选择对应的Django 版本,用于编写代码

前言

多年来来只对象说他每天劳作时犹使翻看某些官方网站的通知,一看就是是十几单网站,每个网站来回切,很是烦恼,于是咨询我出无来于elegant
的解决办法。作为一个程序员,能因此代码解决的永不动手。起初是故Python
写了个简单的脚本,通过爬取这些网站的关照,再经过目录的形式显得下,方便查看。

但是作为一个iOS 开发,考虑做成个App
来查看更为便利,顺带着啊仿照下后端的学识,自己写个API,搭建筑个服务器啥的。经调研打算先打Django
入手。Django 是下 Python 编写的一个开源 Web
框架,可以就此它们来很快增加建筑一个胜似性能的网站。本文先称个家,Let’s do it!

顿时篇稿子介绍如何通过Django框架搭建筑一个后台,实现接口编写、实时报道与推送功能。

1.搭建筑环境

我动用的家伙:
PyCharm
用于编写代码,破解方法以此,如果生请自行检索其他方法破解
Postman
用于测试接口
mysql
服务器数据库操作自选用的凡mysql,不过本文不打算讲数据库的物,可以无装

安装pip

sudo easy_install pip

读书过程遭到参考链接:
廖雪峰Python教程,学习Python的核心采用
菜鸟教程,学习环境的搭建及行使,本文主要内容

安装Django

sudo pip install Django==1.11

倘专注的凡一旦根据自己之Python 版本选择相应之Django 版本,python
版本对许涉及

提议设置好我点提到的工具,还有地方菜鸟教程的始末和本文编写接口功能核心接近,可以直接参考该链接。还有Django是急需事先安装的,我是透过pip3
install django进行设置之,安装详细教程也得参照菜鸟教程上。

安装Django REST framework

sudo pip install djangorestframework

开始

率先新建一个档,打开终端cd到一个目下,执行语句既可创一个Django项目,helloworld表示项目文件称,可由定义

$ cd desktop
$ django-admin.py startproject helloworld

图片 1

文本内容

目录说明:

  • hellowrold:项目容器
  • manage.py:命令行工具,可以于你通过命令行与拖欠Django交互。比如数据库操作
  • hellowrold/init.py: 一个缺损文件,告诉 Python 该目录是一个 Python
    包。不常使用可是要的
  • hellowrold/settings.py: 该 Django 项目的装/配置。经常以
  • hellowrold/urls.py: 该 Django 项目的 URL 声明; 一客由 Django
    驱动之网站”目录”。可以当作是后台api接口
  • hellowrold/wsgi.py: 一个 WSGI 兼容的 Web
    服务器的输入,以便运行而的路。没因此过

2.跑起来

新建一个app

cd这个路,创建一个app,app名为example,表示该档之一个分支

python manage.py startapp example

然后在setting文件的INSTALLED_APPS里添加 ‘example’

图片 2

屏幕快照 2018-01-10 15.48.28.png

创建项目

django-admin startproject apiproject

起先服务器

1.于是pycharm打开该品种,右上角-file-open,此时于pycharm上运行(run)成功。

2.或者以顶峰(teminal) cd
到该helloworld文件路径,通过输入指令来启动服务器,这个路子而小心不要弄错,要确定是manage.py文件的目录

$ cd 路径/hellowrold
$ python manage.py runserver 0.0.0.0:8000  //8000指的是端口号,不说明的情况下为8000,也可以自行修改

诸如此类就启动了服务器,打开浏览器输入127.0.0.1:8000即可见到It
worked!
,说明服务器启动成功。

运行Web 服务

python manage.py runserver

每当浏览器输入 http://127.0.0.1:8000/ ,看到如下的页面提示信息

屏幕快照 2017-12-29 下午3.24.55.png

深受四邻设备也克跻身及本机的服务器

通过pycharm运行启动之服务器,只能于本机上查看相,即当浏览器上输入127.0.0.1:8000,而同等网络下的手机还是电脑都没法儿查看,要为四邻设备也能够进来,必须采用极限(terminal)的点子启动服务器,terminal除了上面的主意外,在pycharm内也来一个Terminal选项,在那边执行命令也可以。

图片 3

屏幕快照 2018-01-10 13.54.17.png

然后还有关键的某些,在列蒙找到setting.py,在里的’ALLOWED_HOSTS =
[]’中上加本机的IP地址,如

ALLOWED_HOSTS = ['127.0.0.1',
                 '192.168.0.1']

本机IP地址在系统偏好设置-网络中看出。

今,只要同本机在同网络下的装置,都好经过浏览器上及我们的服务器被了。

修改语言

settings.py

LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'

改为

# 把英文改为中文
LANGUAGE_CODE = 'zh-hans'

# 把国际时区改为中国时区
TIME_ZONE = 'Asia/Shanghai'

刷新下

屏幕快照 2017-12-29 下午4.30.41.png

品尝写一个接口

打开example目录下views.py文件,填写内容

from django.http import HttpResponse,JsonResponse

def hello(request):
    return HttpResponse('hello world')  //返回普通文本数据
    # return JsonResponse({'data':'response'})  //返回json格式数据

方代码应该好掌握,在推行hello函数的当儿回来一段落内容,其中倘需要回到json格式的始末,需要导入JsonResponse

然后在urls.py中添加

from django.conf.urls import url
from django.contrib import admin

import example.views as views  

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^helloworld/hello', views.hello),
]

import example.views as views 导入example的views文件,以views来命名
url(r’^helloworld/hello’, views.hello)
新建一个接口也hello/hello的API,此时访127.0.0.1:8000/helloworld/hello即可看出返回值

3.开立应用APP

写一个get接口

下一场就是足以把多几只接口进行测试,现在尝试写一个get请求的接口,同样是以view文件里编写接口函数,然后于urls文件被定义接口路径

def get_test(request):
    if request.method == 'GET':
        return HttpResponse('接收到get请求')

    return HttpResponse('error')

urls.py文件

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^helloworld/hello', views.hello),
    url(r'^helloworld/get_test', views.get_test),
]

专注,urls.py中定义好接口路径,可能无会见就见效,如果发现接口无效,可以品尝还打开服务器。

创建

django-admin.py startapp api

写一个post接口

职务或同

def post_test(request):
    if request.method == 'POST':
        title = request.POST.get('title','值为空时')
        return HttpResponse('接收到post请求,接收到值: ' + title)
    return HttpResponse('error')

url(r'^helloworld/post_test', views.post_test),

尚记上面提到的postman工具为,我们在浏览器是无主意测试post接口的,打开postman输入链接和带参,点击send即可发送post请求

图片 4

屏幕快照 2018-01-10 14.57.29.png

如果post不成功,一是csrf错误,请参考该链接,解决办法是于setting.py文件里注释掉
MIDDLEWARE的’django.middleware.csrf.CsrfViewMiddleware’即可

添加App

屏幕快照 2017-12-29 下午4.57.38.png

品写一个聊天室

服务器发矣,接口也会了,现在且学习怎么样充实建筑一个聊天室进行聊天。聊天室的落实自是在欠简书链接中学习的。

在setting的INSTALLED_APPS下添加’channels’。

假使是最先使用pycharm,可能会见并未有库房,如channels等,这样于导入库底小试牛刀会拧,可以于Prederences-Project:helloworld-Project
Interpreter中添加必须的库即可导入。

继之继续以setting中上加

CHANNEL_LAYERS = {
    "default": {
        "BACKEND": "asgiref.inmemory.ChannelLayer",
        'ROUTING': 'helloworld.routing.channel_routing',
    },
}

如此这般即使布置好了通讯的坦途

每当example目录下新建consumers.py文件,内容吗

from channels import Group
import json
from channels import channel_layers

def ws_connect(message):
    print('已连接客户端')
    Group('users').add(message.reply_channel)
    message.reply_channel.send({
        'text': json.dumps({
            'msg': u"你好,很高兴为你服务。",
            'talk': False
        })
    })

def ws_disconnect(message):
    print('与客户端断开连接')
    Group('users').discard(message.reply_channel)

def ws_receive(message):
    print('接收到客户端发来的消息')
    data = json.loads(message['text'])
    message.reply_channel.send({
        'text': json.dumps({
            'msg': u"我正在思考你的问题{%s}" % data["text"],
            'talk': True
        })
    })

这里是channels通讯的老三单函数,连接客户端、断开客户端与接受客户端发送的消息。

继而开一个HTML页面用于测试,在example目录下新建templates文件,在内部继续新建一个example的文本,在里新建一个chat.html,内容如下

图片 5

屏幕快照 2018-01-10 15.59.25.png

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Test Django Channels</title>
</head>
<body>
<div style="text-align: center;margin-top: 50px">
    <input id="message" type="text" style="width: 300px" placeholder="输入消息">
    <button id="send-message" style="width:80px;margin-left:20px;">发送</button>
</div>
<table id="show-message" style="width: 410px;margin: 0 auto;margin-top: 10px">
    <tr>
        <td style="text-align: center; border-bottom:1px dashed #000;"><strong>聊天记录</strong></td>
    </tr>
</table>
</body>
<script src="//code.jquery.com/jquery-3.1.1.min.js"></script>
<script>
    var socket = new WebSocket('ws://' + window.location.host + '/users/');
    if (socket.readyState == WebSocket.OPEN) {
        socket.onopen();
    }
    socket.onmessage = function (message) {
        var data = JSON.parse(message.data);
        updateLog("机器人", data["msg"]);
        $("#message").val("");
        $("#message").focus();
    };
    $("#send-message").click(function () {
        var inputText = $("#message").val();
        if (typeof(inputText) == "undefined" || inputText.length < 1) {
            alert("没有输入信息");
        }
        else {
            var msg = {"text": inputText};
            socket.send(JSON.stringify(msg));
            updateLog("你", inputText);
        }
    });
    function updateLog(name, message) {
        var chat = $("#show-message");
        var ele = "<tr><td>" + name + ": " + message + "</td></tr>"
        chat.append(ele);
    }
</script>
</html>

在views中添加

def chat_page(request):
    return render(request, 'example/chat.html')

在urls中添加

url(r'^helloworld/chat_page', views.chat_page),

此时浏览器打开链接127.0.0.1:8000/helloworld/chat_page即可看出显示页面,尝试输入有值

图片 6

屏幕快照 2018-01-10 16.01.39.png

4.数据库模型

成就聊天室

由此就完成了聊天室的意义,现在解释一下刚刚的操作,我们以setting.py的INSTALLED_APPS中补充加了channels,并且上加了CHANNEL_LAYERS配置通道路径,就是routing.py,routing里导入了consumers.py,我们于consumers里面就是得开展报道的操作了,在views里我们上加了chat_page函数,该函数的作用是回调一个网页供浏览器展示。

每当chat.html里发生只途径,var socket = new WebSocket(‘ws://’ +
window.location.host +
‘/users/’);因为channels是以websocket进行报道的,所以路径头为ws://,后面接的/users/可以改,用于判断处理不同用户连接服务器,比如user1,那么在连续服务器的时段就是会见当consumers.ws_connect函数中赢得到user1。

用户通讯目前的作用只是一个聊天室,且机器人之还原是message.reply_channel.send(),就是本着该通道返回,这样连无克好多总人口报道。记得在ws_connect里的Group(‘users’).add(message.reply_channel)吗,这里代表Group的名为也’users’的组添加了该客户端的大路,可以视于断开连接时ws_disconnect该组进行了针对性承诺通道的去,我们可由此这个力量进行双人通讯或群组通讯,只要根据地方的user1的措施展开匹配即可。

创建model
from django.db import models

class Category(models.Model):
    name = models.CharField(max_length=100)
    url = models.CharField(max_length=200)

class Article(models.Model):
    title = models.CharField(max_length=200)
    date = models.CharField(max_length=50)
    url = models.CharField(max_length=200)
    category = models.ForeignKey(Category)

屏幕快照 2017-12-29 下午4.54.12.png

服务器进行iOS推送

所谓推送,可以是客户端正处于与服务器端的连天过程遭到,服务器通过树立之通讯管道展开信息推送,也堪是像微信那样,即便手机app被手动刷掉了,也克闹一个消息弹窗,这里就是说一下这种推送。

iOS有地方推送和网推送,关于网络推送我前面来摆了,链接以此处,建议优先看一下当下首文章,因为咱们得采取里面的推送证书,获取到关系后还需要处理成pem格式,证书之博与处理得参照马上首文章

搬数据库

一定给创造数量库表

python manage.py makemigrations

python manage.py migrate

证处理

由钥匙串中将推送证书导出来后呢.p12文件,通过极端以那个更换为pem格式,现用该p12文本放到桌面上,假而该.p12文件称吧mycert.p12

$ cd desktop
$ openssl pkcs12 -in mycert.p12 -out MyApnsCert.pem -nodes

兹能够在桌面上取到MyApnsCert.pem文件,将欠公文拖入到example目录下,这样证书处理就形成了

始建 Admin 后台管理员账户

用以登录后台
python manage.py createsuperuser

增长推送函数

还是在views.py上进行

率先需导入一个仓房,如果无就仍自者说之展开添加,以此库房的github地址

from apns2.client import APNsClient
from apns2.payload import Payload

def push_ios(request):

    token_hex = 'device token'
    payload = Payload(alert="Hello World!", sound="default", badge=1)
    topic = 'your bundle identifier'
    client = APNsClient('example/MyApnsCert.pem', use_sandbox=True, use_alternative_port=False)
    client.send_notification(token_hex, payload, topic)
    return HttpResponse('response')

device
token不用自己说了吧,知道网络推送的便掌握怎么抱,这个价值一般是于客户端连接达服务器之后发送给服务器,以供服务器进行推送用,服务器存储这无异于片本文就隐瞒了。

payload里面带的凡内容,以json的格式发送,上面的数值在iOS设备上收取的内容格式为

    aps =     {
        alert = "Hello World!";
        badge = 1;
        sound = default;
    };

topic 为iOS app的bundle id
client创建时注意路径问题,如果路径不对是会报错的,参数use_sandbox指开发模式,该token是生产模式时虽然反成为false

接下来写好接口即可。

url(r'^helloworld/push_ios', views.push_ios),

调用后快即能够看手机接收推送证书了。

在 Admin 后台注册模型
from django.contrib import admin
from .models import Category, Article

admin.site.register(Article)
admin.site.register(Category)

屏幕快照 2017-12-29 下午5.03.31.png

运行开发服务器,访问
http://127.0.0.1:8000/admin/
输入账号密码

屏幕快照 2017-12-29 下午5.04.02.png

结语

正文介绍了什么通过Django框架搭建筑一个后台,并且实现了拉家常功能,支持双人聊天、群聊,以及针对iOS设备的音信推送功能,每一个成效都花了本人无数时日,写就首稿子可以拉我梳理知识点,应该为能够拉到需要的人头。

5.序列器(Serializers)

from .models import Article, Category
from rest_framework import serializers

class ArticleSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Article
        fields = ('title', 'date', 'url', 'category')

class CategorySerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Category
        fields = ('name', 'url')

屏幕快照 2017-12-29 下午5.47.23.png

6.视图(Views)

from .models import Article, Category
from rest_framework import viewsets
from .serializers import ArticleSerializer, CategorySerializer

class ArticleViewSet(viewsets.ModelViewSet):
    queryset = Article.objects.all()
    serializer_class = ArticleSerializer

class CategoryViewSet(viewsets.ModelViewSet):
    queryset = Category.objects.all()
    serializer_class = CategorySerializer

屏幕快照 2017-12-29 下午5.50.49.png

7.URLs

from django.conf.urls import url, include
from rest_framework import routers
from django.contrib import admin
from api import views

router = routers.DefaultRouter()
router.register(r'articles', views.ArticleViewSet)
router.register(r'categorys', views.CategoryViewSet)

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^', include(router.urls)),
    # url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework'))
]

屏幕快照 2017-12-29 下午5.51.22.png

8.测试API

http://127.0.0.1:8000/articles/

屏幕快照 2017-12-29 下午6.01.38.png

这会儿还并未数量,需要向数据库里补充加几长长的数据

屏幕快照 2017-12-29 下午5.52.37.png

此间有个问题输入中文后,后续添加修改会产出编码错误的页面
得在manager.py 添加这段代码就从来不问题了

import sys
reload(sys)
sys.setdefaultencoding('utf-8')

丰富通告

屏幕快照 2017-12-29 下午6.04.19.png

屏幕快照 2017-12-29 下午6.05.21.png

再试一下,YES!鸡冻!

屏幕快照 2017-12-29 下午6.06.24.png

然而此地发现独稍题目,category字段应该只是归类的名字,我们改变下序列器,顺便把id
也添加

class ArticleSerializer(serializers.HyperlinkedModelSerializer):
    category = serializers.ReadOnlyField(source='category.name')
    class Meta:
        model = Article
        fields = ('id', 'title', 'date', 'url', 'category')

class CategorySerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Category
        fields = ('id', 'name', 'url')

再试下

屏幕快照 2017-12-29 下午6.23.41.png

居功至伟告成!三个钟头之名堂,对于新手来说已好爽朗了

后续

手上只是当地服务,而且就生一个API,之后会全盘再多的API,并且配备到阿里云之服务器上,先定下此略带目标吧!生命在于折腾!