後で見るDjango Web開発サイクル

14308 ワード

>江古ウェブページ開発大周期


1.全体の流れ


(Browser)Httpリクエスト→(Webサーバ)Nginx/APacheの静的リソース(HTML、Image...)要求処理+このとき参加する(WSGI)wsgi.py条約によれば、webサーバは受信したリクエストをpythonアプリケーション→urlに転送する.pyリクエストのurlに一致する関数→viewsを送信します.pyで対応する関数を検索します.このとき、その関数はformsです.py | models.pyと対話→最後にテンプレートを送信できます.

2.開発手順


settings.py → urls.py → views.py + models.py | forms.py → example.html + static files

Step by step practice


a.cドライブにフォルダを作成するには、次の手順に従います.
work_django>django_mldl
$pip install virtualenv==16.7.7
$virtual django_env
$django_env\Scripts\activate # 가상환경 실행. 로컬에 설치된 라이브러리와 버전 충돌을 막기 위해 독립된 가상환경 생성. 
$pip install django==2.2.6
b.adminプロジェクト(Web)作成
$django-admin startproject _프로젝트명_
c.機能(会員加入、商品調査...)アプリケーションの作成
このとき、管理します.py=江古プロジェクト管理
  • プロジェクトに入り、アプリケーションを作成します:startapp
  • python manage.py startapp _기능명_
    c-2. サーバーの実行:runserver
    $python manage.py runserver
    d.モデル@(models.py)の作成
  • DBとのコミュニケーションでは、DjangoはSQLではなくモデルクラス(==クラス/オブジェクト+テーブル)を使用してORM(==クラス/オブジェクト+テーブル)を使用します.
    -ORM:SQL = {
    Class:Table,
    Class's variable: Column(DB field),
    Class's object: Row(DB record)
    }
  • class GuessNumbers(models.Model):
       name = models.CharField(max_length=24) 
       text = models.CharField(max_length=255) 
       lottos = models.CharField(max_length=255, default='[1, 2, 3, 4, 5, 6]') 
       num_lotto = models.IntegerField(default=5) 
       update_date = models.DateTimeField()
       def generate(self): # 해당 함수 views.py으로 이동 가능.
           self.lottos = ""
           origin = list(range(1,46)) # 로또 숫자 범위
           for _ in range(0, self.num_lotto): # num_lotto개 행 데이터 생성 (로또 번호 자동 생성)
               random.shuffle(origin)
               guess = origin[:6]
               guess.sort()
               self.lottos += str(guess) +'\n' # 로또 번호 str에 6개 번호 set 추가
           self.update_date = timezone.now() # Asia/Seoul기준 시간 저장
           self.save()
    d-2. モデルの変更前にファイルを作成する
    $python manage.py makemigrations
    d-3. モデル変更の反映
    $python manage.py migrate
    e.管理者アカウントの作成(@admin.py)
    $python manage.py createsuperuser
    from django.contrib import admin
    from .models import GuessNumbers
    e-2. 管理者ページでDBを表示するには、ここに追加します.
    admin.site.register(_DB Class명_) 
    f.すべてのアプリケーションの静的ファイルにおいて
    $python manage.py collectstatic
    g.テストコード(@test.py)の作成
    from django.test import TestCase
    from .models import GuessNumbers
    class GuessNumbersTestCase(TestCase):
        def test_generate(self):
            g = GuessNumbers(name='Test numbers', text='selected numbers') 
            # g = GuessNumbers()
            # g.name = 'Test numbers'
            # text = 'selected numbers'
            g.generate() 
            print(g.update_date)
            print(g.lottos)
            self.assertTrue(len(g.lottos) > 20) # 생성된 숫자rk 20개 이상이면 True반환
    $python manage.py test
    h.アプリケーションのhtmlを生成する
    _앱명_ > templates > _앱명_ > __.html파일 생성
    _앱명_ > static > css > __.css파일 생성 # 아직 html파일에서 import는 X. 왜? 번거로우니 추후 collected css파일을 import할 것임.
    $python manage.py collectstatic
    後でhtmlファイルを作成してマージ(@.html):
    {% load static %} # html파일 상단에 위치시켜 로딩.  
    # 추가로 아래와 같이 Django template code로 python 코드를 html에서 사용 가능함. 
    {%for lotto in lottos%}
    {%if error_message%} # error_message없다면 False
  • 以上のコードを送信すると...(settings.py)でSTATIC ROOTに設定したように、staticというフォルダを作成します.
  • STATIC_URL = '/static/'
    STATIC_ROOT = os.path.join(BASE_DIR, 'static') # Base_dir에 static폴더 생성하라
    htmlファイルに
  • 上のマージ静的ファイルをインポートする場合:
  • <link rel='stylesheet' href="{% static 'css/lotto.css' %}">
  • STATIC URLとは?
    img01. hrefでは、/staticはフォルダ名ではなく、以前の設定です.pyで設定したSTATIC URL='/static/'です.
  • i.DBにインポートしたデータhtmlに表示
    (@urls.py)
    urlpatterns = [
        path('lotto/', views.index, name='index'),
    ]
    (@views.py)
    def index(request):
        lottos = GuessNumbers.objects.all() # 해당 클래스(테이블)의 모든 행 뽑아오기
        return render(request,'lotto/default.html',{'lottos':lottos})
    (@default.html)
    <p>{{ lottos }}</p> # 중괄호 2개로 불러오기
  • Djangoテンプレート付加機能
  • :各ループにbrタグ
  • を追加
    j.adminはテーブルに直接入力するのではなく,ユーザが受け取った形式で記録する.
    方法htmlフォームタグの生成
    方法Django forms
    _app name_ > forms.py 생성
    (@forms.py)
    from django import forms
    from .models import GuessNumbers
    class PostForm(forms.ModelForm):
        class Meta: # 초기회값 제외 모두 약속...
            model = GuessNumbers
            fields = ('name','text',)
    (@urls.py)
    urlpatterns = [
        path('lotto/new/',views.post, name='new_lotto'),
    ]
    (生成@form.html)
      <form method="POST" class="post-form"> <!--action='_목적지_'. but action이 없는 경우, 자기 자신의 url로 post 요청을 보냄  -->
       {% csrf_token %} <!-- CSRF (Cross Site Request Forgery) 공격 방지를 위한 Token 생성: hidden되어있고, submit할때 같이 제출됨. 로봇이 아님을 판별. -->
       {{ form.as_p }} <!-- form을 html p 태그로 감싸서 출력 -->
       <button type="submit" class="save btn btn-default">Save</button>
      </form>
    (@views.py)
    def post(request):
        # <POST 요청일 >
       if request.method == "POST":
           print(request.POST) # POST요청 후 담기는 데이터를 dict형태로 확인할 수 있음. request.POST['~~~']가 콘솔에 출력돼
           # print(request.method) # 주석을 풀면 새로운 로또 번호 생성 후 cmd에서 이 값을 확인할 수 있음
           # 사용자로부터 넘겨져 온 POST 요청 데이터를 담아 PostForm 객체 생성
           form = PostForm(request.POST) # filled form. forms.py대신 통채로 넘길 수 있음
           # 아래 방법이 싫으면, 위 주석처리된 코드 +validation code 로 대체 가능함
           if form.is_valid(): # 입력받은 form에 대한 validation 검사
                 # 사용자로부터 입력받은 form 데이터에서 추가로 수정해주려는 사항이 있을 경우 save를 보류함
               lotto = form.save(commit = False) # 최종 DB 저장은 아래 generate 함수 내부의 .save()로 처리.
               # commit=False아직 db에 반영은 안하는 상태.
               # 왜? generate()로 한번에 저장하려고...save()==generate()
               # lotto에는 저장하려했던 행을 리턴해줘.
               lotto.generate()
               return redirect('index') # urls.py path의 별명인 name='index'에 해당
               # -> 상단 from django.shortcuts import render, redirect 수정
       else: # <GET 요청일 >
           form = PostForm() # empty form
           return render(request, "lotto/form.html", {"form": form})
    k.選択した宝くじ詳細ページの生成
    予想url構造:/lotto/id/detail
    (@urls.py)
    path('lotto/<int:lottokey>/detail/', views.detail, name='detail'), #변하는 id값을 받겠다. detail함수로 같이 전달될 것임.
    (@views.py)
    def detail(request, lottokey):
        lotto = GuessNumbers.objects.get(pk=lottokey) # all이 아닌 get. pk가 lottokey인 행을 꺼내    return render(request, 'lotto/detail.html', {'lotto':lotto})
    (生成@detail.html)
       <h2>{{ lotto.text }}</h2>
       <p> by {{ lotto.name }}</p>
       <p> {{ lotto.update_date }}</p>
       <p> {{ lotto.lottos | linebreaksbr }}</p>
    (@default.html)
    /lotto/newルーティングボタンを追加&タイトルにラベルを付けて/lotto/id/detailに移動!
     <h2><a href="{% url 'detail' lottokey=lotto.pk %}">{{lotto.text}}</a></h2>
      <!--new_lotto라는 url name을 찾아서 넣겠다. url-reversing: 역으로 name으로 url 생성해줄 때 --> 
    <!--name으로 detail을 가진  url의 lottokey에 lotto.pk를 넣어줘-->
    **하드코딩: 직접 url같은 변수 적는 것
    <-> 쟝고 기능 활용
    (views.py)
    def detail(request, lottokey):
        lotto = GuessNumbers.objects.get(pk=lottokey) # all이 아닌 get. pk가 lottokey인 행을 꺼내.
        return render(request, 'lotto/detail.html', {'lotto':lotto})
  • ボタンの表情記号を追加
    http://bootstrapk.com/components/
  • <span class="glyphicon glyphicon-plus"></span>