Python Django 后台连接数据库并提供API接口给Android客户端

上一篇讲了一下python 中Django 框架模块的一些基本概念,比如安装Django 模块,以及url的一些映射规则,以及Django 的模板语法!
这一篇就主要讲解Django 与后台数据库的一些联系。

首先新建好一个项目app中,若还不知道怎么用Django 命令新建项目和模块的可以先去看下我上一篇文章!讲解python Django 框架的基础使用

整个项目的结构如下图所示:
在这里插入图片描述

其次在models.py 中新建一个类比如:

#活动表
class Activity(models.Model):
    cname = models.CharField(max_length=200)
    ctime = models.CharField(max_length=50)
    address = models.CharField(max_length=200)
    price = models.CharField(max_length=100)
    photo = models.CharField(max_length=200)
    urlLink = models.CharField(max_length=150)

#用户表
class User(models.Model):
    username = models.CharField(max_length=50)
    password = models.CharField(max_length=50)
    email = models.CharField(max_length=100)
    phone = models.CharField(max_length=50)

新建好模型后,需要输入一行命令:python manage.py migrate # 创建表结构,输入之后就会看到一个migrations的文件夹,在这个文件夹中会存储一些你对数据库的一些记录历史,然后如果你之后对models.py 文件做过任何改动之后,只需要再输入一条命令:python manage.py makemigrations app 用来更新数据库中的字段模型等

接下来就需要django 连接后台数据库了:
在settings.py 中将之前默认连接的sqlite3数据库注释掉,换成连接MySQL数据库,代码如下:

# DATABASES = {
#     'default': {
#         'ENGINE': 'django.db.backends.sqlite3',
#         'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
#     }
# }

DATABASES = {
    'default': {
    'ENGINE': 'django.db.backends.mysql',
    'NAME': 'bendibao',
    'USER': 'root',
    'PASSWORD': 'root',
    'HOST': '127.0.0.1',
    'PORT': '3306',
    }
}

然后连接好之后,就需要去测试是否已经连接好了数据库,然后取出里面的数据了,于是我新建了一个testdb.py 文件:然后定义了一个方法,用来将后台数据库中的Activity表中的所有数据全部取出来:

def testdb(request):
    list = Activity.objects.all()

    # list2 = {}

    list3 = []
    i = 1
    for var in list:
        data = {}
        data['id'] = i
        data['cname'] = var.cname
        data['ctime'] = var.ctime
        data['address'] = var.address
        data['price'] = var.price
        data['photo'] = var.photo
        data['urlLink'] = var.urlLink
        #
        # list2['id'] = i
        # list2['data'] = data

        list3.append(data)
        i += 1

    # a = json.dumps(data)
    # b = json.dumps(list2)

    # 将集合或字典转换成json 对象
    c = json.dumps(list3)
    return HttpResponse(c)

然后将该方法映射到一个url地址上:我们在urls.py 里面添加代码:

from django.conf.urls import url
from django.contrib import admin
from app import testdb
from app import views
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^$', views.index),
    url(r'^testdb$', testdb.testdb),
]

这样的话,启动之后,输入相对应的网址就可以取后台数据了,截图如下:
在这里插入图片描述

将后台中的所有数据都获取下来并且转换成json格式的形式,至于json样式的排版的这么好,是因为我在谷歌浏览器上装了一个jsonview 的插件,专门用来排版json格式的数据。

然后取到数据之后,就可以封装提供成一个接口提供给客户端使用了,大家应该知道从Android客户端请求,大部分主要是采用get请求或post请求方式两种,我这里就分别处理用get请求以及post请求然后返回的数据。

首先处理Get请求:

if(request.method == 'GET'):
        print("parseData : " + "get data !")
        #用get方式请求数据
        username = request.GET.get('username' , "")
        password = request.GET.get('password' , "")
        email = request.GET.get('email' , "")
        phone = request.GET.get('phone' , "")

        user = User()
        user.username = username
        user.password = password
        user.email = email
        user.phone = phone

        #保存一条用户数据
        user.save()
        print("cx getData" , "username : " + username +":password : " + password + ":email : " + email + ":phone:" + phone)
        # 作为json 数组返回给客户端
        data = {}
        data['username'] = username
        data['password'] = password
        data['email'] = email
        data['phone'] = phone

        list = {}
        list['data'] = data
        list['state'] = 1
        list['msg'] = "Get 正常"
        response = json.dumps(list)
        return HttpResponse(response)

这里主要是将客户端请求中的url中的参数截取下来,然后分别取出相对应的值,然后封装到一条数据存入本地数据库中,再将这条数据,封装成一个由data,state,msg组成的对象数组,返回给客户端,先看后台数据:

在这里插入图片描述

看下在Android客户端请求的代码:

    //初始化键值对params
    public List<NameAndValue> initNameAndParams(){
        List<NameAndValue> list = new ArrayList<>();
        list.add(new NameAndValue("username" , "cx3"));
        list.add(new NameAndValue("password" , "4343543"));
        list.add(new NameAndValue("email" , "[email protected]"));
        list.add(new NameAndValue("phone" , "13710651984"));
        return list;
    }

   //异步调用Get请求
    public void getData(){
        new Thread(new Runnable() {
            @Override
            public void run() {
                HttpHelper.getInstance().getData(Constancts.TEST_URL , initNameAndParams());
            }
        }).start();
    }

	//用OkHttpClient 发起一个 get请求
	public void getData(String url , List<NameAndValue> params){
        if(params != null && params.size() > 0){
		   // params = encodeParamsJson(params);
            StringBuilder mStringBuilder = new StringBuilder();
            for(NameAndValue mNameValuePair : params){
                mStringBuilder.append("&" + mNameValuePair.getName() + "=" + mNameValuePair.getValue());
            }
            Log.e("cx getData : params : " , mStringBuilder.toString() + ": url : " + url);
            url = url + "?" + mStringBuilder.toString();
            Log.e("cx getData : params : " , ": url : " + url);
        }

        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder()
                .url(url)
                .get()
                .build();
        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {

            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                Log.e("cx: getData" + TAG , response.body().string());
            }
        });
    }

然后再看抓包的请求:
在这里插入图片描述

这里是明文,没有用到AES加密的,所以可以看到这么清晰的数据,下一篇会讲到AES加密的相关知识,读者可以尽情期待哦。


讲完了Http 的Get请求方式,现在再来看看Post请求方式,同样还是先看看Python 的服务端的代码:

 if(request.method == 'POST'):
        print("parseData : " + "post data !")
        # postBody = request.body
        username = request.POST.get('username', "")
        password = request.POST.get('password', "")
        email = request.POST.get('email', "")
        phone = request.POST.get('phone', "")

        user = User()
        user.username = username
        user.password = password
        user.email = email
        user.phone = phone

        #添加保存到数据库
        user.save()
        print("cx postData" , "username : " + user.username +":password : " + user.password + ":email : " + user.email + ":phone:" + user.phone)
        #作为json 数组返回给客户端
        data = {}
        data['username'] = user.username
        data['password'] = user.password
        data['email'] = user.email
        data['phone'] = user.phone

        list = {}
        list['data'] = data
        list['state'] = 1
        list['msg'] = "Post 正常"
        response = json.dumps(list)
        return HttpResponse(response)

AES加解密逻辑的代码我已经注释删除了,会在下一篇专门讲解。现在看下Android 客户端post方式请求的代码:

   //用OkHttpClient 的post请求
   public List<NameAndValue> initNameAndParams(){
        List<NameAndValue> list = new ArrayList<>();
        list.add(new NameAndValue("username" , "cx3"));
        list.add(new NameAndValue("password" , "4343543"));
        list.add(new NameAndValue("email" , "[email protected]"));
        list.add(new NameAndValue("phone" , "13710651984"));
        return list;
    }
    
       public void postData(String url , List<NameAndValue> params){
        OkHttpClient client = new OkHttpClient();
        //进行加密传输params 的value
//        params = encodeParamsJson(params);
        FormBody.Builder formBody = new FormBody.Builder();
        for(NameAndValue nameAndValue : params){
            formBody.add(nameAndValue.getName() , nameAndValue.getValue());
        }
        final Request request = new Request.Builder()
                .url(url)
                .post(formBody.build())
                .build();

        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {

            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                String result = response.body().string();
                Log.e("cx : postData: " , result);
//                JSONObject jsonObject = null;
//                try {
//                    jsonObject = new JSONObject(result);
//                    String res = jsonObject.getString("data");
//                    Log.e("cx" , "a :" + res);
//                    String deCodes = AESUtils.deCode(res ,AESUtils.KEY);
////                    String deCodes = AESUtils.deCode(a, AESUtils.KEY);
//                    Log.e("cx" , "deCodes : "  + deCodes);
//
//                    String a = "npzI+QLvPDSbmIP6xaaZuj4ELpBBHD0w+lK4eoEjosyYt5gvfmRAyxIX/1F1Yx1hWmUZWFP2Buan\n" +
//                            "IrY1h4RmhhBaaV/WPPVbC5fBxQEkwTU=";
//                    Log.e("cx" , "a 1:" + a);
//                    System.out.println("加密result 22:" + a);
//                    String deResult1 = AESUtils.deCode(a , AESUtils.KEY);
//                    Log.e("cx" ,"deResult1:" + deResult1);
//                } catch (JSONException e) {
//                    e.printStackTrace();
//                }

//                Gson gson = new Gson();
//                Type apiType = new TypeToken<List<ModelTestUser>>(){}.getType();
//                List<ModelTestUser> mApiResult = gson.fromJson(result, apiType);
            }
        });

然后再看看Fiddler 抓包的数据:
在这里插入图片描述

然后就可以从客户端中取到post请求所响应的数据了!

上面的测试主要是另外一个user表 ,用来测试get请求,post请求的;然后,我用之前的testdb的url "http://127.0.0.1:8010/testdb"去请求得到的json数据给Android 客户端,然后在客户端中用RecyclerView展现出来:

private Handler mHandler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            if(msg.what == GET_DATA_WHAT){
                List<ModelPlay> list = (List<ModelPlay>) msg.obj;
                data.clear();
                data.addAll(list);
                adapterBenDiPlay.setData(data);
                rvPlay.setLayoutManager(new LinearLayoutManager(ActivityBendiPlay.this));
                rvPlay.setAdapter(adapterBenDiPlay);
            }
        }
    };

private void initData() {
        data = new ArrayList<>();
        adapterBenDiPlay = new AdapterBenDiPlay(ActivityBendiPlay.this , data);

        new Thread(new Runnable() {
            @Override
            public void run() {
                HttpGetHelper.get(Api.bendiHost, new HttpCallbackListener() {
                    @Override
                    public void onSuccess(String result) {
                        if(TextUtils.isEmpty(result)){
                            return;
                        }
                        Gson gson = new Gson();
                        Type apiType = new TypeToken<List<ModelPlay>>(){}.getType();
                        List<ModelPlay> mApiResult = gson.fromJson(result, apiType);
                        Message message = new Message();
                        message.what = GET_DATA_WHAT;
                        message.obj = mApiResult;
                        mHandler.sendMessage(message);
                    }

                    @Override
                    public void onError(Exception e) {

                    }
                });
            }
        }).start();

    }

这里用的是HttpClient做的请求,虽然被谷歌放弃了,但还是可以请求的,只需要在app的build.gradle中加入 
 useLibrary 'org.apache.http.legacy' 就可以使用了
  /**
     * get请求,获取返回字符串内容
     */
    public static void get(String url, HttpCallbackListener httpCallbackListener) {
        HttpGet httpGet = new HttpGet(url);
        execute(url, httpGet, httpCallbackListener);
    }

然后在手机端展现如图所示:由于服务端是在本地搭建的,并没有上传给自己的服务器中,所以在手机上需要连接本机电脑的代理IP地址,才能请求数据成功,并且返回正确的结果!!!

在这里插入图片描述

在这里插入图片描述

ok,写到这里,这篇博客就结束了,总结一下,主要讲了python django 框架连接后台数据库之后,再从数据库中取出数据后,然后处理客户端的get请求,post请求,封装成json数据然后提供接口,返回给Android客户端!!!

发布了22 篇原创文章 · 获赞 15 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/m0_37094131/article/details/84990607