반응형

기본적으로, 깃 프로젝트 담겨있는 데이터  => 파일 시스템 상에서의 스냅샷(Snapshot)

 

파일 자체를 저장하기 보다는 실제 프로젝트를 커밋하여 적용할  순간을 중요시 여겨 그 수정 내역 자체를 저장

 

 

<Git 프로젝트 3가지 구성요소 >

 

- Working Directory: 작업할 파일이 있는 디렉토리(내 컴퓨터 작업 공간)

- Staging Area: 커밋(Commit)을 수행할 파일들이 올라가는 영역

- Git Directory: Git 프로젝트의 메타 데이터와 데이터 정보가 저장되는 디렉토리

 

 

 

 

??저장소란??

  저장소(Repo)는 실제 소스코드가 담겨 있으면서 커밋(Commit) 내역 등의 모든 작업 이력이 담겨 있는 공간을 의미합니다. 실제로 프로젝트의 메타 데이터를 포함해 각종 데이터는 .git 폴더에 담기게 됩니다. 실제로 이 폴더를 열어 보면 각종 데이터와 해시 값 등이 담겨 있습니다.

 

  어떠한 파일을 Commit 하게 되면 각 작업들을 분류하기 위해 내부적으로 해당 작업에 대한 해시(Hash) 값을 이용하는 것입니다. 일반적으로 해시 값은 충돌이 발생하지 않기 때문에 정확히 커밋 내역들을 관리할 수 있습니다.

 

 

출처: https://ndb796.tistory.com/187 [안경잡이개발자]
반응형
반응형

Git 이용하는 2가지 방법

  • SourceTree : Git GUI 툴 (접근하기 좋고 현재 상태에 대해 파악하기 좋아 협업에서는 많이 사용되지만,
                                     좀 더 디테일한 명령어를 다룰 수 없기에 좋아하지 않는다 ㅎㅎ)
  • Git Bash

 

기본적인 명령어 

  • 화면 초기화 : Ctrl + L
  • 한 행의 처음과 끝 : Ctrl + A, Ctrl + E
  • 목록 보기 : ls 또는 dir
  • 파일의 내용 보기 : cat
  • 특정 문자를 검색 : grep
  • 디렉터리로 이동 : cd
  • 디렉터리 생성 : mkdir
  • 파일 삭제 : rm
  • 파일 생성 : touch

 

git config (최초 1회 실행)

// git commit에 사용될 username

git config --global user.name "your_name"

 

// git commit에 사용될 email

git config --global user.email "your_email@example.com"

 

// 설정한 내용을 확인할 수 있다.

git config --list

git init 

//현재 디렉토리를 로컬저장소로 설정한다

// 로컬저장소로 설정할 프로젝트 위치로 이동

cd 프로젝트path

 

// 로컬저장소로 설정

// (master) 브랜치로 보이면 성공!

git init

 

// 만약 init을 취소하려면 아래의 명령어를 입력

rm -r .git

 

git status

//로컬 저장소의 현재 상태 보여줌

 

git add

//파일을 준비영역(Staging Area)으로 옮김 (GitHub와 연동하려면 git remote로 원격 저장소와 연결해야 함)

// a.html 파일만 추가

git add a.html

 

// 워킹 디렉터리 내 모든 파일을 추가

git add .

 

// 명령 프롬프트에서 상호작용하면서 추가 (나갈땐 q를 입력)

git add -i

 

// 진행중인 파일일 경우, Staging Area에서 워킹 디렉터리로 옮긴다.

$git rm --cached a.html

$git rm -r --cached .

 

git commit

// 준비영역(Staging Area) 의 파일을 로컬저장소에 저장

// 에디터가 출력되고, 에디터에서 커밋 메시지 입력 후 저장하면 커밋됨

git commit

 

// 간단한 커밋 메시지를 입력후 커밋

git commit -m "커밋 메시지"

 

// Staging Area에 들어간 파일에 대해서만 (워킹 디렉터리는 적용 X)

git commit -a -m "커밋 메시지"

 

 

git log

//로컬 저장소의 커밋 이력을 조회

// 커밋 이력 상세조회
git log 

 

// 커밋 이력중 커밋ID, 타이틀 메시지만 조회

git log --oneline

 

// 모든 브랜치 커밋 이력 조회

git log --oneline --decorate --graph --all

 

// 특정 파일의 변경 커밋 조회

git log -- a.html

 

git remote

//로컬 저장소와 원격 저장소를 연결

// Github 원격저장소와 연결한다.

git remote add origin [자신의 Github 원격저장소 주소]

 

// 연결된 원격저장소 확인한다.

git remote -v

 

git push

//원격 저장소에 저장

// 원격저장소에 저장한다.
git push -u origin master

 

// 에러 - ! [rejected] master -> master (fetch first)

// 이미 변경된 파일이 원격저장소에 있을경우 발생

git pull origin master 

 

// 에러 - ! [rejected] master -> master (non-fast-forward)

git push origin +master

 

 

git branch

//브랜치 생성, 수정, 삭제

//브랜치 보기
$git branch

//브랜치 생성
$git branch [브랜치명]

//브랜치 수정
$git branch -m [브랜치명] [바꿀이름]

//브랜치 삭제
$git branch -d [브랜치명]

 

 

git checkout

//워킹 디렉토리 소스를 특정 커밋이나 특정 브랜치로 변경

//특정 브랜치로 워킹 디렉터리 변경
$git checkout [브랜치명]

//특정 커밋으로 워킹 디렉터리 변경
$git checkout [Commit ID]

 

//특정 파일을 해당 브랜치 또는 커밋 상태로 변경 (원복)
$git checkout [돌아갈 Commit ID] -- [파일 경로]
*충돌 방지를 위해 브랜치명을 확인하고, 파일 추가 및 수정한 뒤 커밋해야 한다.

//브랜치 생성 및 체크아웃을 같이 할 경우
$git checkout -b develop

 

git merge

//다른 두 개의 브랜치 소스 병합

$git checkout master
$git merge develop

*같은 파일의 같은 위치의 내용이 변경된 경우 충돌이 발생한다.
반응형
반응형

1. Views of DRF

모델 기반의 viewset을 작성했었다.

from rest_framework import viewsets
from .models import Post
from .serializer import PostSerializer

class PostViewSet(viewsets.ModelViewSet):
    queryset = Post.objects.all()
    serializer_class = 

ViewSet

-> View(CRUD)를 설계하는 가장 간단한 방법

 

 

2. APIView

         -> 장점 : 자신의 마음대로 코드를 작성할 수 있다.

         -> 단점 : CBV의 장점인 중복되는 코드 제거를 하지 못한다.

         

         -> Response : 클라이언트가 요청한 형태로 콘텐츠를 렌더링 해준다.

         -> Status : Http 에서 제공하는 상태 코드는 숫자이지만, REST 프레임워크에서는 
              문자 형태의 식별자를 제공하여 상태를 좀더 잘 구분할 수 있도록 한다.

 

         -> APIView를 상속해서 view를 설계할 때는 
             status 와 Response를 import 하여 Response과정을 작성

         -> APIView를 상속해서 만든 CBV의 내부 함수들은 필요로 하는  HTTP Method 이름으로 갖는다.

         -> 어떠한 status를 받고 response를 전달할지 직접 정하는 것이 apiview를 상속받은 cbv

class SnippetDetail(APIView):
    def get(...):
        ...

    def put(...):
        ...

    def delete(...):
        ...
        
#SnippetDetail 클래스에 필요한 method는 GET, PUT, DELETE

##실습해보기

  • django-admin startproject <project-name>
  • cd <project-name>
  • python manage.py startapp <app-name>
  • settings.py에 App, rest_framework추가
  • models.py에 모델 작성 및 migrate
class Post(models.Model):
    title = models.CharField(max_length=100)
    body = models.TextField()
  • serializer.py 생성 및 작성
from .models import Post
from rest_framework import serializers


class PostSerializer(serializers.ModelSerializer):
    class Meta:
        model = Post
        fields = "__all__"
  • views.py 작성
    1) 필요한 모듈 추가(apiview를 상속받은 cbv를 작성하기 위해 아래 모듈 추가)
from CBV.models import Post
from CBV.serializer import PostSerializer
from django.http import Http404
from rest_framework.response import Response
from rest_framework import status
from rest_framework.views import APIView

           2)객체들 목록 가져오는 PostList 작성

             - post 메서드는 다수의 post 객체를 반환하는 메서드 

             - 다수의 객체를 직렬화 하기위해서는 PostSerializer 에 many = True를 넘겨야 한다

            - post 메서드는 새로운 객세 생성하는 함수

           - 저장 성공시 상태코드 201(created) / 반환 실패시 400(bad request)반환  

class PostList(APIView):
    def get(self, request):
        posts = Post.objects.all()
        serializer = PostSerializer(posts, many=True)

        return Response(serializer.data)

    def post(self, request):
        serializer = PostSerializer(data=request.data)

        if serializer.is_valid():
            serializer.save()

            return Response(serializer.data, status=status.HTTP_201_CREATED)

        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

          3) 객체의 상세 정보를 받는 PostDetail 작성

              - 각각의 함수에 pk 값을 인자로 받는다

              - get_object 함수 : get_object_or_404 함수와 동일한 기능을 한다

              - PostList 에서 작성한 함수들과 비슷한 방식으로 작동

class PostDetail(APIView):
    def get_object(self, pk):
        try:
            return Post.objects.get(pk=pk)
        except Post.DoesNotExist:
            return Http404

    def get(self, request, pk, format=None):
        post = self.get_object(pk)
        serializer = PostSerializer(post)

        return Response(serializer.data)

    def put(self, request, pk, format=None):
        post = self.get_object(pk)
        serializer = PostSerializer(post, data=request.data)

        if serializer.is_valid():
            serializer.save()

            return Response(serializer.data)

        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    def delete(self, request, pk, format=None):
        post = self.get_object(pk)
        post.delete()

        return Response(status=status.HTTP_204_NO_CONTENT)
  • urls.py 작성하기
    1) App 내부의 urls.py 
        - rest_framework.urlpatterns 의 format_suffix_patterns 모듈 추가 
        - views.py 가져와 <ClassName>.as_view() 형식으로 작성
from django.urls import path, include
from rest_framework.urlpatterns import format_suffix_patterns
from . import views

urlpatterns = [
    path("post", views.PostList.as_view()),
    path("post/<int:pk>", views.PostDetail.as_view()),
]

urlpatterns = format_suffix_patterns(urlpatterns)

       2) 프로젝트 폴더의 urls.py 
           - include 를 사용해 앱의 urls.py 를 가져와 PATH 설정

from django.contrib import admin
from django.urls import path, include
import CBV.urls

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

실행하면 -> http://127.0.0.1:8000/post 로 젒고하면 결과가 잘 보인다.

 


3. Mixins

  • APIView를 상속해 CBV 구현시 문제점
    • 여러가지 모델 사용 시 비슷한 논리 코드 반복
      -> 불필요한 반복을 제거하기 위해 mixins 사용 
      -> 상속을 통해 불필요한 반복을 제거 

##실습해보기

1. views.py 작성하기 전

  • django-admin startproject <project-name>
  • cd <project-name>
  • python manage.py startapp <app-name>
  • settings.py에 App, rest_framework추가
  • models.py에 모델 작성 및 migrate

2. views.py 작성

   1) 필요한 모듈 추가하기 

from .models import Post
from serializer import PostSerializer
from rest_framework import generics
from rest_framework import mixins

  2) PostList 클래스 작성

  • apiview를 상속해 작성한 PostList 클래스와 동일한 기능
  • mixins 의 ListModelMixin 과 CreateModelMixin , generics의 GenericAPIView 상속
  • 사용할 모델의 쿼리셋과 Serializer 클래스 등록
  • 객체 목록을 가져오는 GET 메서드는 ListModelMixin 에 구현된 list 함수 사용
  • 객체 생성하는 POST 메서드는 CreateModelMixin 에 구현된 create 함수 사용
class PostList(mixins.ListModelMixin,
               mixins.CreateModelMixin,
               generics.GenericAPIView):
    queryset = Post.objects.all()
    serializer_class = PostSerializer

    def get(self, request, *args, **kwargs):
        return self.list(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        return self.create(request, *args, **kwargs)

   3) PostDetail 클래스 작성하기  

  • PostList를 작성한 것과 동일하게 작성
  • 각 메서드에 필요한 mixins 모듈 상속하고 , serializer, 쿼리셋 등록 후 각 HTTP Method 함수 작성
class PostDetail(mixins.RetrieveModelMixin,
                 mixins.UpdateModelMixin,
                 mixins.DestroyModelMixin,
                 generics.GenericAPIView):
    queryset = Post.objects.all()
    serializer_class = PostSerializer

    def get(self, request, *args, **kwargs):
        return self.retrieve(request, *args, **kwargs)

    def put(self, request, *args, **kwargs):
        return self.update(request, *args, **kwargs)

    def delete(self, request, *args, **kwargs):
        return self.destroy(request, *args, **kwargs)

3. urls.py 작성

- 앱 내부에 urls.py 생성 및 작성

from django.urls import path
from rest_framework.urlpatterns import format_suffix_patterns
from . import views

urlpatterns = [
    path("post", views.PostList.as_view()),
    path("post/<int:pk>", views.PostDetail.as_view()),
]

urlpatterns = format_suffix_patterns(urlpatterns)

- 프로젝트 폴더 내부의 urls.py 에 include 

from django.contrib import admin
from django.urls import path, include
import post.urls

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

실행하고 http://127.0.0.1:8000/post 에 접속하면 정상 작동한다

 

4. Generic CBV

<분류>

  • 기반 뷰(Base View): 뷰 클래스를 생성하고 다른, 제너릭 뷰의 부모 클래스가 되는 기본 제너릭 뷰
    • view : 최상위 부모 제너릭 뷰 클래스
    • TemplateView : 주어진 템플릿으로 렌더링
    • RedirectView : 주어진 URL로 리다이렉트
  • 제너릭 보기 뷰(Generic Display View): 객체의 목록 또는 하나의 객체 상세 정보를 보여주는 뷰
    • DetailView : 조건에 맞는 하나의 객체 출력
    • ListView : 조건에 맞는 객체 목록 출력
  • 제너릭 수정 뷰(Generic Edit View): 폼을 통해 객체를 생성, 수정, 삭제하는 기능을 제공하는 뷰
    • FormView : 폼이 주어지면 해당 폼 출력
    • CreateView : 객체 생성하는 폼 출력
    • UpdateView : 기존 객체 수정하는 폼 출력
    • DeleteView : 기존 객체 삭제하는 폼 출력
  • 제너릭 날짜 뷰(Generic Date View): 날짜 기반 객체의 연/월/일 페이지로 구분해 보여주는 뷰
    • YearArchiveView : 주어진 연도에 해당하는 객체 출력
    • MonthArchiveView : 주어진 월에 해당하는 객체 출력
    • DayArchiveView : 주어진 날짜에 해당하는 객체 출력
    • TodayArchiveVIew : 오늘 날짜에 해당하는 객체 출력
    • DateDetailView : 주어진 연, 월, 일 PK(OR 슬러그)에 해당하는 객체 출력

<제너릭 뷰 오버라이딩>

  • 속성 변수 오버라이딩
    • model : 기본 뷰(View, Template, RedirectView) 3개를 제외하고 모든 제너릭 뷰에서 사용한다.
    • queryset : 기본 뷰(View, Template, RedirectView) 3개를 제외하고 모든 제너릭 뷰에서 사용한다. queryset을 사용하면 model 속성은 무시된다.
    • template_name : TemplateView를 포함한 모든 제너릭 뷰에서 사용한다. 템플릿 파일명을 문자열로 지정한다.
    • context_object_name : 뷰에서 템플릿 파일에 전달하는 컨텍스트 변수명을 지정한다.
    • paginate_by  : ListView와 날짜 기반 뷰(예, YearArchiveView)에서 사용한다. 페이징 기능이 활성화 된 경우 페이지당 출력 항목 수를 정수로 지정한다.
    • date_field : 날짜 기반 뷰(예, YearArchiveView)에서 사용한다. 이 필드의 타입은 DateField 또는 DateTimeField이다.
    • form_class : FormView, CreateView, UpdateView에서 폼을 만드는데 사용할 클래스를 지정한다.
    • success_url : FormView, CreateView, UpdateView, DeleteView에서 폼에 대한 처리가 성공한 후 리디이렉트할 URL 주소이다.
  • 메소드 오버라이딩
    • def get_queryset() : 기본 뷰(View, Template, RedirectView) 3개를 제외하고 모든 제너릭 뷰에서 사용한다. 디폴트는 queryset 속성을 반환한다. queryset 속성이 지정되지 않은 경우 모델 매니저 클래스의 all() 메소드를 호출해 QuerySet 객체를 생성해 반환한다.
    • def get_context_data(**kwargs) : 뷰에서 템플릿 파일에 넘겨주는 컨텍스트 데이터를 추가하거나 변경하는 목적으로 오버라이딩한다.
    • def form_valid(form)

<모델을 지정하는 방법 3가지>

  1. model 속성 변수 지정
  2. queryset 속성 변수 지정
  3. def get_queryset() 메소드 오버라이딩

##실습

1. views.py 작성하기 전

  1. django-admin startproject <project-name>
  2. cd <project-name>
  3. python manage.py startapp <app-name>
  4. settings.py에 App, rest_framework추가
  5. models.py에 모델 작성 및 migrate
  6. serializer.py생성 및 작성

2. views.py 작성하기

   1) 필요한 모듈 추가하기

       - 사용할 모델, serializer , rest_framework 의 generics 추가

from .models import Post
from .serializer import PostSerializer
from rest_framework import generics

    2) PostList 클래스 작성하기

     -  generics의 ListCreateAPIView 는 mixins에서 사용한 list 함수와 create 함수를 가지고 있는 class 이다.

class PostList(generics.ListCreateAPIView):
    queryset = Post.objects.all()
    serializer_class = PostSerializer

    3) PostDetail 클래스 작성하기

     - genercis의 RetrieveUpdateDestoryAPIView 또한 mixins에서 사용한 함수들과 동일한 기능

class PostDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Post.objects.all()
    serializer_class = PostSerializer

3. urls.py 작성하기

- 앱 내부에 urls.py 생성 및 작성

from django.urls import path
from rest_framework.urlpatterns import format_suffix_patterns
from . import views

urlpatterns = [
    path("post", views.PostList.as_view()),
    path("post/<int:pk>", views.PostDetail.as_view()),
]

urlpatterns = format_suffix_patterns(urlpatterns)

- 프로젝트 폴더 내부의 urls.py 에 include 

from django.contrib import admin
from django.urls import path, include
import post.urls

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

-> 실행 결과 : http://127.0.0.1:8000/post로 접속하면 잘 작동하는 것을 확인할 수 있다.

 

5. ViewSet

rest_framework의 viewsets.py내부에는 4개의 클래스가 존재한다.

  • ViewSet
  • GenericViewSet
  • ReadOnlyModelViewSet
  • ModelViewSet

모두 간단하게 구성되어 mixins와 GenricViewSet, APIView등을 묶는 역할을 한다.

 

ReadOnlyModelViewSet

- 상속 받은 클래스

  • mixins.RetrieveModelMixin
  • mixins.ListModelMixin
  • GenericViewSet

상속받은 클래스로 보아 해당 viewset 역할은 retrieve 함수와 list 함수 기능을 가지고 있다

- 기능 : 특정 객체 가져오는 역할(retrieve)  / 객체 목록을 가져오는 역할(list)

 

ReadOnly를 수행하는 viewSet 이다

 

아래와 같이 작성하면

기존 postlist, postDetail 클래스의 기능을 따로 작성하지 않아도 ReadOnlyModelViewSet을 상속받아 사용할 수 있다.

from rest_framework import viewsets
from .models import Post
from .serializer import PostSerializer

class PostViewSet(viewsets.ReadOnlyModelViewSet):
    queryset = Post.objects.all()
    serializer_class = 

ModelViewSet

모델과 Serializer 을 사용할 건지 등록한다

permission_classes는 action을 수행할 수 있는 권한을 설정하는 변수

  • IsAuthenticatedOrReadOnly : 권한이 없을 경우 ReadOnly
  • IsOwnerOrReadOnly : 소유자가 아닐 경우 ReadOnly
from rest_framework import viewsets
from rest_framework.decorators import action
from rest_framework.response import Response

class SnippetViewSet(viewsets.ModelViewSet):
    queryset = Snippet.objects.all()
    serializer_class = SnippetSerializer
    permission_classes = [
        permission.IsAuthenticatedOrReadOnly,
        IsOwnerOrReadOnly,
    ]

    @action(detail=True, renderer_classes=[renderers.StaticHTMLRenderer])
    def highlight(self, request, *args, **kwargs):
        snippet = self.get_object()
        return Response(snippet.highlighted)

    def perform_create(self, serializer):
        serializer.save(owner=self.request.user)

-> customAPI 함수는 default로 GET 메서드로 처리된다. / 다른 메서드로 처리하고 싶다면 action의 format 인자로 지정 가능

 

%action decorator

@는 decorator장식자라고 부른다.
ViewSet을 이용하면 CRUD는 간단하게 구현되나 다른 논리들을 구현할 때
@action를 사용한다. 개발자가 임의로 View를 설계할 수 있도록 해준다.

 

%renderer_classes

Response를 어떤 형식으로 Rendering시킬 것인가를 정의

  • renderer.JSONRenderer
  • renderer.BrowsableAPIRenderer
  • renderer.StaticHTMLRenderer
  • TemplateHTMLRenderer

등 여러가지가 있다. 기본 설정은 JSONRenderer와 BrowsableAPIRenderer다.

 

##실습해보기

viewSet 적용하기

1. views.py 작성하기 전

  • django-admin startproject <project-name>
  • cd <project-name>
  • python manage.py startapp <app-name>
  • settings.py에 App, rest_framework추가
  • models.py에 모델 작성 및 migrate
  • serializer.py생성 및 작성

2. views.py 작성하기

    1) 필요한 모듈 추가

from .models import Post
from .serializer import PostSerializer
from rest_framework import viewsets
from rest_framework import renderers
from rest_framework.decorators import action
from django.http import HttpResponse

    2) ReadOnlyModelViewSet을 상속해 클래스 작성하기

      - viewsets의 ReadOnlyModelViewSet을 상속받아 작성한다. ReadOnlyModelViewSet을 상속받았으므로 읽기만 가능하다.

class PostViewSet(viewsets.ReadOnlyModelViewSet):
    queryset = Post.objects.all()
    serializer_class = PostSerializer

3. urls.py 작성하기

- post 앱 내부의 urls.py

from rest_framework.routers import DefaultRouter
from django.urls import include, path
from .views import PostViewSet

router = DefaultRouter()
router.register('', PostViewSet)

urlpatterns = [
    path('post', include(router.urls))
]

- 프로젝트 폴더의 urls.py 

from django.contrib import admin
from django.urls import path, include
import post.urls

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

>>실행결과 

-http://127.0.0.1:8000/로 접속하면 아래와 같은 결과를 확인할 수 있다.
DefaultRouter를 사용했기 때문에 PATH가 ""일때도 화면이 나온다.

 

-http://127.0.0.1:8000/post로 접속하면 사용가능한 HTTP Method가
ReadOnlyModelViewSet을 상속받았으므로 GET밖에 없다.

 

4. ModelViewSet 상속해 클래스 작성하기

viewsets의 ModelViewset 상속받은 PostViewSet 클래스 작성

사용할 모델과 serializer을 등록하는 것은 기존과 동일

추가적으로 @action 데코레이터를 이용해 custom api 작성

get 방식으로 @action Custom API Test를 띄우는 highlight 함수 작성

 

class PostViewSet(viewsets.ModelViewSet):
    queryset = Post.objects.all()
    serializer_class = PostSerializer

    @action(detail=True, renderer_classes=[renderers.StaticHTMLRenderer])
    def highlight(self, request, *args, **kwargs):
        return HttpResponse("@action Custom API Test")

post로 처리하고 싶다면 @action(method=['post']) 와 같이 작성

 

>>실행결과

http://127.0.0.1:8000/post로 접속하면 사용가능한 HTTP Method가 GET외에도 POST가 추가된 것을 확인

 

Custom API 테스트

>http://127.0.0.1:8000/post/2/와 같이 Detail페이지로 접속하면 Extra Actions 스크롤 메뉴가 생긴 것을 확인할 수 있다.

스크롤 메뉴에서 highlight 버튼 클릭 시 아래와 같은 결과가 생성된다

6. Router

viewSet 복습

- ReadOnlyModelViewSet

  • retrieve()와 list()의 기능

- ModelViewSet

  • list(), create(), retrieve(), update()
    partial_update(), destroy()의 기능

path 

viewSet을 하나의 path 함수로 처리할 수 있을까?

하나의 path로 ListView, DetailView 의 CRUD가 모두 처리 가능할까??

 

===> 불가능하다 / PATH를 하나로 묶어줄 방법이 필요하다

 

as_view

as_view({'http_method' : '처리할 함수'})

예시

path = PostViewSet.as_view({
    'get': 'retrieve',
    'put': 'update',
    'patch': 'partial_update',
    'delete': 'destroy'
})

urlpatterns = [
    path('', path)
]

router : 관례적인 url 맵핑 단계를 자동으로 구현해주는 방식

 

<사용 방법>

1. rest_framework의 router에서 DefaultRouter 추가

from rest_framework.router import DefaultRouter

2. DefaultRouter 객체 생성 및 등록

-> URL Prefix : 127.0.0.1:8000/post와 같은 URL에서 post부분

router = DefaultRouter()
router.register(<URL Prefix>, <View Logic>)

3.  urlpatterns에 router의 urls 추가

urlpatterns = [
    path('', include(router.urls)),
]
반응형

'Web > Django' 카테고리의 다른 글

[Django_심화]4 - (1)pagination  (0) 2020.03.18
[Django] Instagram 클론 코딩(1)  (0) 2020.03.17
[Django_심화]2 - Rest, Serializer  (0) 2019.11.03
[Django_심화]1 - 준비운동  (0) 2019.11.02
[6주차]Form  (0) 2019.03.06
반응형

1.Rest Architecture 

-REST란? : Representational State Transfer  / “자원을 이름으로 구분하여 상태를 전송하는 방법”

 

-Rest 설계 필요 충분 조건

   1. SERVER – CLIENT 

   2. STATELESS #클라이언트의 이전 상태를 기록하지 않는 연결방식을 취함 

   3. CACHE #캐쉬 처리기능 

   4. UNIFORM INTERFACE #일관된 인터페이스 

  • Resource가 URI로 식별이 되어야한다.
  • CRUD를 HTTP메세지로 수행 가능해야한다.
  • 메세지는 자체로 모든 것이 설명 가능해야한다.
  • 어플리케이션의 상태는 하이퍼링크를 이용해 전이되야한다.(HATEOAS)

   5. LAYERED SYSTEM #다칭적인 구성

   6. CODE-ON-DEMAND #JS처럼 서버와 같이 원격지에서 보낸 코드로 메소드를 실행시킬 수 있는 것

 

-API란? Application Program Interface / Request, Response로 오가는 구조화된 데이터

-Rest API  : REST의 설계방식을 잘 따르는 API / 대부분의 API는 rest를 잘 따르지 않는다 / Json은 모든 태그가 만들어져 있지않고, 만든 이가 정의하기 나름이기 때문에

 

    -> 필요한 이유?

         : 백엔드, 프론트엔드 분리 / 독립적인 네트워크 향상 가능 / 클라이언트 플랫폼 다양화 지원 가능

 

Django VS Django Rest Framework

  Django Djnago Rest Framework
만들어지는 것 웹 어플리케이션 RESTful API
전달하는 데이터 HTML Form(HTML, CSS, JS) JSON 데이터
데이터를 담는 곳  Form / ModelForm Serializer/ ModelSerialier
model로 부터 Field 읽어온다
유효성 검사

 

Form VS Serializer

 

 

Serializer vs ModelSerialier

Form과 ModelForm이 존재하듯이 Model만 작성할 줄 알면
더 간편하게 Serializer를 사용할 수 있게하는 ModelSerialier에 대해서 공부한다.
ModelSerialier는 쿼리셋과 모델 직렬화를 알아서 해준다.

 

2.Serializer 실습 

가상환경 생성

$python -m venv myvenv

 

필요 패키지 설치

$pip install djangorestframework

$pip install django

 

django 프로젝트 생성

$django-admin startproject rest

-> 생성 후 cd rest 로 폴더 이동

 

django app 생성

$ python manage.py startapp post

 

settings.py에 앱 추가(장고 프레임워크도 등록)

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework',
    'post',
]

url 관리

   -> 앱 폴더 내부에 urls.py 생성(계층적 url 관리 위해 분할) ##아니 나는 urls.py를 완성하지 못하면 마이그레이트가 안된다.. 이거먼저!

from django.urls import path, include
from rest_framework.routers import DefaultRouter
from . import views

router = DefaultRouter() #ROUTER 객체 생성
router.register('post', views.PostViewSet) #ROUTER 객체의 REGISTER 함수(첫번째 인자 = URL, 함수)

urlpatterns = [
    path('', include(router.urls))
]

#rest_framework는 ROUTER을 사용해 URL을 결정한다
#CRUD 기반으로 URL을 설정한다

  

    -> 프로젝트 폴더 urls.py 에 모듈 추가

from django.contrib import admin
from django.urls import path, include
import post.urls


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

앱 폴더의 models.py 에 모델 클래스 정의 (post/models.py)

from django.db import models

class Post(models.Model):
    title = models.CharField(max_length=100)
    body = models.TextField()
# Create your models here.

앱 폴더 내부에 serializer.py 생성 및 작성 (어떤 클래스의 어떤 필드를 사용할 것인지)

from .models import Post
from rest_framework import serializers

class PostSerializer(serializers.ModelSerializer):
    class Meta:
        model = Post
        fields = ['title', 'body'] 
        # 모든 필드를 사용할 경우 '__all__' 사용 가능

views.py 작성하기

-> rest_framework 의 viewsets 모듈과 작성한 모델serializer 추가

 

from rest_framework import viewsets
from .models import Post
from .serializer import PostSerializer

class PostViewSet(viewsets.ModelViewSet):
    queryset = Post.objects.all()
    serializer_class = PostSerializer
    
Django Rest Framework는 Class base View 이기에 
view로서 class를 작성한다
viewsets의 ModelViewSet을 상속받는다.

 

##ROUTER

▪ ViewSet에는 여러가지 메소드(함수)들이 있다 

      ex) retrieve() , destroy(), …

▪ 이 모든 것을 하나의 path()로 처리해 주는 것은 불가능하다.

▪ Path함수를 묶어준다 == path함수의 두번째 인자로 오는 함수를 묶는다 

     -> Path(요청을 처리할 url, 요청을 인자로 받아 처리할 함수, namespace)

 

#실행 결과(api 서버 보기)

1. api root : urls.py 에 작성된 DefaultRouter 에 의해 만들어진 기본적인 환경 / 처음 보여지는 화면은 GET 요청을 할 수 있는 URL이 보여진다.

 

2.POST API

-request : 127.0.0.1/8000/post

 

-response

 

post 후 post/1로 들어가면 allow 부분에 put이 들어간 것을 볼 수 있음

각 객체에 pk 값 부여하기 

-> serializer.py 파일의 PostSerializer 을 수정한다

class PostSerializer(serializers.ModelSerializer):
    class Meta:
        model = Post
        fields = ['id', 'title', 'body'] 

새로 고침 후 보면 id 값을 직접 확인할 수 있는 것을 볼 수 있다. 

id 값 : 각 인스턴스에 붙는 고유 번호

Read Only 설정하기

 -> serializer.py 파일의 PostSerializer을 수정한다

 -> read_only_fields 에 read_only 속성을 적용할 필드를 tuple에 추가한다

 -> 수정 시 read_only 부분이 true로 바뀌는 것을 볼 수 있다.

 -> write_only부분도 같은 방법으로 수정하면된다!

class PostSerializer(serializers.ModelSerializer):
    class Meta:
        model = Post
        fields = "__all__"
        read_only_fields = ("title",)

반응형

'Web > Django' 카테고리의 다른 글

[Django] Instagram 클론 코딩(1)  (0) 2020.03.17
[Django_심화]3 - viewset & router  (2) 2019.11.03
[Django_심화]1 - 준비운동  (0) 2019.11.02
[6주차]Form  (0) 2019.03.06
[5.5주차]Faker  (0) 2019.03.05
반응형

1. JSON & Http Resquest & Response & Httpie

  • JSON 
    • Java Script Object Notation 의 약자
    • 데이터 송수신을 자바스크립트의 문법으로 표현된 객체로 수행할 수 있게 만든 가벼운 문자열 데이터 표현식
    • 자바스크립트를 사용하지 않아도 사용 가능하다!
    •  웹에서는 Server와 Client 사이에는 여러 항목을 주고 받음. /구조를 나타내는 HTML /스타일을 표현하는 CSS /논리를 구현하는 Javascript
    • 앞으로의 강의들은 데이터인 JSON 만 주고 받음!
  • JSON 문법 형식
    • Python 의 딕셔너리와 비슷한 구조
    • name : value
    • 숫자, 문자(열), Boolean, 배열, 객체 등으로 구성 가능 
    • JSON  데이터를 보낼 때에는 직렬화(Serialization) 과정을 거쳐 JSON 데이터를 문자열로 바꾸어 상대방에게 보낸다.
    • 데이터를 보낼 때에는 JSON  -> 문자열로 / 데이터를 받을 때에는 문자열 -> JSON으로 바꾸어 받는다.
json_example = { 
	"string_name": "something",
    "number_name": 3,
    "null_name": null,
    "bool_name": true
}
  • Python에서 JSON 사용하기
    • Python 딕셔너리 자료형을 반환해보자
import json //Json을 처리하는 라이브러리를 제공
diary = {
	"id": 3,
    "title": “멋쟁이사자처럼”,
    "body“: “2학기도 파이팅”
}

print(diary)
//{‘id’: 3, 'title': ‘멋쟁이사자처럼’, ‘body’: ‘2학기도 파이팅’}

print(type(diary))
//<class ‘dict’>
  • Dict to JSON 
    • JSON의 dumps 함수를 이용해 변환 진행
    • 데이터를 송신할 때 사용할 수 있다.
    • dic 이였던 자료형이 str로 변환
diary_s = json.dumps(diary)
print(diary_s) 
//{‘id’: 3, 'title': ‘멋쟁이사자처럼’, 'body': ‘2학기도 파이팅’}
print(type(diary_s)) 
//<class ‘str’>
  • JSON to Dict
    • JSON 의 load 함수를 이용해 변환을 진행
    • 데이터를 수신할 때 사용할 수 있다
    • Str 자료형이 dict로 다시 변환되었음을 볼 수 있다.
diary_b = json.loads(diary)
print(diary_b) 
//{‘id’: 3, 'title': ‘멋쟁이사자처럼’, 'body': ‘2학기도 파이팅’}
print(type(diary_b)) 
//<class ‘dict’>

Http Requsest & Response

  • 정의
    • Http란?
      • 웹 상에서 통신을 주고 받을 수 있는 주체, Client와 Server 그 중, Server의 역할은 Request 를 가공해서 처리해주는 역할
      • Web 상에서 지원하는 통신 규약을 Http
      • 한마디로 정의한다면?
        • HttpRequest : 요청에 대한 메타 정보를 가지고 있는 객체 
        • HttpResponse : 요청에 대한 메타 정보를 가지고 있는 객체
    • Django 에서 Http Method
GET POST
빈 입력공간 가져와 입력한 내용 처리
URL에 데이터 정보 포함 URL에 데이터 정보 포함 안함

        ▪ Django 에서 Rest FrameWork에서 Http Method

Method 기능
GET 요청받은 URL의 정보 검색하여 응답
POST 요청된 자원을 생성(CREATE)
DELETE 요청된 자원 삭제
PATCH 요청된 자원 일부 수정
OPTION 웹 서버에 지원된 메소드 종류 확인

 

 

 Django Rest FrameWork?

-> 장고 안에서 RESTful API 서버를 쉽게 구축할 수 있도록 도와주는 오픈 소스라이브러리

 

-Rest?

    -> HTTP 의 URL과 HTTP Method(GET, POST, PUT, DELETE)를 사용해서

         API 사용 가독성을 높인 구조화된 시스템 아키텍쳐(Framework)

 

-RESTful 아키텍쳐를 HTTP Method와 함께 사용해서 웹, 데스크탑 앱, 어플리케이션 까지 구동할 수 있는 서버를 만든다고 생각!

 

  • Django Rest Framework API Server에서는 JSON을 주고 받음
  • 서버 Response 종류 
    • 1XX (정보) -> 요청을 받았으며 프로세스를 계속한다.
    • 2XX(성공) -> 요청을 성공적으로 받았으며 인식했고 수용했다. 
    • 3XX(리다이렉션) -> 요청을 완료하기 위해 추가 작업 조치가 필요하다.
    • 4XX(클라이언트 오류) -> 요청의 문법이 잘못되었거나 요청을 처리할 수 없다.
    • 5XX(서버 오류) -> 서버가 명백히 유효한 요청에 대해 충족에 실패했다.

Httpie

- 요청을 Command Line으로 동작하는 파이썬 기반 프로그램 (=http client)

- 다른 http Client 보다 가볍고 설치하기 편하기 떄문에 사용

 

-httpie 설치

>>pip install --upgrade httpie

 

-httpie 명령어

>>http [flags] [METHOD] URL [ITEM[ITEM]]

 

flags : 옵션

▪ METHOD : HTTP METHOD

▪ URL : 요청이나 응답의 대상 URL

▪ ITEM : 처리할 값 (인자)

▪ POST / PUT : =로 표현

▪ GET : ==로 표현

 

▪ Httpie 명령어 사용 예시 

     ▪ GET

          http(GET) 대상주소 인자 ==값

 http (GET) example.org a==1 b==2
 http example.org a==1 b==2 


      ▪ PUT

           http(PUT) 대상주소 GET인자 ==값 PUT인자=값

 http PUT example.com a==1 b==2


▪ Get 인자가 있으면 쓰고 없으면 안쓴다. ▪ Put 인자가 있으면 쓰고 없으면 안쓴다.

 

2. CBV

-장고의 view

    - 호출 가능한 객체(callable object) 로 정의

        -> 함수 / 클래스

    - 함수와 클래스의 차이 : 함수 (상속x) / 클래스 (상속o)

    - 상속을 사용하는 이유는 ? 중복의 제거 / 코드의 재사용

 

따라서 CBV를 사용하는 이유는 상속을 사용해 코드를 더 간단하게 작성하기 위해 사용

 

-FBV(Function Based View)  : 함수 기반 뷰 

 

##실습하면서 익혀봅시다

순서 : 프로젝트 생성 -> 앱 생성 -> 템플릿 추가

 

가상환경 생성 및 활성화

$python -m venv myvenv

$ source myvenv/Scripts/activate

 

프로젝트 생성

$ django-admin startproject CBV

$ cd CBV

 

앱 생성 

$python manage.py startapp classBaseCrud

 

settings.py 에 앱 추가

INSTALLED_APPS = [
    'classBaseCrud',
]

 models.py 작성하기

- 클래스 생성

from django.db import models

# 클래스를 생성하여 제목, 생성일, 수정일, 본문 필드 작성

class ClassBlog(models.Model):
    title = models.CharField(max_length=100)
    created_at = models.DateTimeField(auto_now_add=True)
    #auto_now_add 옵션 : model이 최초 저장시에만 현재 날짜 적용
    updated_at = models.DateTimeField(auto_now=True)
    #auto_now 옵션 : 데이터가 저장 될 때마다 현재 날짜로 갱신
    body = models.TextField()

    def __str__(self):
        return self.title

-admin.py에 생성한 클래스 등록

from django.contrib import admin
from .models import ClassBlog

admin.site.register(ClassBlog)

-마이그레이션

$ python manage.py makemigrations
$ python manage.py migrate

 

views.py 작성하기

1) 사용할 모듈 추가 - CRUD

게시글 목록 ListView
새로운 게시글 생성 CreateView
게시글 상세 내용 DetailView
게시글 수정 UpdateView
게시글 삭제 DeleteView

    -Generic Views : 웹 개발 시 자주 사용하는 기능을 장고에서 미리 제공 / 외부 모듈 적용이 필요하다

 

      #사용할 모듈 추가 CRUD

from django.utils import timezone

from django.urls import reverse_lazy

from django.views.generic.list import ListView
#게시글 목록 보여줌

from django.views.generic.detail import DetailView
#게시글의 상세 내용을 보여줌

from django.views.generic.edit import CreateView, UpdateView, DeleteView
#게시글 생성, 수정, 삭제 

from .models import ClassBlog

2)모듈을 상속해 클래스 작성(classBaseCrud/views.py)

-CREATE

#CREATE
class BlogCreate(CreateView):
    model = ClassBlog
    fields = ["title", "body"]
    success_url = reverse_lazy('list')
    #reverse_lazy 
    #- redirect 와 같은 기능으로 , generic view에서 주로 사용
    #- reverse_lazy() 함수 사용 인자로 URL 이름을 넣어줌
    #- 작업이 성공적으로 완료되었을 경우 해당 URL로 이동

-READ

#READ
class BlogView(ListView):
    model = ClassBlog
    template_name = 'classBaseCrud/list.html'
    context_object_name = 'blog_list'
    # List Views
    #- Generi view 중 특정 모델의 리스트를 출력해주는 뷰
    #- 모델에 대한 쿼리가 필요하고(queryset)
    #- 어느 템플릿에 (template_name)
    #- 어떤 파라미터명으로 전달할지 (context_object_name) 를 정의
    #- 약속되어있는 html 이름을 사용하지 않고 작성하기 위함
    #- 해당 html을 사용할 class에 template_name을 설정하면 된다
    
    #context_object_name : 임의로 설정하여 기본적으로 설정되어있는 객체를 가져옴
class BlogRead(DetailView):
    context_object_name = 'blog'
    model = ClassBlog
    #DetailView
    #- 특정 모델의 특정 오브젝트에 대한 자세한 정보를 출력해주는 뷰
    #- 어떤 모델의 어떤 오브젝으를 어떤 템플릿에 전달할지 정의

-UPDATE

#UPDATE
class BlogUpdate(UpdateView):
    model = ClassBlog
    fields = ["title", "body"]
    success_url = reverse_lazy("list")

-DELETE

#DELETE
class BlogDelete(DeleteView):
    model = ClassBlog
    success_url = reverse_lazy("list")

앱 내부에 urls.py 생성 및 작성

- 작성할 클래스에 맞는 url path 작성

- (urls.py / classBaseCurd)

from django.urls import path
from .import views

#작성할 클래스에 맞는 url path 작성
urlpatterns = [
    path("", views.BlogView.as_view(), name='list'),
    #as_view : view를 하나 만들어서 이를 return
    #함수가 하나 만들어지는 것과 같음
    #클래스를 정의한 후 이에 해당하는 함수 만들어 사용하는 방식

    path("create/", views.BlogCreate.as_view(), name="create"),
    path("read/<int:pk>/", views.BlogRead.as_view(), name="read"),
    path("update/<int:pk>/", views.BlogUpdate.as_view(), name="update"),
    path("delete/<int:pk>/", views.BlogDelete.as_view(), name="delete"),
]

프로젝트 urls.py 에 앱 urls.py 추가

- (urls.py / CBV)

from django.contrib import admin
from django.urls import path, include
#django.urls 의 include 모듈 추가
#앱의 urls.py 파일을 프로젝트 urls.py에 추가
import classBaseCrud.urls
import classBaseCrud.views

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

templates 생성하기

- 수행 결과를 보여주는 HTML 템플릿이 존재해야하고 
ListView 는 블로그 리스트 HTML / CreateView, UpdateView 는 입력공간(form)을 갖는 HTML

DetailView는 상세 페이지 HTML / DeleteView 는 삭제 작업을 확인하는 HTML 필요

 

- Generic View 에서는 기본적으로 설정된 이름이 존재

- 다른 이름으로 HTML 을 작성하기 위해서는 추가 설정이 필요

 

View 이름 HTML 이름
ListView (소문자 모델)_list.html
CreateView (소문자 모델)_form.html
DetailView (소문자 모델)_detail.html
UpdateView (소문자 모델)_form.html
DeleteView (소문자 모델)_confirm_delete.html

 

##template폴더 구성할 때 template 안에 HTML 파일을 작성하는 게 아니라 App 이름의 폴더를 작성하고 그 안에 작성

앱 안에 templates라는 폴더를 만들고 그 안에 앱 이름으로 폴더를 만들어 그 안에 html를 만들어야함

#classblog_list.html

<!DOCTYPE html>
<html lang="ko" dir="ltr">
    <head>
        <meta charset="utf-8">
        <title>Class Base View</title>
    </head>
    <body>
        <a href="{% url 'create' %}"> 추가 </a>
        
        <br>
        
        {% for blog in blog_list %}
        <h2> {{ blog.title }} </h2>
        <h2> {{ blog.created_at }} </h2>
        <p> {{ blog.body }} </p>
        
        <a href="{% url 'read' blog.id %}"> 자세히보기 </a><br>
        <a href="{% url 'update' blog.id %}"> 수정 </a><br>
        <a href="{% url 'delete' blog.id %}"> 삭제 </a><br>
        {% endfor %}
    </body>
</html>

#classblog_form.html

<form method="POST">
    {% csrf_token %}
    {{ form.as_p }}
    <input type="submit" value="추가하기">
</form>

//HTTP POST, PUT, DELETE 🡪 {% csrf token %} 사용
//{{ form.as_p}} : view에서 전달한 form 객체를 템플릿 변수로 사용 / 폼의 각 필드를 p태그 안에 배치

#classblog_detail.html

<h1> 본문 자세히 보기 페이지 </h1>

<hr>

<h2> 제목 : {{ blog.title }} </h2>
<h4> 날짜 : {{ blog.created_at }} </h4>
본문 : {{ blog.body }}

#classblog_confirm_delete.html

<form method="POST">
    {% csrf_token %}
    <h2>진짜 지울거야?</h2>
    <br>
    <br>
    <input type="submit" value="삭제">
</form>

##결과

CREATE
DETAIL
UPDATE(수정)
DELETE
생성 후 리스트 목록

반응형

'Web > Django' 카테고리의 다른 글

[Django_심화]3 - viewset & router  (2) 2019.11.03
[Django_심화]2 - Rest, Serializer  (0) 2019.11.03
[6주차]Form  (0) 2019.03.06
[5.5주차]Faker  (0) 2019.03.05
[5주차]2.Pagination  (0) 2019.03.05
반응형

1. 다운

$wget http://forum.falinux.com/_zdownload/data/ezboot.x5.v18.tar.gz

2. 압축 해제

tar -xvf ezboot.x5.v18.tar.gz

3. 내용물 확인

jisu@ubuntu:~$ cd v18.org
jisu@ubuntu:~/v18.org$ ls
eztiny  image  include  main  Makefile  start

image - 이지부트의 최종 이미지 파일이 들어감.

include - 이지부트 소스가 사용하는 헤더 파일이 있음.

main - C언어로 작성된 코드가 있음.

start - 어셈블리어로 작성된 보드 초기화 관련 코드들이 있음.

 

이지부트는 어셈블리 코드들이 컴파일 되어 한부분, main 이렉터리에 있는 C코드들이 컴파일되어 한부분을 이룹니다.

 

프로그램이 시작되면 맨처음 0번지에는 start에 있는 코드들이 실행(초기화라고 생각해라)된다. 그리고 실행이 끝나면 PC(Program Counter)에 main() 함수주소가 들어갑니다.(PC <- main() 주소)

 

4. 홈 디렉토리에 작업폴더 만들기!

jisu@ubuntu:~/v18.org/main$ cd ..
jisu@ubuntu:~/v18.org$ mkdir ~/navilnux
jisu@ubuntu:~/v18.org$ cp main ~/navilnux/chap2 -r
jisu@ubuntu:~/v18.org$ cp include ~/navilnux/chap2 -r

5. chap2폴더로 들어와 작업해봅시다

jisu@ubuntu:~/v18.org$ cd  ~/navilnux
jisu@ubuntu:~/navilnux$ ls
chap2
jisu@ubuntu:~/navilnux$ cd chap2
jisu@ubuntu:~/navilnux/chap2$ ls
arp_cmd.c      flash_cmd.c  lib1funcs.S     net.o       time.c
arp_cmd.o      flash_cmd.o  main.c          printf.c    time.o
config.c       go_cmd.c     main-elf32      printf.o    vscanf.c
config.o       go_cmd.o     main-ld-script  ram_cmd.c   vscanf.o
cs8900.c       gpio.c       main.o          ram_cmd.o   vsprintf.c
cs8900.o       gpio.o       main_org        serial.c    vsprintf.o
defaultlibs    help.c       Makefile        serial.o    zmodem.c
entry.o        help.o       Makefile.bak    string.c    zmodem_cmd.c
entry.S        include      nand.c          string.o    zmodem_cmd.o
flash_29lvx.c  info_cmd.c   nand.o          tftp_cmd.c  zmodem.o
flash_29lvx.o  lib1funcs.o  net.c           tftp_cmd.o

6. serial.c 파일을 수정합니다

  • 헤더 파일에 있는 #include <config.h> 지움
    -> 이지부트 설정을 담고 있는 파일 
  • extern TConfig Cfg;를 지움
    -> 이지부트 설정 담음
  • void SerialInit( eBauds baudrate ) 함수를 다 지움
    -> 이지부트 설정 담음
  • static volatitle Word *UART = (volatile Word *) STUART; 
    =>>>#ifdef IN_GUMSTIX
    static volatitle Word *UART = (volatile Word *) FFUART;

    #else static volatitl
    #endif

    -> UART : 컴퓨터 간에 통신 기능을 제공하는 기법
    -> 나빌눅스에서는 FULL FUNCTION UART를 사용
    ==> UART를 버퍼 주소로 변경해 준다
    -> volatile 는 컴파일러로부터 최적화를 막아주는 키워드

6. main.c를 그냥 다 지우고

navilux.c를 만들어서 하자

 

$rm main.c
$gedit navilnux.c
#include <pxa255.h>
#include <time.h>
#include <gpio.h>
#include <stido.h>
#include <string.h>

int main(void){
	while(1){
		printf("hello world\n");
		msleep(1000);
	}
}

//나빌눅스 c코드 / 1초마다 hello world를 출력

7.권한 주기

$chmod +x navilnux.c

8. 지워야할 항목 temp 폴더 만들어서 옮기기

jisu@ubuntu:~/navilnux/chap2$ chmod +x navilnux.c
jisu@ubuntu:~/navilnux/chap2$ mkdir temp
jisu@ubuntu:~/navilnux/chap2$ mv entry.S temp
jisu@ubuntu:~/navilnux/chap2$ mv gpio.c temp
jisu@ubuntu:~/navilnux/chap2$ mv lib1funcs.S temp
jisu@ubuntu:~/navilnux/chap2$ mv main-ld-script temp
jisu@ubuntu:~/navilnux/chap2$ mv navilnux.c temp
jisu@ubuntu:~/navilnux/chap2$ mv printf.c temp
jisu@ubuntu:~/navilnux/chap2$ mv serial.c temp
jisu@ubuntu:~/navilnux/chap2$ mv string.c temp
jisu@ubuntu:~/navilnux/chap2$ mv time.c temp
jisu@ubuntu:~/navilnux/chap2$ mv vsprintf.c temp

9. c 파일을 지움 삭제후 폴더에 보관했던 파일들을 꺼내오고 폴더를 삭제

$rm *.c
$cp temp/* .
$rm -r temp

10.헤더파일 정리

$cd include
$mkdir temp
$mv gpio.h temp
$mv pxa255.h temp
$mv serial.h temp
$mv stdarg.h temp
$mv stdio.h temp
$mv string.h temp
$mv time.h temp
$rm *.h
$rm 1
$cp temp/* .
$rm -r temp

11. Makefile 지웠다가 다시 만듬

CC = arm-linux-gcc

LD = arm-linux-ld

OC = arm-linux-objcopy

 

CFLAGS = -nostdinc -I. -I./include

CFLAGS += -Wall -Wstrict-prototypes -Wno-trigraphs -O2

CFLAGS += -fno-strict-aliasing -fno-common -pipe -mapcs-32

CFLAGS += -mcpu=xscale -mshort-load-bytes -msoft-float -fno-builtin

 

LDFLAGS = -static -nostdlib -nostartfiles -nodefaultlibs -p -X -T ./main-ld-script

 

OCFLAGS = -O binary -R .note -R .comment -S

all: navilnux.c

$(CC) -c $(CFLAGS) -o entry.o entry.S

$(CC) -c $(CFLAGS) -o gpio.o gpio.c

$(CC) -c $(CFLAGS) -o time.o time.c

$(CC) -c $(CFLAGS) -o vsprintf.o vsprintf.c

$(CC) -c $(CFLAGS) -o printf.o printf.c

$(CC) -c $(CFLAGS) -o string.o string.c

$(CC) -c $(CFLAGS) -o serial.o serial.c

$(CC) -c $(CFLAGS) -o lib1funcs.o lib1funcs.S

$(CC) -c $(CFLAGS) -o navilnux.o navilnux.c

$(LD) $(LDFLAGS) -o navilnux_elf entry.o gpio.o time.o vsprintf.o printf.o string.o serial.o lib1funcs.o navilnux.o

$(OC) $(OCFLAGS) navilnux_elf navilnux_img

$(CC) -c $(CFLAGS) -o serial.o serial.c -D IN_GUMSTIX

$(LD) $(LDFLAGS) -o navilnux_gum_elf entry.o gpio.o time.o vsprintf.o printf.o string.o serial.o lib1funcs.o navilnux.o

$(OC) $(OCFLAGS) navilnux_gum_elf navilnux_gum_img

 

clean:

rm *.o

rm navilnux_elf

rm navilnux_img

rm navilnux_gum_elf

rm navilnux_gum_img

12.

v18.org/ main / main.c 의 gokernel 확인

    	     	if ( getc_timed( Cfg.BootMenuKey, Cfg.AutoBootWaitTime*1000 ) )
    	     	{
       	     		//printf( "\r                                                                \n");  
       	     		printf( "\n");  
             		CopyImage();
             		GoKernel( 1, NULL );
             		// ¿©±â·Î ¿òÁ÷ÀÌÁö ŸÊŽÂŽÙ.
             		// ---
    	     	}
    	     	break;

 

13.v18.org/main/go_cmd.c 안의 함수 주소 확인

int 	GoKernelSingle( void )
{
    	char buff[] = { 0,0,0,0,0 }; // ží·É Ä¿žÇµå œÃÇè¿ëÀÓ 
    	void (*theKernel)(int zero, int arch);

	char kcmd[2048];
	int  len;
	
	// Ä¿³Î Ä¿žÇµå ¹®ÀÚ¿­À» ŸòŸî¿ÂŽÙ.
	memset( kcmd, 0, 2048 );
	len = GetKCmdStr( kcmd );	

    	printf( "Starting kernel [MARCH %d]...\n", Cfg.Kernel_ArchNumber );

    	memcpy( (char *) DEFAULT_RAM_KERNEL_ZERO_PAGE, kcmd, 2048 );

    	theKernel = (void (*)(int, int))DEFAULT_RAM_KERNEL_START; 
    	theKernel( ( long ) 0 , (long) Cfg.Kernel_ArchNumber );

    	return 0;
}

14.v18.org/include/mem_map.h 확인

#define DEFAULT_RAM_KERNEL_START        0xA0008000              // ·¥¿¡Œ­ Ä¿³Î     œÃÀÛ Ÿîµå·¹œº 
#define DEFAULT_RAM_RAMDISK_START       0xA0800000              // ·¥¿¡Œ­ ·¥µðœºÅ© œÃÀÛ Ÿîµå·¹œº 
#define DEFAULT_RAM_WORK_START          0xA1000000              // ÀϹÝÀûÀÎ ºÎÆ® ·ÎŽõ ÀÛŸ÷ ¿µ¿ª 

#define DEFAULT_RAM_KERNEL_ZERO_PAGE    0xA0000000              // ºÎÆ®·ÎŽõ¿¡Œ­ Ä¿³Î·Î ÀüŽÞÇÏŽÂ ¿µ¿ª œÃÀÛ Ÿîµå·¹œº 

#define DEFAULT_RAM_KERNEL_START 0xA0008000

이라고 되어있습니다.

메모리 주소가 하나의 헤더파일에 정의되어 있는 것입니다.

이지부트가 실행이 끝나면, . 커널이 실행되어야 할 주소입니다.

 

15.v18.org/main/main-ld-script 수정

change 0xA0F00800 to 0xA0008000.

OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_ram_entry)
SECTIONS
{
	. = 0xA0008000;

	. = ALIGN(4);
	.text : { *(.text) }

	. = ALIGN(4);
	.rodata : { *(.rodata) }

	. = ALIGN(4);
	.data : { *(.data) }

	. = ALIGN(4);
	.got : { *(.got) }

	. = ALIGN(4);
	.bss : { *(.bss) }
}

make해서 이지부트 이미지 만들려고하는데 에러 나옴ㅎㅎ 울고싶다

include/pxa255.h:46:1: warning: this is the location of the previous definition
serial.c:41: error: syntax error before "Word"
serial.c:41: warning: initialization discards qualifiers from pointer target type
make: *** [all] Error 1

 

반응형
반응형
https://insightbooklist.wordpress.com/books/programming-insight/%EB%8F%84%EC%A0%84-%EC%9E%84%EB%B2%A0%EB%94%94%EB%93%9C-os-%EB%A7%8C%EB%93%A4%EA%B8%B0/%EC%86%8C%EC%8A%A4%EC%BD%94%EB%93%9C%EC%99%80-%EC%B0%B8%EA%B3%A0-%EC%9E%90%EB%A3%8C/

어떤 착한 분이 임베디드 관련 자료들을 다 복원해주셨다 ㅜㅜ 우선 다 다운받아놓기 ....

 

1.gumstix_uboot.tgz 다운

위에서 다운받으면 되지만 vmware는 32bit , OS는 64bit여서 자꾸 다운됨 ㅜㅜ 그래서 wget 명령어 사용함

$wget -O gumstix_uboot.tgz https://drive.google.com/file/d/0B6crpDdRQpLzVDM0clpoWG5ROHc/edit

##이거 안돼서 

https://tttsss77.tistory.com/76

로 공유 폴더 만들고 gumstix_uboot.tgz 공유 폴더로 만듬 

 

ubuntushare 폴더에서 gumstix_uboot.tgz 를 root로 cp

$ cp gumstix_uboot.tgz ~
$ ls
Desktop    examples.desktop   Pictures    qemu-2.1.2.tar.bz2  workspace
Documents  gumstix_uboot.tgz  Public      Templates
Downloads  Music              qemu-2.1.2  Videos

 

 

2. uboot 압축 품

$tar -xvf gumstix_uboot.tgz

 

3.폴더 이동해 make distclean  입력

$cd gumstix_uboot
$make distclean

 

4.파일 삭제되는 것을 볼 수 있습니다

@ubuntu:~/gumstix_uboot$ make gumstix_config
Configuring for gumstix board...
$make all

하고 ls 하면 u-boot.bin이 생성된 것을 볼 수 있음

jisu@ubuntu:~/gumstix_uboot$ ls
arm_config.mk dtt lib_nios nios_config.mk board dump lib_nios2 post CHANGELOG examples lib_ppc ppc_config.mk common fs m68k_config.mk pro compilelog i386_config.mk MAINTAINERS README config.mk include MAKEALL rtc COPYING lib_arm Makefile System.map cpu lib_generic microblaze_config.mk tools CREDITS lib_i386 mips_config.mk u-boot disk lib_m68k mkconfig u-boot.bin doc lib_microblaze net u-boot.map drivers lib_mips nios2_config.mk u-boot.srec
jisu@ubuntu:~/gumstix_uboot$ /usr/local/bin/qemu-system-arm -M connex -pflash u-boot.bin -nographic
qemu-system-arm: failed to read the initial flash content
qemu-system-arm: Initialization of device cfi.pflash01 failed

64비트와 32비트 차이로 오류가 났다 ㅜㅜ >> 명령어 입력 >> flash.bin이 생성 > uboot.bin을 대체한다고 생각

jisu@ubuntu:~/gumstix_uboot$ dd if=/dev/zero of=flash.bin bs=4096 count=4096
4096+0 records in
4096+0 records out
16777216 bytes (17 MB) copied, 0.0392093 s, 428 MB/s
jisu@ubuntu:~/gumstix_uboot$ dd if=u-boot.bin of=flash.bin bs=4096 conv=notrunc
38+1 records in
38+1 records out
158832 bytes (159 kB) copied, 0.00100775 s, 158 MB/s

해결하고 다시 명령어 입력해보면 완성!

jisu@ubuntu:~/gumstix_uboot$ /usr/local/bin/qemu-system-arm -M connex -pflash flash.bin -nographic
pxa2xx_clkcfg_write: CPU frequency change attempt


U-Boot 1.1.4 (Sep 23 2019 - 04:51:26) - 200 MHz - 

*** Welcome to Gumstix ***

U-Boot code: A3F00000 -> A3F26C70  BSS: -> A3F5BD8C
RAM Configuration:
Bank #0: a0000000 64 MB
Flash: 16 MB
Using default environment

SMC91C1111-0
Net:   SMC91C1111-0
Hit any key to stop autoboot:  0 
Instruction Cache is ON
### JFFS2 loading 'boot/uImage' to 0xa2000000
Scanning JFFS2 FS:  done.
find_inode failed for name=boot
load: Failed to find inode
### JFFS2 LOAD ERROR<0> for boot/uImage!

 

 

지긋지긋한 설치 완성 

이러고 나서 또 에러나면 그냥 ㅘㄱㅁ,ㅇ라ㅣㅇㄴ러ㅣ마어리ㅏㅇㄴ

반응형
반응형

qemu 설치

1.qemu 받을 폴더 만들고 -> wget로 파일 받음

$mkdir workspace
$wget http://wiki.qemu-project.org/download/qemu-2.1.2.tar.bz2 

 

2. 다운 완료 되면 압축 풀어줌

$tar -xvf qemu-2.1.2.tar.bz2

$ls
>>qemu-2.1.2   qemu-2.1.2.tar.bz2

3.qemu-2.1.2 폴더로 이동 -> ./configure

$cd qemu-2.1.2/
$./configure

4.패키지 여러 개 설치     (설치하고 -> make 하면 에러가 뜬다)

아니 뭐가 문젠지는 모르겠지만 make 하기전에 패키지를 다 깔고 들어가도 되지 않을까 싶어서 시작했는데 된다! 

glib-2.12와 gthread-2.0이 컴파일하는데 필요

$sudo apt-get install libglib2.0
autoreconf를 못찾는다는 에러

$sudo apt-get install autoconf
http://theintobooks.wordpress.com/2012/10/30/installing-qemu/
에러 참고

$sudo apt-get install libtool
flex와 bison을 찾지 못함
$sudo apt-get install aptitude // 다른 설치 툴 사용
$sudo aptitude install flex        //flex 설치
$sudo aptitude install bison     //bison 설치

##make 시 에러가 나면 ctrl + c 정지 후 -> sudo make clean -> make 

 

$sudo make install 

5.install 완료

오랜시간이 걸려 완료 후 정상적으로 설치되었는지 확인하려면

$ls /usr/local/bin

완료 완료!

반응형

+ Recent posts