본문 바로가기
모바일앱 프로젝트

Android + Django 로그인 기능 구현하기 (2) 로그인

by Nicole 2021. 3. 12.

이전 포스팅에서는 간단한 회원가입 페이지를 구현해봤다.

이제는 다시 로그인 페이지로 돌아와서,

회원가입 페이지에서 생성한 id와 pw를 submit하는 경우 다음 activity로 넘어갈 수 있도록 구현해봤다.

 

우선 django 측 코드는 다음과 같이 추가해주었다. 기존의 프로젝트에 더해서 추가해 준 부분만 작성하였다.

혹시라도 전체 코드를 참고하고 싶으신 분이 있다면..

비밀댓글을 작성해주시길 바란다.

 

- views.py

class CheckAccountViewset(viewsets.ModelViewSet):
    queryset = Accounts.objects.all()
    serializer_class = AccountsSerializer

    def create(self, request):
        checkID = post_data['checkID']
        checkPW = post_data['checkPW']

        if Accounts.objects.filter(identify=checkID).exists():
            if Accounts.objects.filter(password=checkPW).exists():
                return Response(status=200)

        return Response(status=400)

위와 같이 새로운 클래스 타입 뷰를 생성해주었다.

해당 부분은 기존에 만든 accounts 모델을 사용하여 안드로이드에서 들어온 id와 pw가 있는지를 조회한다.

ORM 쿼리 작성 방식을 reference에서 참고하도록 한다.

 

위의 코드에서 model_name.objects.filter('field_name' = value)

sql query로 따지면 select data from model_name where field_name is value 와 같은 코드이다.

조건에 해당하는 데이터를 데이터베이스 테이블에서 가져오는 것이다.

 

해당 부분은 별도의 url request가 들어올 때 처리해주려고 한다.

 

그리고 exists 메소드를 사용하여 해당 id와 pw 값을 가지는 row가 존재하는 경우,

http status code 200을 리턴해주고, 그렇지 않은 경우 status code 400을 리턴해준다.

안드로이드에서는 response 값으로 받은 코드에 따라 로그인 다음 페이지로 접근 여부를 결정한다.

 

- urls.py

router = routers.DefaultRouter()
...
router.register(r'check', views.CheckAccountViewset)

localhost:8000/check url로 안드로이드 요청이 들어오도록 구현한다.

 

 

안드로이드 측 코드는 다음과 같다.

우선 MyAPI.java 코드에 check url로 들어가는 Multipart를 따로 정의해준다.

 

- MyAPI.java

@Multipart
    @POST("/check/")
    Call<ResponseBody> post_check(
            @Part("checkID") RequestBody param1,
            @Part("checkPW") RequestBody param2
    );

로그인 페이지에서 위와 같이 id와 pw가 들어간다.

그리고 로그인 activity 코드를 수정해줘야 한다.

 

- MainAcitivity.java

private void checkAccount(String userId, String userPass) {
        //
        RequestBody checkID = RequestBody.create(MediaType.parse("text/plain"), userId);
        RequestBody checkPW = RequestBody.create(MediaType.parse("text/plain"), userPass);

        // Retrofit 객체 생성
        Retrofit.Builder builder3 = new Retrofit.Builder()
                .baseUrl("https://50d050ed24bc.ngrok.io")
                .addConverterFactory(GsonConverterFactory.create());
        Retrofit retrofit3 = builder3.build();

        MyAPI myAPI3 = retrofit3.create(MyAPI.class);

        // post 한다는 request를 보내는 부분.
        Call<ResponseBody> call = myAPI3.post_check(checkID, checkPW);
        // 만약 서버로 부터 response를 받는다면.
        call.enqueue(new Callback<ResponseBody>() {
            @Override
            public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                if(response.isSuccessful()){

                    Log.d(TAG,"계정 확인 완료용!!"+response.toString());
                    Toast.makeText(getApplicationContext(),"계정 확인이용!!!!!",Toast.LENGTH_SHORT).show();

//                     로그인. Main Activity2 를 호출한다. (갤러리와 이미지 처리 버튼이 나오는 부분이다)
//                     text view 내의 값들이 db에 있는 경우
                     Intent intent = new Intent(getApplicationContext(), MainActivity2.class);
                     intent.putExtra("firstKeyName",userId); // Verify된 경우 userId 다음 액티비티로 전달하기
                     startActivity(intent);
                }else {
                    Log.d(TAG,"Post Status Code ㅠㅠ : " + response.code());
                    Toast.makeText(getApplicationContext(),"계정 없어용!!!!!",Toast.LENGTH_SHORT).show();
                    Log.d(TAG,response.errorBody().toString());
                    Log.d(TAG,call.request().body().toString());
                }
            }

            @Override
            public void onFailure(Call<ResponseBody> call, Throwable t) {
                Log.d(TAG,"Fail msg : " + t.getMessage());

            }
        });
    }

로그인 버튼 onClick시 위의 메소드가 호출된다.

EditText 필드 안에 있는 값을 파라미터 값으로 전달 받는다.

계정이 존재하는 경우 intent 객체를 생성하여 다음 activity를 호출하는데, 이 때 intent.putExtra( ) 메소드로 해당 id 파라미터를 다음 activity 로 전달한다.

이는 추후에 해당 계정이 등록한 이미지만 데이터베이스에서 불러오기 위함이다.

 

없는 계정으로 등록을 시도할 시 다음과 같은 alert가 뜨고, 다음 activity로 접근이 불가하다.

 

- SubActivity2.java

glide 라이브러리로 JSON 포맷 데이터를 서버에서 불러와 grid type gallery를 구현하는 SubActivity2.java 코드를 수정해줘야한다.

기존에는 모든 이미지를 띄우는 것으로 구현이 되어있었는데,

이제 특정 id값을 보유한 이미지만 띄울 수 있도록 바꿔주는 것이다.

private void fetchImages(String userId) {

        pDialog.setMessage("Downloading json...");
        pDialog.show();

        JsonArrayRequest req = new JsonArrayRequest(endpoint,
                new Response.Listener<JSONArray>() {
                    @Override
                    public void onResponse(JSONArray response) {
                        Log.d(TAG, "Received JSON from server" + response.toString());
                        pDialog.hide();

                        images.clear();
                        for (int i = 0; i < response.length(); i++) {
                            try {
                                JSONObject object = response.getJSONObject(i);
                                Image image = new Image();
                                // id가 일치하는 경우에만 이미지 add
                                if (object.getString("title").equals(userId)) {
                                    image.setName(object.getString("title"));
                                    image.setImage(object.getString("image"));

                                    images.add(image);
                                }


                            } catch (JSONException e) {
                                Log.e(TAG, "Json parsing error: " + e.getMessage());
                            }
                        }

                        mAdapter.notifyDataSetChanged();
                    }
                }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                Log.e(TAG, "Error: " + error.getMessage());
                pDialog.hide();
            }
        });

        // Adding request to request queue
        AppController.getInstance().addToRequestQueue(req);
    }

파라미터 값으로 해당 activity로 들어온 userId 값을 전달 받는다.

서버에서 받아온 JSON 데이터에서 해당 userId값만 image array list에 추가해준다.

 

참고로 이전 activity에서 전달한 intent 파라미터 값을 받는 방법은 activity의 main 메소드 부분 (onCreate 메소드 부분)에서 보낸 key값으로 받으면 된다.

Intent myIntent = getIntent(); // gets the previously created intent
String userId = myIntent.getStringExtra("firstKeyName");

이로서 1) 간단한 로그인 및 회원가입 기능2) 사용자별 다른 데이터를 불러올 수 있도록 하는 기능이 모두 구현되었다.

짝짝짝!

 

그런데 imageview를 불러올 때 지금 main thread에서 너무 많은 일을 하고 있다는 에러가 가끔 뜬다.

어떨 땐 뜨고 어떨 땐 안 떠서 확실한 이유는 모르겠으나,

테스트 해보니 이미지 사이즈가 너무 클 때 그런 에러가 발생하는 것 같다.

안드로이드 기기에서 이미지 데이터를 보낼 때 미리 resize해서 일괄적인 사이즈로 보내도록 코드를 고쳐봐야겠다.

 

 

 

 

REFERENCE

1. ORM 쿼리

django-orm-cookbook-ko.readthedocs.io/en/latest/select_some_fields.html

 

6. 필요한 열만 골라 조회하려면 어떻게 하나요? — Django ORM Cookbook 2.0 documentation

6. 필요한 열만 골라 조회하려면 어떻게 하나요? auth_user 모델에는 여러 개의 필드가 정의되어 있습니다. 그런데 이 필드가 전부 다 필요하지 않을 때도 있죠. 그럴 때 필요한 열만을 데이터베이

django-orm-cookbook-ko.readthedocs.io

ychae-leah.tistory.com/135

 

[Django] 장고 ORM 정리

더보기 1) ORM(Object-Relational Mapping)이란? 2) 장고 Queryset documentation 3) 관련 객체에 접근하기 4) (__) 던더스코어 필드 조회 장고 shell 열고 import 장고 인터랙티브 콘솔 (interactive console) $..

ychae-leah.tistory.com

 

댓글