Django 开发 Web 应用程序并考虑将其扩展到 android,怎么弄?

2022-08-0118:29:44后端程序开发Comments925 views字数 24696阅读模式

我们的计划:

1] 创建 Django Web 应用程序:我们将在 django Web 应用程序中创建基本的用户配置文件机制。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/26337.html

2] 创建与 Android 通信的 API:我们将创建控制器(Django 视图),它将返回 JSON 响应(将充当 API),我们将在 android 应用程序中捕获它。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/26337.html

3] 开发 Android 网络应用程序:我们将创建将与 Django API 通信的 android 网络应用程序。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/26337.html


注意:- 您必须在线部署您的 Web 应用程序,以便该站点必须是公开可访问的(即它必须可以从其他设备访问)。

现在让我们执行我们的计划:

1] 在 Django 中开发基本的学生档案应用程序:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/26337.html

  • 首先通过在终端中输入以下命令来创建 Django 项目(basic_app):django-admin startproject basic_app
  • 在您的项目中创建新应用 StudentProfile:
   cd basic_app
   django manage.py startapp StudentProfile
   python manage.py createsuperuser 

第一个命令会将终端带入当前项目目录。
第二个命令用于创建 StudentProfile 应用程序。
第三个命令为管理站点创建超级用户(管理员)。此命令要求输入用户名、电子邮件和密码。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/26337.html

  • 我们通过在 StudentProfile 和 User 之间提供一对一的关系来扩展基本的 User auth 模型来存储特定于学生的其他信息:
    #CODE SNIPPET 1
    from django.db import models
    #Create your models here.    
    from django.db import models
    from django.contrib.auth.models import User

    class StudentProfile(models.Model):
        user = models.OneToOneField(User,on_delete=models.CASCADE,primary_key=True)
        student_id = models.CharField(max_length=7,null=False,unique=True,default='')
        profile_pic = models.ImageField(upload_to='profilepic/',null=False,default='')
        mobile_number=models.BigIntegerField(blank=True,default=9999999999)

    def __str__(self):
        return "{}".format(self.student_id)

上面的代码进入 StudentProfile App 中的 models.py。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/26337.html

  • 从代码片段 1 开始,我们正在存储学生的个人资料图片,因此我们必须在设置中定义 MEDIA_URL 和 MEDIA_ROOT 以及提供静态文件的其他一些设置:
#CODE SNIPPET 2
#add this lines in settings.py

STATIC_URL = '/static/'

MEDIA_URL = '/media/'

STATICFILES_DIRS = [os.path.join(BASE_DIR,'assets/static/'),'']

MEDIA_ROOT = os.path.join(BASE_DIR,'assets/')

同样在 settings.py 中的 TEMPLATE dict 的 DIRS 字段中添加路径:['assets/static/',]
还在 INSTALLED_APPS 的 Django Settings.py 中添加“StudentProfile”,这有助于服务器检测项目中的新应用程序:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/26337.html

INSTALLED_APPS=[ ...,
  ...,
  'StudentProfile',]

  • 在项目目录中创建文件夹 assets,在 assets 中创建 2 个文件夹 static 和 profilepic(static 将提供模板、css、js 和 profilepic 将存储学生的个人资料图片)。
  • 创建模型后,我们应该在管理站点中注册模型,以便我们可以从管理站点添加删除编辑模型实例:
#CODE SNIPPET 3
from .models import StudentProfile
from django.contrib import admin

admin.site.register(StudentProfile)

  • 现在我们将定义控制器(Django Views)用于如何呈现登录表单以及如何在成功登录后呈现学生信息(我们正在创建非常基本的表单,因为我们的主要目的是创建将与android通信的api):
#CODE SNIPPET 4
from django.shortcuts import render,HttpResponse,redirect
from django.contrib.auth import logout,login,authenticate
from .models import StudentProfile
from django.core import serializers
from django.contrib.auth.models import User

# Create your views here.
def Login(request):
    if request.method == 'POST':
        user=authenticate(request,username=request.POST.get('username'),password=request.POST.get('password'))
        if user is not None:
            login(request,user)
            return redirect('/display')
        else:
            return HttpResponse("Credentials are Incorrect")
    else:
        return render(request,'html/login.html',{})

def display(request):
    if request.method == 'GET':
        user    = User.objects.filter(pk = request.user.pk)[0]
        profile = StudentProfile.objects.filter(user = request.user.pk)[0]
        return render(request,'html/display.html',{'user':user,'profile':profile})

def Logout(request):
    if request.user.is_authenticated:
        logout(request)
        return redirect('/')
    else:
        return HttpResponse("ERROR:Error Logging Out")

此代码进入 StudentProfile 中的 views.py。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/26337.html

说明:-
1]登录:- 如果请求是 'GET',则此定义检查请求是 'POST' 还是 'GET',然后它将为 Signin.Else 呈现表单,如果请求是 'POST' 则它将使用从表单接收的数据并将尝试对用户进行身份验证。如果凭据正确,则用户已登录,否则将显示错误消息。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/26337.html

2]显示:-一旦用户成功登录,他将被重定向到显示页面,该页面通过呈现html来显示他的信息。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/26337.html

3]注销:-此定义将用户注销。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/26337.html


注意:- 我们只需要更改我们的视图来创建用于与 android 应用程序通信的 API。

  • 现在我们将创建 Urls(路由器),它将我们路由到将为我们呈现页面的不同控制器:
#CODE SNIPPET 5
from django.contrib import admin
from django.urls import path,include
from django.conf import settings
from django.conf.urls.static import static

urlpatterns = [
    path('admin/', admin.site.urls),
    path('',include('StudentProfile.urls')),
]

    urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

此代码必须包含在 basic_app urls.py 文件中。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/26337.html

说明:-
1]urlpatterns 定义用于调用不同控制器的 url,这些控制器要么呈现要么重定向。
2]include用于包含应用程序的所有url。
3]我们正在为 MEDIA_ROOT ('assets/') 添加 urlpatterns URL 将是 MEDIA_URL ('/media/')。这将暴露项目目录中的媒体文件。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/26337.html

#CODE SNIPPET 6
from django.contrib import admin
from django.urls import path,include
from .views import Login,display,Logout

urlpatterns = [
    path('',Login),#Calls Login View(Homepage)
    path('display/',display),#Calls display View(After Successful Login )
    path('logout/',Logout),#Controller for logging out 
]

此代码必须包含在 StudentProfile 的 urls.py 中。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/26337.html

  • 现在我们需要创建将由视图呈现的模板:
<!--CODE SNIPPET 7-->
<!DOCTYPE html>
<html>
    <head>
        <title>LOGIN</title>
    </head>

    <body style="font-family:sans-serif;">
        <form method='POST' action=''>
        {%csrf_token%}
        <input type='text' name='username' placeholder='username'>    
        <input type='password' name='password' placeholder='password'>
        <button>SUBMIT</button>
        </form>

    </body>
</html>

此模板应作为 login.html 存储在 assets/static/html 中文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/26337.html

<!--CODE SNIPPET 8-->
{% load static %}
<!DOCTYPE html>
<html>
    <body>
        <p>username:{{user.username}}</p>
        <p>firstname:{{user.first_name}}</p>
        <p>lastname:{{user.last_name}}</p>
        <p>email:{{user.email}}</p>
        <p>student_ID:{{profile.student_id}}</p>
        <p>mobile number:{{profile.mobile_number}}</p>
        <img src="/media/{{profile.profile_pic}}"  >
        <form action='/logout' method='GET'><button>LOGOUT</button></form>
    </body>
</html>

此模板应作为 display.html 存储在 assets/static/html 中文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/26337.html

现在我们完成了我们的 Web 应用程序

2] 为 Android 应用程序创建 API:-正如在其中一篇注释中所说,创建 API 非常容易。我们将使用与之前为 Web 应用程序创建的控制器相同的控制器,只是我们将进行一些小的更改。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/26337.html

  • 启动名为 api 的新项目:python manage.py startapp api
  • 表单和登录 API:
from django.shortcuts import render,HttpResponse,redirect
from django.contrib.auth import logout,login,authenticate
from StudentProfile.models import StudentProfile
from django.core import serializers
from django.contrib.auth.models import User
from django.middleware.csrf import *

# Create your views here.
def Login(request):
    if request.method == 'POST':
        user=authenticate(request,username=request.POST.get('username'),password=request.POST.get('password'))
        if user is not None:
            login(request,user)
            return redirect('/api/display/')
        else:
            return HttpResponse("ERROR:-Credentials are Incorrect")
    else:
        if request.session.is_empty():
            return render(request,'html/api_login_workThrough.html',{})
        authenticate(request)
        print('-------------------')
        print(request.user)
        return redirect('/api/display/')

def display(request):
    if request.method == 'GET':
        user    = User.objects.filter(pk = request.user.pk)[0]
        profile = StudentProfile.objects.filter(user = request.user.pk)[0]
        return HttpResponse(serializers.serialize('json',[user,profile])) 

def Logout(request):
    if request.user.is_authenticated:
        logout(request)
        return redirect('/')
    else:
        return HttpResponse("ERROR:-Error Logging Out")

这段代码应该放在文件 api/views.py文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/26337.html

解释:-文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/26337.html

1]登录:- 附加了 url '/api' 中有一些小的变化,这是因为现在我们指的是不同的控制器集,我们将使用这些控制器与应用程序进行通信。
如果请求方法是“GET”,那么与我们在 Web 应用程序中的代码相比,代码会有重大变化。这是因为一旦我们登录到应用程序并且我们关闭应用程序而不注销它必须打开配置文件页面对我们来说,而不是一种形式。
我们正在检查 request.session 是否存在,如果存在,那么我们将直接重定向到配置文件页面,如果不存在,那么我们将返回包含 csrf 令牌的表单(什么是 csrf 以及它是如何工作的,我们将在稍后讨论)。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/26337.html

2]显示:-而不是呈现显示页面,我们只是将JSON作为HttpResponse返回给应用程序(即使控制器作为REST API工作)。我们使用django本身提供的序列化器库将django模型序列化为JSON,用于序列化模型。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/26337.html


注意:-当请求方法是“GET”并且没有与请求关联的会话对象时,我们正在渲染名为 api_login_workThrough.html 的页面,这是我想到使用 django 的 csrf 机制与我的 android 一起工作的工作应用程序。可能有更好的方法,但我想出了这个简单的想法。我们将在本文后面详细了解这项工作的工作原理。

  • api_login_workThrough.html 位于 assets/static/html 并包含:-
<form>{%csrf_token%}</form>

  • 现在我们将为 API 创建 URLS(Routers):
from django.contrib import admin
from django.urls import path,include
from django.conf import settings
from django.conf.urls.static import static
from .views import *

urlpatterns = [
    path('login/',Login),
    path('display/',display),
    path('logout/',Logout)
]

此代码由 api/urls.py 包含。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/26337.html

看起来和StudentProfile的urls.py一样,其实是一样的,区别在于basic_app的urls.py。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/26337.html

在 basic_app(主项目应用程序)的 urls.py 中,在末尾添加 url 模式:-文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/26337.html

urlpatterns =[
               ...,
               ...,
               path('api/',include('api')), ]

我们为用户学生资料创建了 API。

现在让我们开始使用 Android

  • Android 应用概览
Django 开发 Web 应用程序并考虑将其扩展到 android,怎么弄?

AsyncRequest:-请求响应处理程序

package com.example.workstation.basic;

import android.annotation.TargetApi;
import android.content.Context;
import android.os.Build;
import android.util.Log;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.CookieStore;
import java.net.HttpCookie;
import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.List;
import java.util.Map;
import javax.net.ssl.HttpsURLConnection;

public class AsyncRequest extends Thread
        /* Thread is used to make the request response cycle asynchronous to help preventing the UI from being Unresponsive*/
{
    final String TAG = AsyncRequest.class.getSimpleName();

    final String domain_name;
    BasicCookieStore store;
    /*Basic Cookie Store is Persistent Cookie Store implementation for Android used to store Cookie */
    String ResponseMsg = new String();  //Response message received from (Django)server
    int  ResponseCode;                  //Response code received from server (Code: (2xx for OK),(3xx for Redirects),(4xx for ClientError),(5xx for InternalSerer Error)
    String ResponseBody = new String(); //It is Data Received from Server(HTTP response or File response or JSON response)
    Map<String,List<String>> ResponseHeader;//Response Header Received from Server

    String Url = new String();             //Url to which to send request and response
    String RequestBody = new String();     //Request Body means Data to be sent to Server
    final String RequestType;              //Type of Request(GET,POST)

    AsyncRequest(String requestType,Context context)
    /* Context is accepted for CookieStore to initialize for the Application*/
    {
        RequestType = requestType;
        store=new BasicCookieStore(context);
        domain_name=context.getResources().getString(R.string.domain_name);
    }

    @TargetApi(Build.VERSION_CODES.N)
    @Override
    public void run()
    {
        try
        {
            URL url = new URL(Url);
            URI uri = new URI(Url);
            HttpURLConnection httpconn = (HttpURLConnection) url.openConnection();
            /*HttpURLConnection is the class which establish the connection between client and server and exchange data
            * using HTTP request response cycle.
            * url.openConnection() establishes the connection between client and server */
            httpconn.setInstanceFollowRedirects(false);
            /*Sets whether HTTP redirects (requests with response code 3xx) should be automatically followed by this HttpURLConnection
             instance*/
            HttpsURLConnection.setFollowRedirects(false);
            /*Sets whether HTTP redirects (requests with response code 3xx) should be automatically followed by this class*/
            httpconn.setRequestMethod(RequestType);//set Types of Request
            String S="";
            for(HttpCookie H:store.get(new URI(domain_name)))
                S+=H+"; ";
            httpconn.setRequestProperty("Cookie",S);
            /*retriving the cookie from cookie store and sending back to the server(session_id,csrf_token,etc)*/
            if(RequestType=="POST")
            {
                DataOutputStream output=new DataOutputStream(httpconn.getOutputStream());
                output.writeBytes(RequestBody);
                output.flush();
                output.close();
            }
            /* if the request is POST  then we send data to the server this using output stream received from connection*/

            boolean redirect = false;

            // normally, 3xx is redirect
            int status = httpconn.getResponseCode();
            if (status != HttpURLConnection.HTTP_OK) {              //if request succeds then skip
                if (status == HttpURLConnection.HTTP_MOVED_TEMP
                        || status == HttpURLConnection.HTTP_MOVED_PERM
                        || status == HttpURLConnection.HTTP_SEE_OTHER)//if response code is 3xx then it is redirect request
                    redirect = true;                                  //set redirect to true
            }

            System.out.println("Response Code ... " + status);

            if(redirect) {
                // when response code 3xx then we receive redirect url in header field called "location"
                String newUrl = httpconn.getHeaderField("Location");

                // get the cookie if need, for login
                List<String> cookiesL =httpconn.getHeaderFields().get("set-cookie");
                Log.i(TAG, "run: "+httpconn.getHeaderFields());
                if(cookiesL != null)
                    for(String x:cookiesL)
                        store.add(new URI(domain_name),HttpCookie.parse(x).get(0));

                // open the new connnection again on url recived from location header
                url = new URL(domain_name+newUrl);
                uri = new URI(domain_name+newUrl);
                Log.i(TAG, "run: "+url);
                httpconn.disconnect();
                httpconn = (HttpURLConnection) url.openConnection();
                httpconn.setInstanceFollowRedirects(false);
                HttpURLConnection.setFollowRedirects(false);
                httpconn.setRequestMethod("GET"); //considered that redirect url will be GET request only
                S="";
                for(HttpCookie H:store.get(new URI(domain_name)))
                    S+=H+"; ";
                httpconn.setRequestProperty("Cookie",S);
                Log.i(TAG, "CookiesSession--: "+S);
                /*same as processed for first request*/

            }

            Log.i(TAG, "run: " + httpconn);

            this.ResponseMsg = httpconn.getResponseMessage(); //retriving  response message from httpconn object
            this.ResponseCode = httpconn.getResponseCode();//response code is retrived
            this.ResponseHeader = httpconn.getHeaderFields(); //getting header fields
            byte[] b = new byte[1024 * 1024]; // reserving the memory for responsebody
            int len;
            len = (new DataInputStream(httpconn.getInputStream())).read(b); //reads complete response body from httpconn object
            Log.i(TAG, "run: "+b.toString());
            this.ResponseBody = new String(b, 0, len); //stores in responsebody
            httpconn.disconnect();
        }
        catch(IOException e)
        {
            Log.e(TAG, "run: ",e );
        }
        catch (URISyntaxException e)
        {
            Log.e(TAG, "run: ",e );
        }

    }

    /*Getters and Setters*/

    void setUrl(String Url)
    {
        this.Url=Url;
    }

    void setRequestBody(String RequestBody)
    {
        this.RequestBody=RequestBody;
    }

    String getResponseMsg()
    {
        return ResponseMsg;
    }

    String getResponseBody()
    {
        return ResponseBody;
    }

    Map<String,List<String>> getResponseHeader()
    {
        return ResponseHeader;
    }
}

BitmapD:-使用url异步加载图片

package com.example.workstation.basic;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Log;

import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

public class BitmapD extends Thread {

    Bitmap B;
    String Url;

    public void setUrl(String Url)
    {
        this.Url=Url;
    } //Url from which to fetch image

    public void run()
    {
        try {
            Log.e("src",Url);
            URL url = new URL(Url); // converts string url to URL object
            HttpURLConnection connection = (HttpURLConnection) url.openConnection(); //establishes connection between client and server
            connection.setDoInput(true);
            connection.connect();//connection is established
            InputStream input = connection.getInputStream();//retriving input stream to retrive image data
            B= BitmapFactory.decodeStream(input);//convert input received to proper image format depending on header
            Log.e("Bitmap","returned");
        } catch (IOException e) {
            e.printStackTrace();
            Log.e("Exception",e.getMessage());
        }
    }

    public Bitmap getBitmap()
    {
        return B;
    }//getter for fetching bitmap
}

BasicCookieStore:-Persistent Cookie 存储实现

可以在以下位置找到实现:cookie 存储的 Gist Repo文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/26337.html

这个 git repo 包含来自我们应用程序的两个类,即。BasicCookieStore 和 SerializableHttpCookie,第二类支持第一类将 httpcookie 对象序列化为字符串并存储在 cookie 存储中。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/26337.html

MainActivity:-提供用户登录的登录页面

package com.example.workstation.basic;

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

import java.net.CookieStore;
import java.net.HttpCookie;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;

public class MainActivity extends AppCompatActivity {

    String domain_name;
    BasicCookieStore store;
    String csrf_token=new String();

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        domain_name=getResources().getString(R.string.domain_name);       //server domain

        store = new BasicCookieStore(this);                             //Creating CookieStore for Application
        AsyncRequest P=new AsyncRequest("GET",this);        //AsyncRequest object to snrd request
        P.setUrl(domain_name+this.getResources().getString(R.string.Login));                                    //url to which to send request
        P.start();                                                              //starting asynchronous process

        try
        {
            P.join();                                                           //procced after process P is completed
        }
        catch (InterruptedException e)
        {
            e.printStackTrace();
        }
        Log.i("FORM:---", "onCreate: "+P.getResponseBody());
        /*remember of csrf work through i told of explaining in android
          once we receive the workthrough file from server we are checking for substring at index 1 to 4 if it is word "form"
          then we are retriving the csrf token from form generated by {%csrf_token%} tag in template and store it in a variable
          In response header there is field called "set-cookie" which contains cookie to be set we retrive the data and store it in this store
         */
        if(P.getResponseBody().substring(1,5).equals("form"))
        {
            csrf_token = P.getResponseBody().substring(61, 61 + 64);
            Log.i("csrf_token:--", "onCreate: "+csrf_token);
            try {
                store.add(new URI(domain_name), HttpCookie.parse(P.getResponseHeader().get("set-cookie").get(0)).get(0));
            } catch (URISyntaxException e) {
                e.printStackTrace();
            }
        }
        /*then we check if it returns error substring if so then something has went wrong and we recreate the activity
        else
        if workthrough form  and also error is not returned then it implies that the user session was saved in cookie store and hence we directly authenticate
        user to the user data preview
         */
        else
        {
            if(P.getResponseBody().substring(0,5).equals("Error"))
            {
                this.recreate();
            }
            else
            {
                Intent dashBoard = new Intent(this,DashBoard.class); //Explicit intent creation
                this.finish();
                dashBoard.putExtra("displayData",P.getResponseBody());//sending response data to new intent i.e dashboard
                Log.i("JSON:::", "onCreate: "+P.getResponseBody());
                store.loadAllCookies();
                Log.i("VC", "SignIN: "+store.getCookies());
                startActivity(dashBoard);//starting the intent(control goes to dashboard activity)
            }

        }

    }

    // create an action bar button
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        return super.onCreateOptionsMenu(menu);
    }

    /* this is function which is triggered when user click on login button*/
    void SignIN(View B) throws MalformedURLException, URISyntaxException, InterruptedException {
        Button b = (Button)B;
        EditText usernameView = (EditText) findViewById(R.id.Email);
        EditText passwordView = (EditText) findViewById(R.id.Password);

        String username = usernameView.getText().toString(); //retriving username from username field
        String password = passwordView.getText().toString(); //retriving password from password field

        if(!username.isEmpty() && !password.isEmpty()) //username and password validations
        {
            b.setClickable(false);
            AsyncRequest P = new AsyncRequest("POST",this); //creating the login request
            P.setUrl(domain_name+this.getResources().getString(R.string.Login));//setting login url
            P.setRequestBody("username="+username+"&password="+password+"&csrfmiddlewaretoken="+csrf_token+"&LOGIN=LOGIN");
            //setting request body it contains(username,password and csrf token which is used for CSRF attack protection by django)
            P.start();//satrting the process
            P.join();//procced after process P is completed
            if(P.getResponseBody().substring(0,5).equals("ERROR"))//if response contains "ERROR" string then recreate activity
            {
                Toast.makeText(this,P.getResponseBody(),Toast.LENGTH_LONG).show();
                usernameView.setText("");
                passwordView.setText("");
                this.recreate();
            }
            else                        //if login is successful then create Dashboard activity
            {
                Intent dashBoard = new Intent(this,DashBoard.class);
                dashBoard.putExtra("displayData",P.getResponseBody());
                store.loadAllCookies();
                this.finish();
                startActivity(dashBoard);
            }

        }

    }

}

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    android:background="@color/colorPrimaryDark">

    <TextView
        android:id="@+id/LOGIN"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_above="@id/Email"
        android:text="LOGIN"
        android:textColor="@color/green_intheme"
        android:layout_centerHorizontal="true"
        android:layout_marginBottom="15dp"
        android:fontFamily="serif-monospace"
        android:textSize="35dp"/>

    <EditText
        android:id="@+id/Email"
        android:layout_width="match_parent"
        android:layout_height="30dp"
        android:inputType="textWebEmailAddress"
        android:layout_centerVertical="true"
        android:layout_above="@id/Password"
        android:background="@color/gray_outlook"
        android:layout_marginBottom="10dp"
        android:hint="Email"/>

    <EditText
        android:id="@+id/Password"
        android:layout_width="match_parent"
        android:layout_height="30dp"
        android:inputType="textWebPassword"
        android:layout_centerVertical="true"
        android:layout_marginBottom="10dp"
        android:background="@color/gray_outlook"
        android:hint="Password"/>

    <Button
        android:id="@+id/SignIN"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Sign IN"
        android:layout_marginTop="10dp"
        android:layout_below="@id/Password"
        android:background="@color/blue_intheme"
        android:layout_centerHorizontal="true"
        android:textSize="20dp"
        android:onClick="SignIN"
        android:clickable="true"/>

</RelativeLayout>

仪表板:-用户个人资料预览

package com.example.workstation.basic;

import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Build;
import android.support.annotation.RequiresApi;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

public class DashBoard extends AppCompatActivity {

    boolean flag=true;
    String domain_name;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_dash_board);

        this.domain_name =this.getResources().getString(R.string.domain_name);

        BitmapD B=new BitmapD();

        Intent DataIntent = getIntent(); //receiving the intent

        JSONArray obj = new JSONArray();
        try {
            obj = new JSONArray(DataIntent.getStringExtra("displayData"));
            //the received response from server was JSON serialized coverting it back to JSON Array
        } catch (JSONException e) {
            e.printStackTrace();
        }
        try {
            Log.i("Json", "SignIN: "+((JSONObject)((JSONObject)obj.get(0)).get("fields")).get("username"));
        } catch (JSONException e) {

            e.printStackTrace();
        }
        //selectiong differnt elements from UI(xml)
        TextView username = (TextView) findViewById(R.id.username);
        TextView firstname = (TextView) findViewById(R.id.firstname);
        TextView lastname = (TextView) findViewById(R.id.lastname);
        TextView email = (TextView) findViewById(R.id.email);
        ImageView I =(ImageView) findViewById(R.id.ProfilePic);

        try
        {
            //setting appropiate value from JSON Array
            username.setText("username : "+((JSONObject)((JSONObject)obj.get(0)).get("fields")).get("username"));
            lastname.setText(""+((JSONObject)((JSONObject)obj.get(0)).get("fields")).get("last_name"));
            firstname.setText(""+((JSONObject)((JSONObject)obj.get(0)).get("fields")).get("first_name"));
            email.setText("Email : "+((JSONObject)((JSONObject)obj.get(0)).get("fields")).get("email"));
            B.setUrl(domain_name+"/media/"+((JSONObject)((JSONObject)obj.get(1)).get("fields")).get("profile_pic"));
            //setting image url to BitmapD object which loads the image on other thread
            B.start();
            B.join();
            Bitmap bm=B.getBitmap();
            I.setImageBitmap(bm);

        } catch (JSONException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.actionbardb, menu);
        return super.onCreateOptionsMenu(menu);
    }

    //triggers on clicking close icon  and finishes activity
    public void Close(MenuItem i)
    {
        this.finish();
    }

    //triggers on clicking logout icon and destroys the current session and finishes activity
    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
    public void LogOut(MenuItem i) throws InterruptedException {
        AsyncRequest P=new AsyncRequest("GET",this);
        P.setUrl(domain_name+this.getResources().getString(R.string.Logout)); //sends logout request
        P.start();
        P.join();
        this.finish();
    }

}

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".DashBoard">

    <LinearLayout
        android:id="@+id/DataLayout"
        android:layout_width="match_parent"
        android:layout_height="fill_parent"
        android:background="@color/colorPrimaryDark"
        android:orientation="vertical">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">

            <android.support.v7.widget.CardView
                xmlns:card_view="http://schemas.android.com/apk/res-auto"
                android:layout_width="160dp"
                android:layout_height="160dp"
                card_view:cardCornerRadius="80dp"
                card_view:cardBackgroundColor="@color/white"
                card_view:cardElevation="20dp">

                <android.support.v7.widget.CardView
                    xmlns:card_view="http://schemas.android.com/apk/res-auto"
                    android:layout_width="150dp"
                    android:layout_height="150dp"
                    android:layout_margin="5dp"
                    card_view:cardCornerRadius="75dp"
                    card_view:cardBackgroundColor="@color/white"
                    card_view:cardElevation="10dp">

                    <ImageView
                        android:id="@+id/ProfilePic"
                        android:layout_width="150dp"
                        android:layout_height="150dp"/>

                </android.support.v7.widget.CardView>
            </android.support.v7.widget.CardView>

            <LinearLayout
                android:layout_width="fill_parent"
                android:layout_height="match_parent"
                android:orientation="vertical">

                <TextView
                    android:id="@+id/firstname"
                    android:layout_width="match_parent"
                    android:layout_height="30sp"
                    android:textSize="25sp"
                    android:fontFamily="serif-monospace"
                    android:textColor="@color/white" />

                <TextView
                    android:layout_width="match_parent"
                    android:layout_margin="1dp"
                    android:layout_height="1dp"
                    android:background="@color/blue"/>

                <TextView
                    android:id="@+id/lastname"
                    android:layout_width="match_parent"
                    android:layout_height="30sp"
                    android:textSize="25sp"
                    android:fontFamily="serif-monospace"
                    android:textColor="@color/white" />

            </LinearLayout>

        </LinearLayout>

        <TextView
            android:layout_width="match_parent"
            android:layout_margin="1dp"
            android:layout_height="1dp"
            android:background="@color/blue"/>

        <TextView
            android:id="@+id/username"
            android:layout_width="match_parent"
            android:layout_height="30sp"
            android:textSize="25sp"
            android:fontFamily="serif-monospace"
            android:textColor="@color/white" />

        <TextView
            android:layout_width="match_parent"
            android:layout_margin="1dp"
            android:layout_height="1dp"
            android:background="@color/blue"/>

        <TextView
            android:id="@+id/email"
            android:layout_width="match_parent"
            android:layout_height="60sp"
            android:textSize="25sp"
            android:fontFamily="serif-monospace"
            android:textColor="@color/white"/>

        <TextView
            android:layout_width="match_parent"
            android:layout_margin="1dp"
            android:layout_height="1dp"
            android:background="@color/blue"/>

    </LinearLayout>

</RelativeLayout>

哦,就是这样。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/26337.html

我们的教程已经完成。我只分享了对理解很重要的代码片段,其余的我都跳过了,因为文章的长度。我正在链接我的 web 应用程序仓库和 android 应用程序仓库:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/26337.html

  1. Web 应用程序仓库
  2. Android 应用程序仓库

链接:https://dev.to/akshaychhajed1998/strapping-django--android-application-e57文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/26337.html

文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/26337.html
  • 本站内容整理自互联网,仅提供信息存储空间服务,以方便学习之用。如对文章、图片、字体等版权有疑问,请在下方留言,管理员看到后,将第一时间进行处理。
  • 转载请务必保留本文链接:https://www.cainiaoxueyuan.com/bc/26337.html

Comment

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定