Django服务器与App(Android)客户端的简单实现

Django服务器与App(Android)客户端的简单实现

作者是一个技术小白,这也是本人的第一篇文章,虽然网上关于Django和Android结合搭建app的文章很多,但是还是想要根据自己在搭建过程中遇到的问题写一篇学习笔记,同时也供他人借鉴一下。
说明:本示例app为本人实现 的一个很简单的记账软件,不喜勿喷。
附github地址:https://github.com/Kingqibin/PayKeep_Online

Django后台搭建

环境要求:

  1. Ubuntu 16.04 LTS 桌面版/服务器版
  2. Python 3
  3. pip等

代码实现

  1. 安装Django:
pip install django
  1. 创建django项目:
django-admin startproject paykeep # 创建项目
django-admin startapp paykeep_service # 主要的服务内容

startproject命令主要的作用是开启了一个项目的成熟框架,在之后的操作中只需要修改一下里面的参数。
startapp命令主要的功能是创建实现功能的模板。
以下在搭建时主要就是修改paykeep和paykeep_service文件夹下的主要内容。
paykeep的目录文件
paykeep_service下的文件目录结构

  1. 修改paykeep_service下的内容:

(1)修改app.py的内容:

class PaykeepServiceConfig(AppConfig):
    name = 'paykeep_service'   #修改name为你项目的名称

(2)修改model.py的内容:

from django.db import models
# 以下定义自己的类模型,以及相对应的数据段
class Pay(models.Model):
    id = models.IntegerField(null=False, primary_key=True)
    item_spend = models.CharField(null=False, max_length=50)
    money = models.FloatField(null=False)
    year = models.IntegerField(null=False)
    month = models.IntegerField(null=False)
    day = models.IntegerField(null=False)
    isPri = models.BooleanField(null=False)
    data_added = models.DateTimeField(auto_now_add=True)
# 以下的函数的作用是在展示 调试时显示相应的数据内容,可以自行配置
    def __str__(self):
        temp = "id is : " + str(self.id) + "--item is : " + str(self.item_spend)
        return temp

关于更多的类型数据定义可以自行google相关的django API。

(3)修改最重要的view.py的内容:

from django.shortcuts import render
from .models import Pay #!!!
from django.http import HttpResponse#!!!
from django.core.exceptions import ObjectDoesNotExist


def pay(request):
# 解析请求方式:
    if request.method == 'POST':
        item_spend = request.POST.get('item_spend')
        id = request.POST.get('id')
        money = request.POST.get('money')
        year = request.POST.get('year')
        month = request.POST.get('month')
        day = request.POST.get('day')
        isPri = request.POST.get('isPri')
        fun = request.POST.get('fun')
        # 功能解析
        if fun == '1':
            Pay.objects.create(id=id, item_spend=item_spend, money=money, year=year, month=month, day=day, isPri=isPri)
            try:
                t = Pay.objects.get(id=id)
                return HttpResponse("add_ok")
            except ObjectDoesNotExist:
                return HttpResponse("add_error")
        elif fun == '2':
            try:
                temp = Pay.objects.get(id=id)
                temp.delete()
                return HttpResponse("delete_ok")
            except ObjectDoesNotExist:
                return HttpResponse("not_found")
    else:#注意代码对齐
        return HttpResponse("error")

以上为本程序实现所需要的核心代码部分,其中我在使用时的django请求方式好像只能用get和post(因为我在网络方面也是小白,具体的咱也不是太清楚,感兴趣的同学可以详细研究下,看其它地博主好像可以用)。因此使用了一个比较蠢的功能解析(即传fun字段来判断要执行哪一个功能)的方式来实现。
另外在网络响应时使用的是HttpResponse具体的其它功能读者可以自行google API。

  1. 修改paykeep下的内容:

(1)修改setting.py的内容:

···
DEBUG = False
ALLOWED_HOSTS = ['*'] # 可访问的ip
···
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'paykeep_service', # 项目名字
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
#    'django.middleware.csrf.CsrfViewMiddleware', # 注释掉
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

应该只需要做以上的修改就好,具体的可以参考github的源码。

(2)修改重要的urls.py的内容:

from django.contrib import admin
from django.urls import path
from paykeep_service.views import pay

urlpatterns = [
    path('admin/', admin.site.urls),
    path('add_pay/', pay),# !!!!!!!!!!!!!!!!
]

这里的 add_pay/ 为请求方式,pay 为在view.py中定义的方式名,这里一定要对应。如果在view中写了更多的请求功能调用也可以在这里一一列明。

  1. 初始化一下数据库:
    使用manage.py文件
python manage.py migrate
  1. 运行:
python manage.py runserver 0.0.0.0:10000

允许接入的ip地址(0.0.0.0)表示允许所有的ip接入,10000端口表示开放的端口。如果使用的是云服务器,一定要在安全组里面配置一下哟。


目前为止,关于后台的搭建已经基本完成,因为我对于后台的了解也不是太多,所以讲的一些东西可能会不太准确,但是操作基本都是正确的。另外推荐大家在搭建好后台后使用postman进行一下响应的测试,看看传入响应的数据后是否会产生预期的效果,如果没用可能需要改一下代码了。防止在后面搭建完app后再反过头来修改后台,浪费时间。本人在写后台时也是经过了很长时间的调试才达到最后的效果,大家要保持耐心哟~提醒一下,如果模型更改了就要按照第5部重新部署一下数据库文件。


APP的构建(Android)

在这里假设大家对一些基础的android操作都已经很熟悉了,因此只是写一些与网络通信的介绍,其它的可以去github参照下源代码。按照国际惯例先贴代码:

// 添加支出记录:
 private void addPay(final Pay pay,final int n){
 		//开启网络传输线程------这里可以使用rxjava等热门的框架代替,这里从简
        new Thread(new Runnable() {
            @Override
            public void run() {
            	//okhttp 客户端
                OkHttpClient client = new OkHttpClient();
                //请求体----添加你需要上传的字段
                RequestBody requestBody = new FormBody.Builder()
                        .add("id",String.valueOf(pay.getId()))
                        .add("item_spend",pay.getName())
                        .add("money",String.valueOf(pay.getMoney()))
                        .add("year",String.valueOf(pay.getYear()))
                        .add("month",String.valueOf(pay.getMonth()))
                        .add("day",String.valueOf(pay.getDay()))
                        .add("isPri",pay.isPrivate()?"True":"False")
                        .add("fun",String.valueOf(1))
                        .build();
                // 请求构建  添加你自己的ip地址   另外 请求方式 add_pay 要与urls.py中定义的相同
                Request request = new Request.Builder()
                        .url("http://"+ip+"/add_pay/")
                        .post(requestBody)
                        .build();
                try {
                    Response response = client.newCall(request).execute();
                    //请求处理
                    String rd = response.body().string();
                    Log.d(TAG, "get response : "+rd);
                    if (rd.isEmpty()){
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                if (n==1)
                                    Toast.makeText(MainActivity.this,"啊咧咧~下次再上传~",Toast.LENGTH_SHORT).show();
                            }
                        });
                    }else {
                        if (rd.equals("add_ok")){
                            runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    pay.setUploaded(true);
                                    pay.save();
                                    refreshSum();
                                    if (n==1)
                                        Toast.makeText(MainActivity.this,"添加成功",Toast.LENGTH_SHORT).show();
                                }
                            });
                        }else {
                            runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    if(n==1)
                                        Toast.makeText(MainActivity.this,"添加失败",Toast.LENGTH_SHORT).show();
                                }
                            });
                        }
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            if (n==1)
                                Toast.makeText(MainActivity.this,"啊咧咧~下次再上传~",Toast.LENGTH_SHORT).show();
                        }
                    });
                }
            }
        }).start();
    }
	// 删除消费记录 几乎跟上面相同
    private void deletePay(final Pay pay,final int pos){
        new Thread(new Runnable() {
            @Override
            public void run() {
                OkHttpClient client = new OkHttpClient();
                RequestBody requestBody = new FormBody.Builder()
                        .add("id",String.valueOf(pay.getId()))
                        .add("item_spend",pay.getName())
                        .add("money",String.valueOf(pay.getMoney()))
                        .add("year",String.valueOf(pay.getYear()))
                        .add("month",String.valueOf(pay.getMonth()))
                        .add("day",String.valueOf(pay.getDay()))
                        .add("isPri",pay.isPrivate()?"True":"False")
                        .add("fun",String.valueOf(2))
                        .build();
                Request request = new Request.Builder()
                        .url("http://"+ip+"/add_pay/")
                        .post(requestBody)
                        .build();
                try {
                    Response response = client.newCall(request).execute();
                    String rd = response.body().string();
                    Log.d(TAG, "get response : "+rd);
                    if (rd.isEmpty()){
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                Toast.makeText(MainActivity.this,"啊咧咧~电波无法到达~",Toast.LENGTH_SHORT).show();
                            }
                        });
                    }else {
                        if (rd.equals("delete_ok")){
                            runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    pays.remove(pos);
                                    adapter.notifyItemRemoved(pos);
                                    recyclerView.scrollToPosition(pos);
                                    LitePal.delete(Pay.class,pay.getId());
                                    refreshSum();
                                    Toast.makeText(MainActivity.this,"消除成功",Toast.LENGTH_SHORT).show();
                                }
                            });
                        }else {
                            runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    Toast.makeText(MainActivity.this,"消除失败",Toast.LENGTH_SHORT).show();
                                }
                            });
                        }
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            Toast.makeText(MainActivity.this,"啊咧咧~电波无法到达~",Toast.LENGTH_SHORT).show();
                        }
                    });
                }
            }
        }).start();
    }

其它的一些安卓代码,大家有兴趣的话参见github,我在这里就只放核心了,如有问题可在评论区留言。


目前为止项目基本就结束了!因为写文章时离项目完成有一段时间了,所以大家如果觉得我写的有问题,不清楚的地方都可以在评论区留言,我及时修改(只要我看地到-哈哈牛逼地叉会儿腰)

转载请声明出处,谢谢

  • 11
    点赞
  • 57
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值