본문 바로가기

Django

django8 - DB, 표, CRUD, 페이징

 

프로젝트 생성 과정

 

-기존 db 연동하기
anaconda prompt
python manage.py inspectdb > abc.py
type abc.py
생성된 abc.py에서 sangdata class 복사해서 models에 붙여넣기
사용을 다 한 abc.py는 삭제

urls 작성
views 함수 작성, import MySQLdb, config 작성
templates 작성

 

 

프로젝트 예시 코드

 

settings.py

"""
Django settings for django8_sangdata project.

Generated by 'django-admin startproject' using Django 4.1.2.

For more information on this file, see
https://docs.djangoproject.com/en/4.1/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/4.1/ref/settings/
"""

from pathlib import Path

# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/4.1/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = "django-insecure-h%7@pzbm%gp__aqhf!o)px88u1uf9+a+!yj8@2mn7f&80z+p&h"

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = []


# Application definition

INSTALLED_APPS = [
    "django.contrib.admin",
    "django.contrib.auth",
    "django.contrib.contenttypes",
    "django.contrib.sessions",
    "django.contrib.messages",
    "django.contrib.staticfiles",
    "mysangpum",
]

MIDDLEWARE = [
    "django.middleware.security.SecurityMiddleware",
    "django.contrib.sessions.middleware.SessionMiddleware",
    "django.middleware.common.CommonMiddleware",
    "django.middleware.csrf.CsrfViewMiddleware",
    "django.contrib.auth.middleware.AuthenticationMiddleware",
    "django.contrib.messages.middleware.MessageMiddleware",
    "django.middleware.clickjacking.XFrameOptionsMiddleware",
]

ROOT_URLCONF = "django8_sangdata.urls"

TEMPLATES = [
    {
        "BACKEND": "django.template.backends.django.DjangoTemplates",
        "DIRS": [],
        "APP_DIRS": True,
        "OPTIONS": {
            "context_processors": [
                "django.template.context_processors.debug",
                "django.template.context_processors.request",
                "django.contrib.auth.context_processors.auth",
                "django.contrib.messages.context_processors.messages",
            ],
        },
    },
]

WSGI_APPLICATION = "django8_sangdata.wsgi.application"


# Database
# https://docs.djangoproject.com/en/4.1/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql', 
        'NAME': 'test',                # DB명 : db는 미리 작성되어 있어야 함.       
        'USER': 'root',                # 계정명 
        'PASSWORD': '123',             # 계정 암호           
        'HOST': '127.0.0.1',           # DB가 설치된 컴의 ip          
        'PORT': '3306',                # DBMS의 port 번호     
    }
}


# Password validation
# https://docs.djangoproject.com/en/4.1/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator",
    },
    {"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",},
    {"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator",},
    {"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",},
]


# Internationalization
# https://docs.djangoproject.com/en/4.1/topics/i18n/

LANGUAGE_CODE = "en-us"

TIME_ZONE = "UTC"

USE_I18N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/4.1/howto/static-files/

STATIC_URL = "static/"

# Default primary key field type
# https://docs.djangoproject.com/en/4.1/ref/settings/#default-auto-field

DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"

 

 

models.py

from django.db import models

# Create your models here.
class Sangdata(models.Model):
    code = models.IntegerField(primary_key=True)
    sang = models.CharField(max_length=20, blank=True, null=True)
    su = models.IntegerField(blank=True, null=True)
    dan = models.IntegerField(blank=True, null=True)

    class Meta:
        managed = False
        db_table = 'sangdata'

 

 

urls.py

from django.contrib import admin
from django.urls import path
from mysangpum import views
from django.urls.conf import include

urlpatterns = [
    path("admin/", admin.site.urls),
    
    path('',views.MainFunc),
    
    path('sangpum/', include('mysangpum.urls'))
]

 

 

urls.py (mysangpum)

from django.urls import path
from mysangpum import views

urlpatterns = [
    path('list', views.ListFunc),
    path('insert', views.InsertFunc),
    path('insertok', views.InsertOkFunc),
    path('update', views.UpdateFunc),
    path('updateok', views.UpdateOkFunc),
    path('delete', views.DeleteFunc),
 
]

 

 

views.py

from django.shortcuts import render
import MySQLdb
from mysangpum.models import Sangdata
from django.http.response import HttpResponseRedirect
from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage

# sangdata table과 연동
config = {
    'host':'127.0.0.1',
    'user':'root',
    'password':'123',
    'database':'test',
    'port':3306,
    'charset':'utf8',
    'use_unicode':True
}

# Create your views here.
def MainFunc(request):
    return render(request, 'main.html')

def ListFunc(request):
    # SQL문 직접 사용  # 반환 : tuple
    """
    sql = 'select * from sangdata'
    conn = MySQLdb.connect(**config)
    cursor = conn.cursor()
    cursor.execute(sql)
    datas = cursor.fetchall()
    print(datas, type(datas))
    """

    # ORM   # 반환 : QuerySet
    """
    datas = Sangdata.objects.all()
    """
    """
    return render(request, 'list.html', {'sangpums':datas})
    """
    
    # 내림차순, 페이지 나누기
    datas = Sangdata.objects.all().order_by('-code')
    paginator = Paginator(datas, 5)
    
    try:
        page = request.GET.get('page')
    except:
        # 넘어온 page 값이 없다면 1페이지로 시작
        page = 1
    
    try:
        # page에 해당되는 자료를 읽기
        data = paginator.page(page)
    except PageNotAnInteger:
        data = paginator.page(1)
    except EmptyPage:
        data = paginator.page(paginator.num_pages())
    
    # 낱개 페이지 번호를 출력한다면 ...
    allpage = range(paginator.num_pages + 1)  # (0, 4 + 1)
    
    return render(request, 'list2.html', {'sangpums':data, 'allpage':allpage})


def InsertFunc(request):
    return render(request, 'insert.html')

def InsertOkFunc(request):
    if request.method == 'POST':
        # 신상품 code 등록 여부 판단
        try:
            Sangdata.objects.get(code=request.POST.get('code'))
            return render(request, 'insert.html', {'msg':'이미 등록된 code 입니다.'})
        except Exception as e:
            # 입력 자료의 code가 등록된 숫자가 아니므로 insert 작업을 진행
            Sangdata(
                code=request.POST.get('code'),
                sang=request.POST.get('sang'),
                su=request.POST.get('su'),
                dan=request.POST.get('dan'),
            ).save()
        
        return HttpResponseRedirect("/sangpum/list")  # 추가 후 목록보기

def UpdateFunc(request):
    data = Sangdata.objects.get(code=request.GET.get('code'))
    return render(request, 'update.html', {'sang_one':data})


def UpdateOkFunc(request):
    if request.method == 'POST':
        upRec = Sangdata.objects.get(code=request.POST.get('code'))
        upRec.code = request.POST.get('code')
        upRec.sang = request.POST.get('sang')
        upRec.su = request.POST.get('su')
        upRec.dan = request.POST.get('dan')
        upRec.save()

    return HttpResponseRedirect("/sangpum/list")  # 수정 후 목록보기

def DeleteFunc(request):
    delRec = Sangdata.objects.get(code=request.GET.get('code'))
    delRec.delete()
    return HttpResponseRedirect("/sangpum/list")  # 삭제 후 목록보기

 

 

main.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
메인 페이지<p/>
직원 고객 부서 <a href="sangpum/list">상품</a>
</body>
</html>

 

 

list.html - 사용하지 않았다.

페이징 처리 없는 표, 예시에서는 주석처리하고 사용하지 않았다.

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
** 상품 정보 **<p/>
<div style="width:80%; text-align:right;">
	<a href="/sangpum/insert">상품 추가</a>
</div>

<table border="1" style="width:80%">
	<tr style="background-color: orange">
		<th>코드</th><th>상품명</th><th>수량</th><th>단가</th><th>기타</th>
	</tr>
	{% if sangpums %}
	{% for s in sangpums %}
	<tr>
		<!-- select문의 결과를 출력할 때는 tuple 이므로 s.0,..사용 -->
		<td>{{s.code}}</td> 
		<td>{{s.sang}}</td>
		<td>{{s.su}}</td>
		<td>{{s.dan}}</td>
		<td>
			<a href="/sangpum/update?code={{s.code}}">수정</a> 
			<a href="/sangpum/delete?code={{s.code}}">삭제</a> 
		</td>
	</tr>
	{% endfor %}
	{% else %}
	<tr>
		<td colspan="5">자료 없음</td>
	</tr>
	{% endif %}
</table>
</body>
</html>

 

 

list2.html

페이징 처리가 된 표

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script type="text/javascript">
function func(arg){
	//alert(arg);
	let result = confirm("정말 삭제할까요?");
	if(result){
		document.getElementById(arg).submit();
	}
}
</script>
</head>
<body>
** 상품 정보 **<p/>
<div style="width:80%; text-align:right;">
	<a href="/sangpum/insert">상품 추가</a>
</div>

<table border="1" style="width:80%">
	<tr style="background-color: orange">
		<th>코드</th><th>상품명</th><th>수량</th><th>단가</th><th>기타</th>
	</tr>
	{% if sangpums %}
	{% for s in sangpums %}
	<tr>
		<!-- select문의 결과를 출력할 때는 tuple 이므로 s.0,..사용 -->
		<td>{{s.code}}</td> 
		<td>{{s.sang}}</td>
		<td>{{s.su}}</td>
		<td>{{s.dan}}</td>
		<td>
			<a href="/sangpum/update?code={{s.code}}">수정</a> /
			<!-- 삭제 확인 메시지를 못보여준다 
			<a href="/sangpum/delete?code={{s.code}}">삭제</a> 
			-->
			<form action="/sangpum/delete" name="frm" method="get" 
					id ="{{s.code}}" style="display: inline">
				<input type="hidden" name="code" value="{{s.code}}">
				<a href="javascript:void(0); onclick=func({{s.code}})">삭제</a>			
			</form>
		</td>
	</tr>
	{% endfor %}
	
	<!-- 페이징 처리 -->
	<tr>
		<td colspan="5">
		{% if sangpums.paginator.num_pages > 1 %}
			<div>
			{% if sangpums.has_previous %}
				<a href="/sangpum/list?page={{sangpums.previous_page_number}}">&laquo;이전</a>
			{% endif %}
			{% if sangpums.has_next %}
				<a href="/sangpum/list?page={{sangpums.next_page_number}}">다음&raquo;</a>
			{% endif %}
			&nbsp;&nbsp;
			(페이지:{{sangpums.number}} / {{sangpums.paginator.num_pages}})
			<hr>
			{% for p in allpage %}
				{% if p > 0 %}
					{% if p == sangpums.number %}  <!-- 현재 페이지는 링크에서 제외 -->
						[{{p}}]
					{% else %}
						<a href="/sangpum/list?page={{p}}">[{{p}}]</a>
					{% endif %}
				{% endif %}
			{% endfor %}
			</div>

		{% endif %}
		</td>
	</tr>
	
	{% else %}
	<tr>
		<td colspan="5">자료 없음</td>
	</tr>
	{% endif %}
</table>
</body>
</html>

 

 

insert.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script type="text/javascript">
window.onload = function(){
	document.querySelector("#btnSubmit").onclick = function(){
		chkData();
	}
}

function chkData(){
	// alert('a');
	if(frm.code.value === "" || frm.sang.value === ""){
		alert("입력자료를 모두 채우시오");
		return;
	}
	
	// su, dan은 생략
	frm.submit();
}
</script>
</head>
<body>
<h3>* 상품 추가 *</h3>
<form action="/sangpum/insertok" name="frm" method="post">{% csrf_token %}
<table style="width:80%">
	<tr>
		<td>코드 : </td>
		<td><input type="text" name="code"><span style="color:red">{{msg}}</span></td>
	</tr>
	<tr>
		<td>품명 : </td>
		<td><input type="text" name="sang"></td>
	</tr>
	<tr>
		<td>수량 : </td>
		<td><input type="text" name="su"></td>
	</tr>
	<tr>
		<td>단가 : </td>
		<td><input type="text" name="dan"></td>
	</tr>
	<tr>
		<td colspan="2">
			<input type="button" value="저장" id="btnSubmit">
		</td>
	</tr>
</table>
</form>
</body>
</html>

 

 

update.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h2>* 상품 수정 *</h2>
<form action="/sangpum/updateok" method="post">{% csrf_token %}
<input type="hidden" name="code" value="{{sang_one.code}}">
<table style="width:80%">
	<tr>
		<td>코드 : </td>
		<td>{{sang_one.code}}</td>
	</tr>
	<tr>
		<td>품명 : </td>
		<td><input type="text" name="sang" value="{{sang_one.sang}}"></td>
	</tr>
	<tr>
		<td>수량 : </td>
		<td><input type="text" name="su" value="{{sang_one.su}}"></td>
	</tr>
	<tr>
		<td>단가 : </td>
		<td><input type="text" name="dan" value="{{sang_one.dan}}"></td>
	</tr>
	<tr>
		<td colspan="2">
			<input type="submit" value="수정하기">
			<input type="button" value="이전화면" onclick="history.back()">
		</td>
	</tr>
	
</table>
</form>
</body>
</html>

 

'Django' 카테고리의 다른 글

django9 - DB, 게시판, 댓글  (0) 2022.10.19
django project 과정 정리  (0) 2022.10.18
django7 - DB, multi-table (제조사, 상품 관리)  (0) 2022.10.18
django6 - Maria DB (방명록)  (0) 2022.10.17
django5 - DB  (0) 2022.10.17