티스토리 뷰

Template 확장

입력 form 만들기

새글 쓰기/수정/삭제

 

Server Test : git transmission : 생략

 

INTRO

* local / server terminal 구분 : [macOS] / [Raspi]

** venv 표기 : (pyERP)

 

Raspi : server

- Python : 3.7.3

- django : 3.2

 

macOS : local-dev

- Python : 3.9.4

- django : 3.2

 

-------------------- platform review -------------------- 

login 후

home_welcome.html

구성 : head / navbar_main / body_top / navbar_sub / body_bottom / footer

프레임(상단) : user_info

프레임(하단) : notice_list

공지사항 제목 클릭 : notice 이동

새글쓰기 클릭 : notice new

수정하기 클릭 : notice new

삭제하기 클릭 : notice delete, 미리보기 없음

 

-------------------- platform review -------------------- 

 

 

1번 notice part를 이해하면 2번, 3번은 유사한 포멧으로 완성 가능

1. home: notice

 다음과 같이 models/forms/urls/views/templates로 구성

 --> models, forms, (admin), urls, views, templates(route : 공통부분, navbar부분 ), templates(home), css

2. sales

3. production

 

macOS 

Home : notice

- models : 조회수 카운팅 추가 및 구현

{SublimeText} home/models.py

from django.db import models
from django.conf import settings


class Notice(models.Model):
	notice_id  = models.AutoField(primary_key=True)
	author     = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, null=False)
	title      = models.CharField('제목', max_length=128, null=False)
	article    = models.TextField('내용', null=True)
	created_at = models.DateTimeField(auto_now_add=True)
	updated_at = models.DateTimeField(auto_now=True)
	hit        = models.PositiveIntegerField(default=0)
	
	def __str__(self):
		return self.title

	@property
	def hit_cnt(self):
		self.hit = self.hit + 1
		self.save()
	

 

- forms

{SublimeText} home/forms.py

from django import forms
from django.contrib.auth.forms import UserCreationForm
from home.models import Notice


class NoticeForm(forms.ModelForm):

    class Meta:
        model = Notice
        fields = ['author', 'title', 'article']

        widgets = {
            'title'     : forms.TextInput(attrs={'style':'width: 12em'}),
            'article'   : forms.Textarea(attrs={'style':'width: 40em', 'rows':4}),
        }

 

- admin

{SublimeText} home/admin.py

from django.contrib import admin
from home.models import Notice


class NoticeAdmin(admin.ModelAdmin):
    search_fields = ['title']

admin.site.register(Notice, NoticeAdmin)

 

- urls

{SublimeText} home/urls.py

from django.contrib import admin
from django.urls import path
from home import views


urlpatterns = [
	path('', views.home_welcome, name='home_welcome'),
 	path('notice/<int:pk>/', views.notice, name='notice'),
 	path('notice/new/', views.notice_new, name='notice_new'),
	path('notice/<int:pk>/edit/', views.notice_edit, name='notice_edit'),
	path('notice/<int:pk>/delete/', views.notice_delete, name='notice_delete'),
]

 

- views

{SublimeText} home/views.py

from django.shortcuts import render, redirect
from django.contrib import auth
from django.contrib.auth.models import User
from django.contrib.auth import authenticate
from django.contrib.auth.decorators import login_required
from home.models import Notice
from home.forms import NoticeForm


def signup(request):
	if request.method == 'POST':
		if request.POST['password1'] == request.POST['password2']:
			user = User.objects.create_user(username=request.POST['username'], password=request.POST['password1'], email=request.POST['email'], is_active=False)
			auth.login(request, user)
			return render(request, 'signup_waiting.html', {'user':user})
		return redirect('/')
	return render(request, 'signup.html')

@login_required
def home_welcome(request):
	notices = Notice.objects.all().order_by('-notice_id')
	return render(request, 'home_welcome.html', {'notices': notices})

@login_required
def notice(request, pk):
	notices = Notice.objects.all().order_by('-notice_id')
	notice_view  = Notice.objects.get(pk=pk)
	context = {'notices': notices, 'notice_view': notice_view}
	return render(request, 'notice.html', context)

@login_required
def notice_new(request):
	notices = Notice.objects.all().order_by('-notice_id')
	if request.method == 'POST':
		form = NoticeForm(request.POST)
		if form.is_valid():
			notice_new = Notice()
			notice_new.author       = form.cleaned_data['author']
			notice_new.title        = form.cleaned_data['title']
			notice_new.article      = form.cleaned_data['article']
			notice_new.save()
			return redirect('/home/')
	else:
		form = NoticeForm()
		pass
	return render(request, 'notice_new.html', {'notices':notices,'form':form})

@login_required
def notice_delete(request, pk):
	notice_del  = Notice.objects.get(pk=pk)
	if notice_del.author == User.objects.get(username = request.user.get_username()):
		notice_del.delete()
		return redirect('/home/')
	else:
		return render(request, 'warning.html')

@login_required
def notice_edit(request, pk):
	notices = Notice.objects.all().order_by('-notice_id')
	notice_edit  = Notice.objects.get(pk=pk)
	if request.method == 'POST':
		form = NoticeForm(request.POST)
		if form.is_valid():
			notice_edit.author   = form.cleaned_data['author']
			notice_edit.title    = form.cleaned_data['title']
			notice_edit.article  = form.cleaned_data['article']
			notice_edit.save()
			return redirect('/home/')
	else:
		form = NoticeForm()
		pass		
	return render(request, 'notice_edit.html', {'form':form, 'notices':notices})

 

- templates : route(공통)

{SublimeText} templates/base.html

{% load static %}
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>{% block title %}{{ section.title }}{% endblock %}</title>
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <link rel="stylesheet" href="{% static 'css/style_home.css' %}">
  </head>

  <body>
    <div id="container">
      <div id="header">
        <div class="logo">
          <a href="{% url 'home_welcome' %}"><img src="{% static 'img/logo_w_persona.png' %}" width="140" height="38"></a>
        </div>
        <div class="h-item">
          {% if user.is_authenticated %}
          <a href="{% url 'logout' %}"><input type="submit" value="{{ user.username }} (Logout)"></a>
          {% else %}
          <a href="{% url 'login' %}"><input type="submit" value="Login"></a>
          {% endif %}
        </div>  
        <div class="search-item">
          <input type="search" name="q" placeholder="Search query">
          <input type="submit" value="Go!">
        </div>
      </div>

      <!--navbar_top  -->
      {% block navbar_top %}
      {% endblock %}

      <!-- Main block -->
      <div id="m-content">
      {% block content1 %}
      {% endblock %}
      </div>

      <!--navbar_sub  -->
      {% block navbar_sub %}
      {% endblock %}
      
      <!-- Sub block -->
      <div id="s-content">
      {% block content2 %}
      {% endblock %}
      </div>

    <div id="footer">
      <p>Copyright © PERSONA All rights reversed.</p>
    </div>
    </div>
  </body>
</html>

{SublimeText} templates/welcome.html

{% load static %}
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Welcome_PERSONA_ERP</title>
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <link rel="stylesheet" href="{% static 'css/style_home.css' %}">
  </head>

  <body>
    <div id="container">
      <div id="header">
        <!-- <h1>Responsive Layout</h1> -->
        <div class="logo">
          <a href="{% url 'welcome' %}"><img src="{% static 'img/logo_w_persona.png' %}" width="140" height="38"></a>
        </div>
        <div class="h-item">
          <a href="{% url 'login' %}"><input type="submit" value="Login"></a>
          <a href="{% url 'signup' %}"><button type="submit">Sign-Up</button></a>
        </div>  
      </div>

      <div id="m-content">
        <h2>Thanks to visit PERSONA ERP</h2>
        <h3>기존회원로그인</h3>
          <p>로그인 후 모든 서비스를 사용할 수 있음.</p>
        <h3>회원가입안내</h3>
          <p>회원가입 승인 후 모든 서비스를 사용할 수 있음.</p>
      </div>
        
        {% block logform %}
        {% endblock %}

    <div id="footer">
      <p>Copyright © PERSONA All rights reversed.</p>
    </div>
    </div>
  </body>
</html>

{SublimeText} templates/login.html

{% extends 'welcome.html' %}
{% block logform %}
{% include "navbar_login.html" %}

<div id="s-content">
  <div>
    <form method="POST" class="post-form" action="{% url 'login' %}">
        {% csrf_token %}
        {% include "form_errors.html" %}
        <div>
            <label for="username">User-ID</label><br>
            <input type="text" name="username" id="username"
            	   value="{{ form.username.value|default_if_none:'' }}">
        </div>
        <div>
            <label for="password">Password</label><br>
            <input type="password" name="password" id="password"
                   value="{{ form.password.value|default_if_none:'' }}">
        </div>
        <button type="submit">Login</button>
    </form>
  </div>
</div>
{% endblock %}

{SublimeText} templates/signup.html

{% extends 'welcome.html' %}
{% block logform %}
{% include "navbar_signup.html" %}

<div id="s-content">
  <div>
    <form method="POST" class="post-form">
        {% csrf_token %}
        {% include "form_errors.html" %}
        <div>
            <label for="username">User-ID</label><br>
            <input type="text" name="username" id="username"
            	   value="{{ form.username.value|default_if_none:'' }}">
        </div>
        <div>
            <label for="password1">Password</label><br>
            <input type="password" name="password1" id="password1"
                   value="{{ form.password1.value|default_if_none:'' }}">
        </div>
        <div>
            <label for="password2">Password Confirm</label><br>
            <input type="password" name="password2" id="password2"
                   value="{{ form.password2.value|default_if_none:'' }}">
        </div>
        <div>
            <label for="email">E-mail</label><br>
            <input type="text" name="email" id="email"
                   value="{{ form.email.value|default_if_none:'' }}">
        </div>
        <a href="{% url 'signup_waiting' %}"><button type="submit">Create</button></a>
    </form>
  </div>
</div>

{% endblock %}

{SublimeText} templates/signup_waiting.html

{% extends 'welcome.html' %}
{% block logform %}

<div id="s-content">
  <h3>{{ user.username }}님 반갑습니다~^^</h3>
  <h3>{{ user.email }}로 관리자 승인 여부 확인 후 회신 예정입니다.</h3>
</div>

{% endblock %}

{SublimeText} templates/form_errors.html

{% if form.errors %}
    {% for field in form %}
        {% for error in field.errors %}
            <div class="alert alert-danger">
                <strong>{{ field.label }}</strong>
                {{ error }}
            </div>
        {% endfor %}
    {% endfor %}
    {% for error in form.non_field_errors %}
        <div class="alert alert-danger">
            <strong>{{ error }}</strong>
        </div>
    {% endfor %}
{% endif %}

{SublimeText} templates/warning.html

<html>
Warning!!!
</html>

 

 

- template : route(navbar)

{SublimeText} templates/navbar_login.html

<nav class="nav_sub" style="color: white; font-size: 20px">
  <ul>
    <li>Login</li>
  </ul>
</nav>

{SublimeText} templates/navbar_main.html

<nav class="nav_main">
  <ul>
    <li><a href="{% url 'index_sales' %}">영업관리</a></li>
    <li><a href="{% url 'index_production' %}">생산관리</a></li>
    <li><a href="#">구매관리</a></li>
    <li><a href="#">품질관리</a></li>
    <li><a href="#">원가관리</a></li>
    <li><a href="#">인사관리</a></li>
    <li><a href="#">회계관리</a></li>
    <li><a href="#">무역관리</a></li>
    <li><a href="#">경영관리</a></li>
  </ul>
</nav>

{SublimeText} templates/navbar_new.html

<nav class="nav_sub">
  <ul>
    <li><a href="./new/">새글쓰기</a></li>
  </ul>
</nav>

{SublimeText} templates/navbar_notice.html

<nav class="nav_sub" style="color: white; font-size: 18px">
  <ul>
    <li>Notice</li>
    {% if user.is_superuser %}
    <a href="{% url 'notice_new' %}"><li>새글쓰기</li></a>
    {% endif %}
  </ul>
</nav>

{SublimeText} templates/navbar_production.html

<nav class="nav_tree">
  <ul>
    <li><a href="#">수주조회</a></li>
    <li><a href="#">재고조회</a></li>
    <li><a href="#">BOM조회</a></li>
    <li><a href="#">생산조회</a></li>
    <li><a href="#">공정조회</a></li>
    <li><a href="#">검사조회</a></li>
    <li><a href="#">불량조회</a></li>
    <li><a href="#">자재발주</a></li>
    <li><a href="#">외주관리</a></li>
    <li><a href="#">외주발주</a></li>
  </ul>
</nav>

{SublimeText} templates/navbar_sales.html

<nav class="nav_tree">
  <ul>
    <li><a href="#">재고관리</a></li>
    <li><a href="#">수주관리</a></li>
    <li><a href="#">출하관리</a></li>
    <li><a href="#">매출현황</a></li>
    <li><a href="#">이익현황</a></li>
    <li><a href="#">거래처구분</a></li>
    <li><a href="#">제품구분</a></li>
    <li><a href="#">제품이동내역</a></li>
    <li><a href="#">정산</a></li>
  </ul>
</nav>

{SublimeText} templates/navbar_signup.html

<nav class="nav_sub" style="color: white; font-size: 20px">
  <ul>
    <li>Sign-Up</li>
  </ul>
</nav>

{SublimeText} templates/navbar_sub.html

<nav class="nav_sub">
  <ul>
    <li><a href="./edit/">수정</a></li>
    <li><a href="./delete/">삭제</a></li>
  </ul>
</nav>

 

 

- templates : home

{SublimeText} home/templates/home_welcome.html

{% extends 'base.html' %}
<!--navbar_top  -->
{% block navbar_top %}
{% include "navbar_main.html" %}
{% endblock %}

<!-- Main block -->
{% block content1 %}
<h2>{{ user.username }}님 반갑습니다.</h2>
<table>
  <thead>
    <tr>
      <td><B>사번</B></td>
      <td><B>결재함</B></td>
      <td><B>일정보기</B></td>
      <td><B>잔여휴가</B></td>
    </tr>
  </thead>

  <tbody>
    <tr>
      <td>staff_num</a></td>
      <td><a href="#">approval_count</a></td>
      <td><a href="#">schedule_count</a></td>
      <td><a href="#">dayoff_count</a></td>
    </tr>
  </tbody>
</table>


{% endblock %}
<!-- End Main block -->

<!--navbar_sub  -->
{% block navbar_sub %}
{% include "navbar_notice.html" %}
{% endblock %}

<!-- Sub block -->
{% block content2 %}
<h2>공지사항</h2>
<table>
  <thead>
    <tr>
      <td><B>No.</B></td>
      <td><B>작성자</B></td>
      <td><B>제목</B></td>
      <td><B>작성일</B></td>
      <td><B>조회수</B></td>
    </tr>
  </thead>
  <tbody>
    {% for notice in notices %}
    <tr>
      <td>{{ notice.notice_id }}</td>
      <td>{{ notice.author }}</td>
      <td><a href="{% url 'notice' notice.pk %}">{{ notice.title }}</a></td>
      <td>{{ notice.created_at }}</td>
      <td>{{ notice.hit }}</td>
    </tr>
    {% endfor %}
  </tbody>
</table>
{% endblock %}
<!-- End Sub block -->

{SublimeText} home/templates/notice.html

{% extends 'base.html' %}
<!--navbar_top  -->
{% block navbar_top %}
{% include "navbar_main.html" %}
{% endblock %}

<!-- Main block -->
{% block content1 %}
<h2>공지사항</h2>
<table>
  <thead>
    <tr>
      <td><B>No.</B></td>
      <td><B>작성자</B></td>
      <td><B>제목</B></td>
      <td><B>작성일</B></td>
      <td><B>수정일</B></td>
      <td><B>조회수</B></td>
    </tr>
  </thead>
  <tbody>
    {% for notice in notices %}
    <tr>
      <td>{{ notice.notice_id }}</td>
      <td>{{ notice.author }}</td>
      <td><a href="{% url 'notice' notice.pk %}">{{ notice.title }}</a></td>
      <td>{{ notice.created_at }}</td>
      <td>{{ notice.updated_at }}</td>
      <td>{{ notice.hit }}</td>
    </tr>
    {% endfor %}
  </tbody>
</table>
{% endblock %}
<!-- End Main block -->

<!--navbar_sub  -->
{% block navbar_sub %}
{% include "navbar_notice.html" %}
{% endblock %}

<!-- Sub block -->
{% block content2 %}
<p style="display:none">{{ notice_view.hit_cnt }}</p>
{% if user.is_superuser %}
<a href="{% url 'notice_edit' notice_view.pk %}"><button type="submit">수정하기</button></a>
<a href="{% url 'notice_delete' notice_view.pk %}"><button type="submit">삭제</button></a>
{% endif %}
  <h2>{{ notice_view.title }}</h2>
  <p>{{ notice_view.article }}</p>
{% endblock %}
<!-- End Sub block -->

{SublimeText} home/templates/notice_edit.html

{% extends 'base.html' %}
<!--navbar_top  -->
{% block navbar_top %}
{% include "navbar_main.html" %}
{% endblock %}

<!-- Main block -->
{% block content1 %}
<h2>공지사항</h2>
<table>
  <thead>
    <tr>
      <td><B>No.</B></td>
      <td><B>작성자</B></td>
      <td><B>제목</B></td>
      <td><B>작성일</B></td>
      <td><B>수정일</B></td>
      <td><B>조회수</B></td>
    </tr>
  </thead>
  <tbody>
    {% for notice in notices %}
    <tr>
      <td>{{ notice.notice_id }}</td>
      <td>{{ notice.author }}</td>
      <td><a href="{% url 'notice' notice.pk %}">{{ notice.title }}</a></td>
      <td>{{ notice.created_at }}</td>
      <td>{{ notice.updated_at }}</td>
      <td>{{ notice.hit }}</td>
    </tr>
    {% endfor %}
  </tbody>
</table>
{% endblock %}
<!-- End Main block -->

<!--navbar_sub  -->
{% block navbar_sub %}
{% include "navbar_notice.html" %}
{% endblock %}

<!-- Sub block -->
{% block content2 %}
<h2>수정하기</h2>
<form method="post">
  {% csrf_token %}
  {{ form.as_p }}
  <a href="{% url 'home_welcome' %}"><button type="submit">수정</button></a>
</form>
{% endblock %}
<!-- End Sub block -->

{SublimeText} home/templates/notice_delete.py

{% extends 'base.html' %}
<!--navbar_top  -->
{% block navbar_top %}
{% include "navbar_main.html" %}
{% endblock %}

<!-- Main block -->
{% block content1 %}
<h2>공지사항</h2>
<table>
  <thead>
    <tr>
      <td><B>No.</B></td>
      <td><B>작성자</B></td>
      <td><B>제목</B></td>
      <td><B>작성일</B></td>
      <td><B>수정일</B></td>
      <td><B>조회수</B></td>
    </tr>
  </thead>
  <tbody>
    {% for notice in notices %}
    <tr>
      <td>{{ notice.notice_id }}</td>
      <td>{{ notice.author }}</td>
      <td><a href="{% url 'notice' notice.pk %}">{{ notice.title }}</a></td>
      <td>{{ notice.created_at }}</td>
      <td>{{ notice.updated_at }}</td>
      <td>{{ notice.hit }}</td>
    </tr>
    {% endfor %}
  </tbody>
</table>
{% endblock %}
<!-- End Main block -->

<!--navbar_sub  -->
{% block navbar_sub %}
{% include "navbar_notice.html" %}
{% endblock %}

<!-- Sub block -->
{% block content2 %}
<h2>새글작성하기</h2>
<form method="post">
  {% csrf_token %}
  {{ form.as_p }}
  <a href="{% url 'home_welcome' %}"><button type="submit">생성</button></a>
</form>
  <!-- <h2>{{Notice_view.title}}</h2>
  <p>{{Notice_view.article}}</p> -->
{% endblock %}
<!-- End Sub block -->

 

- css : static/css

{SublimeText} static/css/style_home.css

table {
  width: 95%;
  border: 1px solid #444444;
  border-collapse: collapse;
  text-align:center;vertical-align:top
}

thead, tbody {
  border: 1px solid #444444;
  border-collapse: collapse;
}


input[type="text"] {
  margin: 5px;
  padding: 5px;
  border: solid 2px #bcbcbc;
  border-radius: 4px;
}

input[type="password"] {
  margin: 5px;
  padding: 5px;
  border: solid 2px #bcbcbc;
  border-radius: 4px;
  background-color: #000000;
}

#container {
  width: auto;
  padding: 5px;
  border: 1px solid #bcbcbc;
}

#header {
  height: 45px;
  padding: 1px;
  margin-bottom: 5px;
  border: 1px solid #bcbcbc;
  display: flex;
  align-items: center;
}

.logo {
  margin: 5px;
  padding: 5px;
}

.h-item {
  margin: 5px;
  padding: 10px;
}

.search-item {
  margin: 5px;
  padding: 5px;
  display: flex;
}

.nav_main {
  height:24px;
  background-color: #000000;
  display: flex;
  align-items: center;
}

.nav_tree {
  height:24px;
  background-color: #696969;
  display: flex;
  align-items: center;
}

.nav_sub {
  height:18px;
  background-color: #808080;
  display: flex;
  align-items: center;
}

.new_input {
  width: 10px;
/*  height:18px;
  background-color: #808080;
  display: flex;
  align-items: center;*/
}

nav ul {
  padding: 5px;
  display: flex;
}

nav li {
  display: inline;
  padding-left: 20px;
}

nav a {
  display: inline-block;
  font-size: 18px;
  text-transform: uppercase;
  text-decoration: none;
  color: white;
}


#m-content {
  width: auto;
  padding: 10px;
  margin-top: 5px;
  margin-bottom: 5px;
  border: 2px solid #000080;
}

#s-content {
  width: auto;
  padding: 10px;
  margin-top: 5px;
  margin-bottom: 5px;
  border: 2px solid #008080;
}

#footer {
  clear: both;
  padding-left: 10px;
  border: 1px solid #bcbcbc;
}


.tg  {border-collapse:collapse;border-spacing:0;}
.tg td{border-color:black;border-style:solid;border-width:1px;font-family:Arial, sans-serif;font-size:14px;
  overflow:hidden;padding:8px 10px;word-break:normal;}
.tg th{border-color:black;border-style:solid;border-width:1px;font-family:Arial, sans-serif;font-size:14px;
  font-weight:normal;overflow:hidden;padding:8px 10px;word-break:normal;}
.tg .tg-j4pq{background-color:#efefef;border-color:#000000;text-align:center;vertical-align:top}
.tg .tg-wp8o{border-color:#000000;text-align:center;vertical-align:top}
.tg .tg-jbyd{background-color:#ffffff;border-color:#000000;text-align:center;vertical-align:top}
.tg .tg-ymap{background-color:#ffffff;border-color:#000000;font-family:Arial, Helvetica, sans-serif !important;;font-size:28px;
  text-align:center;vertical-align:middle}
.tg .tg-73oq{border-color:#000000;text-align:left;vertical-align:top}
.tg .tg-fm1z{background-color:#f0f0f0;border-color:#000000;text-align:center;vertical-align:top}
.tg .tg-xwyw{border-color:#000000;text-align:center;vertical-align:middle}

 

반응형
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/07   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31
글 보관함