Django DB 예제

kangjuju·2023년 4월 20일
0

Django

목록 보기
4/6

ForeignKey [새로 생성]

외래키를 사용하기위해 테이블을 2개 생성하고, 한 테이블에
models.ForeignKey 를 지정했다.

models

class Maker(models.Model):
    mname = models.CharField(max_length=10)
    mtel = models.CharField(max_length=20)
    maddr = models.CharField(max_length=50)
    
    class Meta:
        ordering=('-id',)
        
    def __str__(self): 
        return self.mname
    
class Product(models.Model):
    pname = models.CharField(max_length=10)
    pprice = models.IntegerField()
    pmaker_name = models.ForeignKey(Maker,on_delete=models.CASCADE) 
    #외래키. Maker id PK 참조

def __str__(self): return self.mname 로 아래의 selector를 생성시켰다.

  • get링크 클릭으로 조건에 의한 검색결과를 페이지에 다시표시했다.
def List3(request):
    mid = request.GET['id']
    #where 조건 사용하여 테이블 검색
    products = Product.objects.filter(pmaker_name=mid)
    return render(request, 'list2.html',{'products':products,'pcount':len(products)})
 

기존 데이터 이용

  • 기존에 짜여져있는 테이블을 이용해보자.
  1. models.py 생성시 직접 작성하지 않고 prompt에서 명령어로 생성한다.
    python manage.py inspectdb > 이름.py
    settings.py에서 명시한 DB 내용을 근거로 내용을 전부 찾아 .py파일로 자동작성한다.

  2. 생성된 .py파일에서 필요한 테이블 Class를 복사하여 models.py에 붙여넣는다.

  3. 생성된 .py는 삭제하고, 프로젝트를 Migration한다.

views.py

  • 기존 데이터를 이용시 SQL문을 직접 사용하여 출력했다.
def ListFunc(request):
    if request.method == 'GET':
        #select : SQL문 사용
        sql = "select * from sangdata"
        conn = MySQLdb.connect(**config)
        cursor = conn.cursor()
        cursor.execute(sql)
        datas = cursor.fetchall()
        print(datas)
        return render(request,'list.html',{'sangpums':datas})
    else:
        pass   

django에서는 ORM 사용을 권장한다. 하지만 쿼리문이 복잡해질땐 부득이하게 SQL을 사용해야 할때가 있는데, 이때 반환되는 datas의 타입의 튜플 속 튜플.

html에서 매핑하여 출력시 타입 쿼리셋과 다름을 유의해야한다. 아래 코드에서 인덱스로 튜플을 접근한 것을 확인했다.

		{%for s in sangpums%}
			<tr>
				<td>{{s.0}}</td>
				<td>{{s.1}}</td>
				<td>{{s.2}}</td>
				<td>{{s.3}}</td>
			</tr>
		{%endfor%}

이어서 이 리스트를 페이징처리로 변환해보자

페이징처리 1

from django.core.paginator import Paginator,PageNotAnInteger,EmptyPage

장고에서는 페이징처리를 위해 위의 모듈을 지원한다.
위의 전체리스트 출력 객체 (datas)를 페이징 처리하는 코드이다.

        #페이징 o
        datas = Sangdata.objects.all().order_by("-code")
        paginator = Paginator(object_list=datas,per_page=5)
        try:
            page = request.GET.get('page')
        except:
            page=1
    
        try:
            data = paginator.page(page)
        except PageNotAnInteger: #페이지가 정수가 아닌 경우
            data = paginator.page(1)
        except EmptyPage: #비어있는경우
            data = paginator.page(paginator.num_pages())
            
        #개별 페이지 번호 표시용
        allPage = range(paginator.num_pages+1)
        print(allPage)
        return render(request,'list.html',{'sangpums':data,'allpage':allPage})

개별 페이지 번호를 html에서 표시하기 위해 range로 수열을 만들어 넘겼다.

<!-- 페이징 -->
		<tr>
			<td colspan="5">
			{% if sangpums.paginator.num_pages > 1 %}
				<div>
				{% for p in allpage %}
					<!-- 현재페이지는 링크표시X -->
					{% if p > 0 %}
						{% if p == sangpums.number %} 
						[{{p}}]
						{% elif p != sangpums.number %}
						<a href="/sangpum/list?page={{p}}">[{{p}}]</a>
						{% endif %}
					{% endif %}
				{% endfor %}
				</div>
			{% endif %}
			</td>
		</tr>

html파일에서 페이징 처리 링크를 만드는 코드이다.

  • if sangpums.paginator.num_pages > 1 : 페이징처리 할 필요가 있는지에 대한 여부 확인
  • for p in allpage : range로 넘어온 페이지 수열의 사이즈를 for문으로 반복한다. range(1,4) : 1,2,3

페이징 처리2

또다른 방법. 위의 방법과 같이 사용해도 된다.

<!-- 방법2 -->
{% 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 %}
<!-- 현재페이지 / 전체페이지-->
(페이지 : {{sangpums.number}} / {{sangpums.paginator.num_pages}})
  • previous/next_page_number : 다음, 이전페이지 번호


insert

  • 이미 등록되어 있는지에 대한 체크는 try를 사용했다.
def InsertFunc(request):
    if request.method == 'GET':
        maxcode = Sangdata.objects.aggregate(Max('code'))['code__max']
        return render(request,'insert.html',{'maxcode':maxcode+1}) 
    elif request.method == 'POST':
        #신상코드번호 유무 확인 후 insert반영
        code = request.POST.get('code')
        try:
            Sangdata.objects.get(code=request.POST.get('code'))
            return render(request, 'insert.html',{'msg':'이미 등록된 번호입니다'})
        except:
            Sangdata(
                code = request.POST['code'],
                sang = request.POST['sang'],
                su = request.POST['su'],
                dan = request.POST['dan']            
            ).save()
        return HttpResponseRedirect('/sangpum/list'

delete

  • 삭제링크
<script type="text/javascript">
function func(arg){
	let result = confirm('code : '+arg +'번을 삭제할까요?')
	if(result){
		document.getElementById(arg).submit();
	}else{
		return;
	}
}
</script>
 <!-- 아이디마다 폼을 지정하기 위해 id를 code로 -->
<form action="/sangpum/delete" id="{{s.code}}" name="frm" method="get" style="display:inline;">
	<input type="hidden" name="code" value="{{s.code}}">
	<!-- a링크 기능없애고 func사용 -->
	<a href="javascript:void(0); onclick=func({{s.code}})">삭제</a>
</form>
def DeleteFunc(request):
    if request.method == 'GET':
        upRec = Sangdata.objects.get(code=request.GET['code']) #기존 데이터 가져옴
        upRec.delete()
        return HttpResponseRedirect('/sangpum/list') #삭제 후 리스트로
    else:
        pass

0개의 댓글