Django中REST framework与MongoDB的搭配使用

Django框架下,因其功能强大可为广大使用者提供各种数据库的配套使用方法。由于要学习学长的项目,所以我需要学习MongoDB数据库搭配REST framework的使用,在网上查找了一些资料后发现大部分资料都是关于其自带的sqlite3的,所以在这里分享一下我在网上查找到的一些MongoDB搭配REST framework的使用方法。

添加依赖

python的第三方库非常的强大,可以说是什么都有,只有你想不到的。要在REST framework中使用MongoDB就必须添加以下两个依赖库。

pip install djangorestframework
pip Django-rest-framework-mongoengine 3.3.1

想要具体了解rest_framework_mongoengine的api详见http://umutbozkurt.github.io/django-rest-framework-mongoengine/index.html 

创建项目

然后当然就是开始创建你的项目了。创建项目具体过程我就不啰嗦了。

#创建项目vis23
django-admin.py startproject vis23
#创建APP datas
python manage.py startapp datas

注册APP

在datas的settings中找到INSTALLED_APPS

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
     #添加
    'rest_framework',
    'rest_framework_mongoengine',
    'datas',
]

向MongoDB中导入数据

导入数据的具体过程我也不详细说了,在我的上一篇博客中有写到。这里我导入的是我们项目中17年的数据。

建立一个名为data2mongo的.py文件,具体代码如下:

from pymongo import MongoClient
from vis.settings import DBCONFIG
import csv

class Data1:
    filename = '网吧信息.csv'
    path = 'C:\\Users\\Administrator\\Desktop\\2017\\'
    c_raw1 = 'raw_data1'
    colname = ['siteid', 'title', 'lng', 'lat']
    res = []
    max_len = 100000

    def __init__(self):
        self.files = []
        self.files.append(self.filename)
        self.client = MongoClient(DBCONFIG['HOST'], DBCONFIG['PORT'])
        self.db = self.client.__getattr__(DBCONFIG['NAME'])
        self.dst_raw1 = self.db[self.c_raw1]

    def __del__(self):
        self.client.close()

    @staticmethod
    def convert_fileaffix(fileaffix):
        if len(fileaffix) == 0:
            return ''
        while fileaffix[0] == '.':
            fileaffix = fileaffix[1:]
        if '.' in fileaffix:
            return None
        else:
            return fileaffix

    def data1(self):
        self.dst_raw1.remove({})
        self.res.clear()
        print('正在处理文件:%s' % (self.path + self.filename))
        with open(self.path + self.filename) as infile:
                reader = csv.reader(infile)
                next(reader)
                for row in reader:
                    fileaffix = self.convert_fileaffix(str(row[3]))
                    if fileaffix is None:
                        continue
                    self.res.append({
                        'siteid': str(row[0]),
                        'title': str(row[1]),
                        'lng': str(row[2]),
                        'lat': str(row[3]),
                    })
                    if self.res.__len__() == self.max_len:
                        self.dst_raw1.insert_many(self.res)
                        self.res.clear()
        if self.res.__len__() > 0:
            self.dst_raw1.insert_many(self.res)
            self.res.clear()

class Data2:
    filename = 'hydata_swjl_{}.csv'
    path = 'C:\\Users\\Administrator\\Desktop\\2017\\'
    count = range(0, 2)
    c_raw2 = 'raw_data2'
    colname = ['personid', 'siteid', 'xb', 'customername', 'onlinetime',
               'offlinetime', 'areaid', 'birthday']
    res = []
    max_len = 100000

    def __init__(self):
        self.files = []
        for i in self.count:
            self.files.append(self.filename.format(i))
        self.client = MongoClient(DBCONFIG['HOST'], DBCONFIG['PORT'])
        self.db = self.client.__getattr__(DBCONFIG['NAME'])
        self.dst_raw2 = self.db[self.c_raw2]


    def __del__(self):
        self.client.close()

    @staticmethod
    def convert_fileaffix(fileaffix):
        if len(fileaffix) == 0:
            return ''
        while fileaffix[0] == '.':
            fileaffix = fileaffix[1:]
        if '.' in fileaffix:
            return None
        else:
            return fileaffix

    def data2(self):
        self.dst_raw2.remove({})
        self.res.clear()
        for i in self.count:
            print('正在处理文件:%s' % (self.path + self.filename.format(i)))
            with open(self.path + self.filename.format(i)) as infile:
                reader = csv.reader(infile)
                next(reader)
                for row in reader:
                    fileaffix = self.convert_fileaffix(str(row[3]))
                    if fileaffix is None:
                        continue
                    self.res.append({
                        'personid': str(row[0]),
                        'siteid': str(row[1]),
                        'xb': str(row[2]),
                        'customername': str(row[3]),
                        'onlinetime': str(row[4]),
                        'offlinetime': str(row[5]),
                        'areaid': str(row[6]),
                        'birthday': str(row[7]),
                    })
                    if self.res.__len__() == self.max_len:
                        self.dst_raw2.insert_many(self.res)
                        self.res.clear()
        if self.res.__len__() > 0:
            self.dst_raw2.insert_many(self.res)
            self.res.clear()

这里解释一下代码:其中, from vis.settings import DBCONFIG 中的 DBCONFIG 是我在datas的setting中定义的一个方便连接MongoDB的函数;因为我要导入的一共是三张.csv 的表,分别是 网吧信息.csv,hydata_swjl_0.csv,hydata_swjl_1.csv,其中后两表表内格式一致,所以建立了两个类用于分别导入。

这里需要特别注意的是:为了去掉表头,使用了

reader = csv.reader(infile)    

next(reader)

这两句话,它的作用是在导入表时去掉表头中的文字,但在运行时总是报错,错误信息为:

next(reader)
UnicodeDecodeError: 'gbk' codec can't decode byte 0xb7 in position 112: illegal multibyte sequence

 这是由于读取文件的字符编码问题,在with open()中这样改一下就好了

with open(self.path + self.filename.format(i), 'r', encoding='UTF-8') as infile:

当然data2Mongo只是导入的方法,要运行还得需要一个函数来调用它,handles.py,代码如下:

from data2mongo import Data1
from data2mongo import Data2
import time
if __name__ == '__main__':
    start = time.clock()
    tomongo1 = Data1()
    tomongo1.data1()
    tomongo2 = Data2()
    tomongo2.data2()

到这之后,终于该进入正题了。在此之前我们需要在datas的setting中添加两句话,并且将DATABASES中的类容设置为空

DATABASES = {
    'default': {
        'ENGINE': None,  #设置为空
    }
}
from mongoengine import connect  #连接MongoDB的库
connect('vis')  #连接vis数据库

编写Datas

1.建立模型,使用mongoengine.Document。一般在编写api的时候我们在models中都是这样写的

class Student(models.Model):

但由于我们要使用mongoDB所以我们需要这样改一下class data1(Document):

class data1(Document):

具体代码如下:

from __future__ import unicode_literals
from mongoengine import *
# Create your models here.
connect('vis', host='127.0.0.1', port=27017) #连接数据库
class data1(Document):
    siteid = StringField(max_length=45)
    title = StringField(max_length=45)
    lng = StringField(max_length=45)
    lat = StringField(max_length=45)

    meta = {'collection': 'raw_data1'} #数据库中的集合

    def __unicode__(self):
        return self.name
class data2(Document):
    personid = StringField(primary_key=True)
    siteid = StringField(max_length=45)
    xb = StringField(max_length=45)
    customername = StringField(max_length=45)
    onlinetime = StringField(max_length=45)
    offlinetime = StringField(max_length=45)
    areaid = StringField(max_length=45)
    birthday = StringField(max_length=45)

    meta = {'collection': 'raw_data2'} #数据库中的集合

    def __unicode__(self):
        return self.name 

2.编写序列,对serializer需要稍作变化,使用rest_framework_mongoengine.serializers

from rest_framework_mongoengine import serializers
from . import models
class data1Serializer(serializers.DocumentSerializer):
    class Meta:
        model = models.data1
        fields = '__all__'
class data2Serializer(serializers.DocumentSerializer):
    class Meta:
        model = models.data2
        fields = '__all__'

3.在view中同理

from . import models
from . import serializers
from rest_framework_mongoengine import generics
class data1View(generics.ListCreateAPIView):
    queryset = models.data1.objects.all().order_by('siteid')
    serializer_class = serializers.data1Serializer
class data2View(generics.ListCreateAPIView):
    queryset = models.data2.objects.all().order_by('personid')
    serializer_class = serializers.data2Serializer

4.设置路由

(1)在datas中的urls中定义路由

from django.urls import path
from .views import data1View
from .views import data2View
urlpatterns = [
    path('data1/', data1View.as_view(), name='data1'),
    path('data2/', data2View.as_view(), name='data2')
]

(2)在总路由中添加路由地址

from django.contrib import admin
from django.urls import path, include
urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/', include('datas.urls')),
]

做完这些之后,我们就可以运行了

python manage.py runserver

在浏览器输入http://127.0.0.1:8000/api/data1或data2 我们就能看到:

这样一个基本的api就实现了,当然其中我们可以看到显示的字符有一些问题,这是由于当初向数据库中导入数据是定义的类型的问题,后面我们会加以改正。

猜你喜欢

转载自blog.csdn.net/weixin_41784648/article/details/83578612