=> HttpResponse(json.dumps(context), content_type="application/json") : context를 dict 타입에서 str로 변환 후
json형식의 str을 send.
12. Ajax + DB
: ajax 요청 시 DB의 직원 테이블 data 조회하여 출력하기.
= django_test11_ajax
=> create application - myajax
* settings
...
INSTALLED_APPS = [
...
'myajax',
]
...
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 번호
}
}
...
=> application 연결.
=> DB 설정
* anaconda prompt
cd C:\work\psou\django_test11_ajax
python manage.py inspectdb > aaa.py
* models
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'
=> aaa.py의 사용할 table을 models.py에 복사 붙여넣기. (제작된 Table을 Django 형식으로 자동 생성)
Make migrations - myajax
Migrate
* urls
from django.contrib import admin
from django.urls import path
from myajax import views
urlpatterns = [
path('admin/', admin.site.urls),
path('', views.MainFunc),
path('list', views.ListFunc),
path('calldb', views.ListDbFunc),
]
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
Article 자료 보기 - Djang template language 사용 <br>
{% if articles.count %}
{% for a in articles %}
<b>{{a.code}}</b> {{a.name}} {{a.price}} {{a.pub_date}}<br>
{% endfor %}
{% else %}
<p>자료가 없습니다.</p>
{% endif %}
</body>
</html>
{% if 조건 %}
{% else %}
{% endif %}
=> if 문
{% for 변수 in 자료 %}
{% endfor %}
=> for 문
6. where, group by
* settings
INSTALLED_APPS = [
...
'sql_app',
]
=> application연결
* models
from django.db import models
# Create your models here.
class Profile(models.Model):
name = models.CharField(max_length = 10)
age = models.IntegerField()
=> DB 테이블 생성
- explore 창 - 프로젝트 오른쪽 클릭 - Django - Create application - sqlapp
-explore 창 - 프로젝트 오른쪽 클릭 - Django - Make Migrations - sqlapp
-explore 창 - 프로젝트 오른쪽 클릭 - Django - Migrate
해당 프로젝트 cmd 창 : python manage.py createsuperuser
* admin
from django.contrib import admin
from sql_app.models import Profile
# Register your models here.
class ProfileAdmin(admin.ModelAdmin):
list_display = ('id', 'name', 'age')
admin.site.register(Profile, ProfileAdmin)
=> 테이블과 admin 계정 연결.
- http://127.0.0.1/admin/ 접속 후 login
- table data 입력
* urls
from django.contrib import admin
from django.urls import path
from sql_app import views
urlpatterns = [
path('admin/', admin.site.urls),
path('', views.IndexFunc),
path('calldata/', views.CallFunc),
]
=> url과 views 연결
* views
from django.shortcuts import render
from sql_app.models import Profile
from django.db.models.aggregates import Avg, Count, Max, Min, Sum
# Create your views here.
def IndexFunc(request):
return render(request, 'index.html')
def CallFunc(request):
profile_list = Profile.objects.all() # 전체 자료 list로 리턴
for row in profile_list.values_list(): # 리스트의 값들 리턴
print(row)
print(Profile.objects.aggregate(Avg('age'))) # select avg(age) from Profile
print(Profile.objects.aggregate(Max('age')))
print(Profile.objects.aggregate(Sum('age')))
print(Profile.objects.aggregate(Count('age')))
print(len(profile_list))
print(Profile.objects.filter(name = '홍길동').aggregate(Avg('age'))) # where 조건
qs = Profile.objects.values('name').annotate(Avg('age')) # group 별 작업
for r in qs:
print(r)
pro_list = []
for pro in profile_list:
pro_dict ={}
pro_dict['name'] = pro.name
pro_dict['age'] = pro.age
pro_list.append(pro_dict)
print(pro_list)
# [{'key1':value1, 'key2':value2, ... }, {'key1':value1, 'key2':value2, ... }, ... ]
context = {'pro_list':pro_list}
return render(request, 'list.html', context)
QuerySet 타입.values_list() : value list 리턴
테이블명.objects.aggregate(Avg('칼럼명')) : select avg(칼럼명) from 테이블명
테이블명.objects.aggregate(Max('칼럼명')) : select max(칼럼명) from 테이블명
테이블명.objects.aggregate(Sum('칼럼명')) : select sum(칼럼명) from 테이블명
테이블명.objects.aggregate(Count('칼럼명')) : select count(칼럼명) from 테이블명
테이블명.objects.filter(칼럼명=값) : select * from 테이블명 where 칼럼명 = 값
테이블명.objects.values('칼럼명').annotate(Avg('칼럼명')) : select avg(칼럼명) from 테이블명 group by 칼럼명
* index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
메인(QuerySet Test)<br>
<a href="calldata/">db 자료를 읽어 dict type으로 출력</a>
<br>
<a href="admin/">장고가 지원하는 관리자 창</a>
</body>
</html>
* list.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
자료 보기</p>
{{pro_list}}
</body>
</html>
7. 원격 DB
= django_test06_mariadb
DB 접속하여 DataBase 생성
explore 창 - 프로젝트 오른쪽 클릭 - Django - Create application - myguset
* settings
INSTALLED_APPS = [
...
'myguest',
]
...
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'yourdb', # DB명 : db는 미리 작성되어 있어야 함.
'USER': 'root', # 계정명
'PASSWORD': '123', # 계정 암호
'HOST': '127.0.0.1', # DB가 설치된 컴의 ip
'PORT': '3306', # DBMS의 port 번호
}
}
DATABASES = { 'default': {
django.db.backends.mysql',
'NAME': 'database명', # DB명 : db는 미리 작성되어 있어야 함. 'USER': 'root', # 계정명 'PASSWORD': '123', # 계정 암호 'HOST': '127.0.0.1', # DB가 설치된 pc의 ip 'PORT': '3306', # DBMS의 port 번호 } }
=> remote DB 연결 정보.
* models
from django.db import models
# Create your models here.
class Guest(models.Model):
myno = models.AutoField(auto_created = True, primary_key = True)
title = models.CharField(max_length=50)
content = models.TextField()
regdate = models.DateTimeField()
def __str__(self):
return self.title
class Meta:
ordering = ('-title', 'id') # title이 같으면 id로 정렬
ordering = ('-id',) # tuple 타입만 가능.
칼럼명 = models.AutoField(auto_created = True, primary_key = True) : 자동 증가하는 index 기본키 생성.
칼럼명 = models.TextField() : text타입 칼럼 생성
class Meta:
ordering = ('-칼럼명1', '칼럼명2')
=> 칼럼명1 기준 desc 정렬 후 데이터가 같은 정보에 대해 칼럼명2 기준 asc정렬.
- explore 창 - 프로젝트 오른쪽 클릭 - Django - Make Migrations -myguset
- explore 창 - 프로젝트 오른쪽 클릭 - Django - Migrate
* admin
from django.contrib import admin
from myguest.models import Guest
# Register your models here.
class GuestAdmin(admin.ModelAdmin):
list_display = ('id', 'title', 'content', 'regdate')
admin.site.register(Guest, GuestAdmin)
=> 테이블과 admin계정 연결.
* admin계정 id 생성 및 table data 입력
* urls(django_test06_mariadb)
from django.contrib import admin
from django.urls import path
from myguest import views
from django.urls.conf import include
urlpatterns = [
path('admin/', admin.site.urls),
path('', views.MainFunc),
path('guest/', include("myguest.urls")),
]
=> url과 views 연결
* urls(myguest)
from django.urls import path
from myguest import views
urlpatterns = [
path('', views.ListFunc),
path('insert', views.InsertFunc),
path('insertok/', views.InsertOkFunc),
]
=> url과 views 연결
* views
from django.shortcuts import render
from myguest.models import Guest
from datetime import datetime
from django.http.response import HttpResponseRedirect
# Create your views here.
def MainFunc(request):
return render(request, 'main.html')
def ListFunc(request):
gdata = Guest.objects.all() # 전체 자료 읽기
gdata = Guest.objects.all().order_by('title') # order_by ascending
gdata = Guest.objects.all().order_by('-title') # order_by descending
gdata = Guest.objects.all().order_by('-id')[0:2] # 정렬 후 슬라이싱
print('gdata type : ', type(gdata)) # <class 'django.db.models.query.QuerySet'>
return render(request, 'list.html', {'gdatas' : gdata})
def InsertFunc(request):
return render(request, 'insert.html')
def InsertOkFunc(request):
if request.method =='POST':
print(request.POST.get('title'))
print(request.POST['title'])
# 입력자료로 테이블에 저장 : ORM
Guest(
title = request.POST.get('title'),
content = request.POST.get('content'),
regdate = datetime.now()
).save()
return HttpResponseRedirect('/guest') # 추가후 목록 보기
'''
# 수정
g = Guest.objects.get(id=1)
g.title = "하하"
g.content = '하하하'
g.save()
# 삭제
g = Guest.objects.get(id=1)
g.delete
'''
테이블명.objects.all().order_by('칼럼명') : order by 칼럼명 asc
테이블명.objects.all().order_by('-칼럼명') : order by 칼럼명 desc
...
INSTALLED_APPS = [
...
'mysangpum',
]
...
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 번호
}
}
...
TIME_ZONE = 'Asia/Seoul'
USE_TZ = False
TIME_ZONE = 'Asia/Seoul' USE_TZ = False
=> admin 페이지에 표시되는 시간은 기본적으로 UTC(UTC+9)이므로, 입력을 해도 9시간 전으로 표시된다. 이에 표시되는 시간과 실제 DB에 입력되는 시간을 모두 Local시간(UTC)으로 맞춰 주어야 한다
* remote DB의 데이터를 Django 형식으로 불러오기
anconda 접속
cd C:\work\psou\django_test08_sangdata
python manage.py inspectdb > abc.py
=> 이미 생성되어 있는 DB를 django 형식으로 abc.py에 코드 자동 작성.
* models
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'
=> abc.py의 sangdata table 내용 입력
- Django - Make migrations - mysangpum
- Django - Migrate
* urls(django_test08_sangdata)
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')), # 요청 위임
]
def ListFunc(request):
...
# 페이지 나누기 처리 - Paginator 클래스
datas = Sangdata.objects.all().order_by('-code') # order by code desc
paginator = Paginator(datas, 3) # 페이지당 출력 행수를 생성자로 전달
try:
page = request.GET.get('page') # page 값을 read
except:
page = 1 # page 값이 없을 경우 1 page 출력
try:
data = paginator.page(page)
except PageNotAnInteger: # page가 숫자가 아닐 경우
data = paginator.page(1)
except EmptyPage:
data = paginator.page(paginator.num_pages()) # 현재 페이지 출력
# 클라이언트 화면에 개별 페이지 번호 표시용
allPage = range(paginator.num_pages + 1)
#print('allPage : ', allPage) # range(0, 5)
return render(request, 'list2.html', {'sangpums':data, 'allPage':allPage})
paginator = Paginator(데이터, 출력행수) : 객체 생성. 페이지당 출력 행수를 생성자로 전달
paginator.page(출력페이지) : 나눠진 페이지에서 출력할 페이지 입력.
paginator.num_pages : 총페이지 수
* list2.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>
<script type="text/javascript">
function func(){
//alert("aa");
let result = confirm("정말 삭제 할까요?")
if(result){
frm.submit();
}
}
</script>
</head>
<body>
<h2>상품자료</h2>
<div style="width:80%; text-align:right;">
<a href="/sangpum/insert">상품 추가</a>
</div>
<table class="table" style="width:80%;">
<tr>
<th>code</th><th>상품</th><th>수량</th><th>단가</th><th>기타</th>
</tr>
{% if sangpums %}
{% for s in sangpums%}
<tr>
<!-- <td>{{s.0}}</td> -->
<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> /
<!-- 삭제 전에 묻는 작업이 필요 -->
<form action="/sangpum/delete" name="frm" method="get" style="display:inline;">
<input type="hidden" name="code" value="{{s.code}}">
<a href="javascript:void(0); onclick=func()">삭제</a>
</form>
</td>
</tr>
{% endfor%}
<!-- paging -->
<tr>
<td colspan="5">
{% if sangpums.paginator.num_pages > 1 %}
<ul class="pager">
{% if sangpums.has_previous %}
<li class="previous"><a href="/sangpum/list?page={{sangpums.previous_page_number}}">Previous</a></li>
<!-- <li><a href="/sangpum/list?page={{sangpums.previous_page_number}}">«이전</a></li> -->
{% endif %}
{% if sangpums.has_next %}
<li class="next"><a href="/sangpum/list?page={{sangpums.next_page_number}}">Next</a></li>
<!-- <li><a href="/sangpum/list?page={{sangpums.next_page_number}}">다음»</a></li> -->
{% endif %}
<li>(페이지 : {{sangpums.number}} / {{sangpums.paginator.num_pages}})</li>
</ul>
<hr>
{% for p in allPage%}
{% if p > 0 %}
{% if p == sangpums.number %}
[{{p}}]
{% elif p != sangpums.number %}
<a href="/sangpum/list?page={{p}}]"> {{p}} </a>
{% endif %}
{% endif %}
{% endfor%}
{% endif %}
</td>
</tr>
{% else %}
<tr>
<td colspan="5">자료가 없습니다.</td>
</tr>
{% endif%}
</table>
</body>
</html>
data.number : 현재페이지
data.paginator.num_pages : 총 페이지
④ 게시물 추가
* views
def InsertFunc(request):
return render(request, 'insert.html')
def InsertokFunc(request):
if request.method == 'POST':
code = request.POST.get("code")
#print('code : ', code)
# 새로운 상품 code 유무 검증 작업 후 insert 진행
try:
Sangdata.objects.get(code=code) # where
#print('code 있음')
return render(request, 'insert.html', {'msg':'이미 등록된 번호입니다.'})
except Exception as e:
#print('code 없음')
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 DeleteFunc(request):
delRec = Sangdata.objects.get(code=request.GET.get('code'))
delRec.delete()
return HttpResponseRedirect('/sangpum/list') # 삭제 후 목록 보기
- Function views 방법 - Class-base views 방법 - Including another URL conf 방법
= django_test2
* settings.py
INSTALLED_APPS = [
'gpapp',
]
* urls.py(django_test2)
from django.contrib import admin
from django.urls import path
from gpapp import views
from gpapp.views import CallView
from django.urls.conf import include
urlpatterns = [
path('admin/', admin.site.urls),
path('', views.MainFunc, name='MainFunc'), # Function views 방법
path('gpapp/callget', CallView.as_view()), # Class-base views 방법
path('sangpum/', include('gpapp.urls')), # Including another URLconf 방법
]
path('url명', views.메소드명) : 해당 url이 수신 시 view.py의 해당 메소드 실행.
path('url명', 클래스명.as_view()) : 해당 url 수신 시 해당 클래스 실행.
path('url명', include('application명.urls')) : 해당 url이 포함됨 url 수신 시 해당 application의 urls 파일에서 나머지 url 연결하여 실행.
* views
from django.shortcuts import render
from django.views.generic.base import TemplateView
# Create your views here.
def MainFunc(request):
return render(request, 'index.html')
class CallView(TemplateView):
template_name = "callget.html"
def InsertFunc(request):
#return render(request, "insert.html") # get/post 모두 처리
if request.method == 'GET':
print('GET 요청')
return render(request, "insert.html")
elif request.method == 'POST':
print('POST 요청')
name = request.POST.get("name")
name = request.POST.["name"]
return render(request,"list.html", {"name":name})
else:
print('요청 에러')
def SelectFunc(request):
pass
def UpdateFunc(request):
pass
# 메인 urls가 각 app에 처리 위임
from django.urls import path
from gpapp import views
urlpatterns = [
path('insert', views.InsertFunc),
path('select', views.SelectFunc),
path('update', views.UpdateFunc),
]
value = request.session.get('key값'): session에 key값에 value값 get.
value = request.session['key값']: session에 key값에 value값 get.
request.session.set_expiry(초) : session 유효 시간 초 단위로 설정.
* main.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
메인화면<p/>
session 연습 : 세션이란 일정시간 동안 같은 사용자로 부터 들어오는 여러 가지 요구들을 하나의 상태를 보고 그 상태를 일정하게 유지 시킨 기술.
클라이언트와 서버 사이의 연결이 유지되는 것 처럼 하기 위해 클라이언트의 정보를 서버 컴퓨터의 일정 공간을 확보해 정보를 기억시킬 수 있다.
<br>
<a href="/setos/">운영체제 선택하기</a>
</body>
</html>