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就实现了,当然其中我们可以看到显示的字符有一些问题,这是由于当初向数据库中导入数据是定义的类型的问题,后面我们会加以改正。