취미삼아 배우는 프로그래밍

Django로 개인 업무(ERP) 홈페이지 만들기-2 본문

파이썬(장고)

Django로 개인 업무(ERP) 홈페이지 만들기-2

Nadure 2020. 11. 3. 23:29

 아무래도 퇴근을 늦게하고 친구들과 롤을 하다가 10시쯤 끝내고난 후 맥주를 마시면서 하는 코딩이라 그런지 크게 진도를 나가진 못했다.

 그래서 오늘은 모델을 대충이나마 코딩해서 얼추 윤곽을 잡고 진행과정을 그려보려 한다.

1. 구상2

도면을 보고 적는 형태는 이런식의 형태로 작성된다.

 

 그러면 진행은 어떻게 하는게 좋을까?

 아무래도 도면을 보고 적어야하니 제일먼저 나와야할 거는 도면리스트가 나와야 할 것 같다. 그리고 그 도면을 보고 적은 오더들에 대한 리스트가 나와야할 것이고 그 오더들에 대한 상세정보 리스트 및 코팅반에서 볼 시의 메모가 나오면 좋을것 같다.

예상진행 방향

 

2. 모델 작성

그래서 우선 모델을 작성했다.

더보기

# models.py

from django.db import models


# Create your models here.
class BaseLocationData(models.Model):
    company = models.CharField(max_length=40, verbose_name="업체명")
    location = models.CharField(max_length=40, verbose_name="현장명")

    def __str__(self):
        return self.company + " / " + self.location


class LocationData(models.Model):
    base = models.ForeignKey(BaseLocationData, on_delete=models.CASCADE)
    district = models.CharField(max_length=50, verbose_name="동")

    def __str__(self):
        return f'{self.base.company} / {self.base.location} / {self.district}'


class ItemBase(models.Model):
    filar = models.CharField(max_length=20, verbose_name="필라")
    panel = models.IntegerField(default=2400, verbose_name="패널")
    rocker = models.CharField(max_length=20, verbose_name="로커")

    def __str__(self):
        return f'{self.filar} + {str(self.panel)} + {self.rocker}'


class ItemInfo(models.Model):
    item = models.ForeignKey(ItemBase, on_delete=models.CASCADE)
    quantity = models.IntegerField(default=0, verbose_name="수량")
    partition = models.CharField(max_length=10, verbose_name="세대")

    def __str__(self):
        return f'{self.item} - {self.partition} - {self.quantity} 개'


class IntegratedInfo(models.Model):
    base_data = models.ForeignKey(LocationData, on_delete=models.CASCADE)
    items = models.ManyToManyField(ItemInfo)
    is_ordered_on = models.BooleanField(default=False, verbose_name="오더있음")
    is_completed = models.BooleanField(default=False, verbose_name="완료")
    is_order_printed = models.BooleanField(default=False, verbose_name="오더인쇄함")
    
    def __str__(self):
        return str(self.base_data)

 어떻게 보면 Json 형식으로 작성해서 진행해도 될것 같긴 한데, 아이템 조회시나 쿼리식을 통해 합계를 낼 때 조금 곤란해질 것 같아서 그냥 Json Field는 사용하지 않기로 했다. 물론 여기에 파일필드에 대한 내용을 추가해야한다. 그치만 파일필드를 넣으면 이것저것 또 더 설정을 건들게 많아지기 때문에 일단은 이것만 추가했다.

 그리고 base.html의 내용을 수정해서 틀을 조금 더 짜주었고, components 내에 footer를 추가했다. 물론 footer를 사용하기 위해서 css도 조금 첨가했다.

더보기

base.html

{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
    <!--Import materialize.css-->
    
    <link type="text/css" rel="stylesheet" href="{% static 'css/materialize.min.css' %}"  media="screen,projection"/>
    <script type="text/javascript" src="{% static 'js/materialize.min.js' %}"></script>
    <link type="text/css" rel="stylesheet" href="{% static 'css/customStyle.css' %}"/>
    <title>
        {% block title %}
        document_title
        {% endblock title%}
    </title>
</head>
<body>
    {% block nav_bar %}
        {% include "components/navbar.html" %}
    {% endblock nav_bar %}
    
    <header>
    {% block header %}
    {% endblock header %}
    </header>
    
    <main>
    {% block body %}
    {% endblock body%}
    </main>

    {% block footer %}
        {% include "components/footer.html" %}
    {% endblock footer %}

    {% block script %}
    {% endblock script %}
</body>
</html>

 

footer

<footer class="page-footer">
    <div class="container">

        <div class="row">
            <div class="col l6 s12">
                <h5 class="white-text">Footer Content</h5>
                <p class="grey-text text-lighten-4">You can use rows and columns here to organize your footer content.</p>
            </div>
        </div>

    </div>

    <div class="footer-copyright">
        <div class="container">
        © 2020 Copyright Text
        <a class="grey-text text-lighten-4 right" href="#!">More Links</a>
        </div>
    </div>
</footer>
        

 

css 추가

nav {
    background: #2f2626;
}

body {
    display: flex;
    min-height: 100vh;
    flex-direction: column;
  }

  main {
    flex: 1 0 auto;
  }

  .page-footer{
    background-color: #c5aa6a;
  }

그래서 완성한

대문 일단락

 

그리고

media 폴더와 staticfiles 폴더는 수동생성이다.

 파일을 저장할 media폴더와 staticfiles 폴더는 자동으로 생성되지 않는다. 해서, 자동으로 생성되게끔 해주면 좋을것 같아서 uvicorn이나 runserver가 참조하는 config.asgi 내에 폴더가 없을 시 생성하는 코드를 추가했다.

더보기

asgi.py

import os

import django
from channels.http import AsgiHandler
from channels.routing import ProtocolTypeRouter

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings')
django.setup()

# make folder if not exist
need_folder = ['staticfiles', 'media', ]
for folder in need_folder:
  if not os.path.exists(folder):
    os.makedirs(folder)

application = ProtocolTypeRouter({
  "http": AsgiHandler(),
  # Just HTTP for now. (We can add other protocols later.)
})

 

3. pdf 뷰어 탑재

이부분이 조금 고민이었는데, pdf뷰어를 어떻게 탑재하는게 좋을까 생각했으나, 의외로 뷰어탑재는 쉬웠다.

test.pdf

 위와 같이 test.pdf를 놔두고 아래처럼 pdf_view를 URL로 요청하면 뷰단에서 파일 자체를 리스폰해버리는데, 자동으로 뷰어를 탑재해 보여준다.

def pdf_view(request):
    try:
        return FileResponse(open('test.pdf', 'rb'), content_type='application/pdf')
    except FileNotFoundError:
        raise Http404()

이런 느낌으로

 일단 진행된 사항은 이렇다. 생각보다 시작은 수월한데, 일단 만들어봐야 알듯 하다.

 

Comments