장고 기초

godo·2022년 5월 5일
0

Django

목록 보기
1/2

템플릿 추가

템플렛 파일 만들고 TEMPLATES 변수에 넣어주기 
'DIRS': [
            BASE_DIR / 'templates'
        ],

템플릿 내부에 a태그? 추가?

{% include 'navbar.html' %}

부분 템플릿 추가

{% extends 'main.html' %}

템플릿 싸이트

https://docs.djangoproject.com/en/4.0/topics/templates/

링크 주기

<a href="/room/{{room.id}}">

{{}} << 안에 값주기

<a href="{% url 'room' room.id %}">

이런 식으로 변경해줄 수 있음

모델

class Room(models.Model) : 

    # host =
    # topic = 
    name = models.CharField(max_length=200)
    description = models.TextField(null=True, blank=True) # 없을 수도 있음 
    # participants = 
    updated = models.DateTimeField(auto_now=True) # 계속 찍힘 
    created = models.DateTimeField(auto_now_add=True) # 처음 일때만 찍힘  


    def __str__(self) : 
        return str(self.name)

그리고 python mange.py makemigrations 를 통해 따로 추가
그리고 migrate 로 완료

admin 추가

python manage.py createsuperuser ... 그리고 admin 아이디와 패스워드 추가

admin 에 추가

해당 앱의 admin.py 가서 다음과 같은 코드 치기

from django.contrib import admin

# Register your models here.

from .models import Room

admin.site.register(Room)

그러면 데이터베이스 관리 가능하게 됨

view 에 추가

from .models import Room

...

rooms = Room.objects.all() # 을 통해서 데이터 베이스 내부 데이터 다 가져옴 

그리고

def home(request) : 
    rooms = Room.objects.all()
    context = {'rooms':rooms}
    return render(request, 'base/home.html',context)

def room(request,pk) :

    room = Room.objects.get(id=pk)

    # room = None
    # for i in rooms : 
    #     if i['id'] == int(pk) : 
    #         room = i
    context = {'room':room}

    return render(request, 'base/room.html',context)

relation model

class Message(models.Model)  :

    # user = 
    room = models.ForeignKey(Room, on_delete=models.CASCADE) # 자동으로 같이 지워지게 됨  
    body = models.TextField()
    updated = models.DateTimeField(auto_now=True) # 계속 찍힘 
    created = models.DateTimeField(auto_now_add=True) # 처음 일때만 찍힘  

    def __str_(self) : 
        return self.body[0:50]

user model

from django.contrib.auth.models import User

추가
그리고

    user = models.ForeignKey(User, on_delete=models.CASCADE)

모델 관련 모든 코드

class Topic(models.Model) : 
    name = models.CharField(max_length=200)


    def __str__ (self) : 
        return self.name


class Room(models.Model) : 

    host = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
    topic = models.ForeignKey(Topic, on_delete=models.SET_NULL, null=True) # CASCADE 가 아닌 무효 
    name = models.CharField(max_length=200)
    description = models.TextField(null=True, blank=True) # 없을 수도 있음 
    # participants = 
    updated = models.DateTimeField(auto_now=True) # 계속 찍힘 
    created = models.DateTimeField(auto_now_add=True) # 처음 일때만 찍힘  


    def __str__(self) : 
        return str(self.name)



class Message(models.Model)  :

    user = models.ForeignKey(User, on_delete=models.CASCADE)
    room = models.ForeignKey(Room, on_delete=models.CASCADE) # 자동으로 같이 지워지게 됨  
    body = models.TextField()
    updated = models.DateTimeField(auto_now=True) # 계속 찍힘 
    created = models.DateTimeField(auto_now_add=True) # 처음 일때만 찍힘  

    def __str_(self) : 
        return self.body[0:50]

그리고 makemigrations 랑 migrate 해주기

그리고 admin 페이지 가서 변경해주기

랜더링

{% extends 'main.html' %}


{% block content %}

<h1>Home Template</h1>

<div>
    <div>
        {% for room in rooms %}
        <div>
            <span>@{{room.host.username}}</span>
            <h5>{{room.id}} -- <a href="{% url 'room' room.id %}">{{room.name}}</a></h5>
            <small>{{room.topic.name}}</small>
            <hr>    
        </div>
        {% endfor %}
    </div>
</div>

{% endblock content %}

home.html 의 코드를 다음과 같이 변경

CRUD

update

준비

{% extends 'main.html' %}


{% block content %}

<div>
    <form method="POST" action="">
        {% csrf_token %}

        <input type="submit" value="Submit">
    </form>



</div>


{% endblock content %}

room 폼 만들어주기

그리고 home.html 다음과 같은 코드 추가

<a href="{% url 'create-room' %}">Create Room</a>

폼 파일

from django.forms import ModelForm
from .models import Room



class RoomForm(ModelForm) : 
    class Meta : 
        model = Room
        field = '__all__' # 보여주고 싶은 것을 선책 
        exclude = ()

뷰 파일

def createRoom(request) : 
    form = RoomForm()
    context = {'form':form}
    return render(request, 'base/room_form.html', context)

url 파일

path('create-room/', views.createRoom, name="create-room"),

템플릿 파일

        {{form.as_p}}

뷰 파일

from django.shortcuts import render, redirect

...

def createRoom(request) : 
    form = RoomForm()
    if request.method == 'POST' :
        form = RoomForm(request.POST)
        if form.is_valid() :
            form.save() # 데이터 베이스에 추가 
            return redirect('home') # url 에 이름 있어서 redirect 가능해짐

    context = {'form':form}
    return render(request, 'base/room_form.html', context)

정렬


Room class 안에 넣어진 

class Meta : 
        ordering = ['-updated','-created'] # '-' 넣어주면 가장 먼저 준 것 먼저 나오고 , 안 주면 가장 나중에 것이 나옴 
        
        

Update

뷰 파일

def updateRoom(request,pk) : 
    room = Room.objects.get(id=pk)
    form = RoomForm(instance=room)
    context = {'form': form}
    return render(request, 'base/room_form.html',context)

url 파일

path('update-room/<str:pk>/', views.updateRoom, name="update-room"),

home 파일

<a href="{% url 'update-room' room.id %}">Edit</a>

view 파일

if request.method == 'POST' :
        form = RoomForm(request.POST, instance=room)
        if form.is_valid() :
            form.save()
            return redirect('home')

업데이트 파일에 추가

Delete

delete.html

{% extends 'main.html' %}

{% block content %}

<form method="POST" action="">
    {% csrf_token %}
    <p>Are you sure you want to delete "{{obj}}"?</p>
    <a href="{{request.META.HTTP_REFERER}}">Go Back</a>  // 전 페이지로 다시 돌아가기 
    <input type="submit" value="Confirm">

</form>

{% endblock content %}

뷰 파일

def deleteRoom(request,pk) :
    room = Room.objects.get(id=pk)
    if request.method == "POST" : 
        room.delete()
        return redirect('home')

    return render(request, 'base/delete.html', {'obj':room})

url 파일

path('delete-room/<str:pk>/', views.deleteRoom, name="delete-room"),

home.html

<div>

        <h3>Browse Topics</h3>
        <hr>

        <div>

            <a href="{% url 'home' %}">ALL</a>
        </div>

        {% for topic in topics %}
            <div>

                <a href="{% url 'home' %}?q={{topic.name}}">{{topic.name}}</a>
            </div>
        {% endfor %}
</div>

쿼리 url 문

view 파일

topics = Topic.objects.all()

로 주제 다 가져오기

q = request.GET.get('q') if request.GET.get('q') != None else ''
    # topic__ 언더바 두개는 부모의 것을 의미 
    # icontains 는 적어도 하나의 문자를 포함할 때...
    rooms = Room.objects.filter(topic__name__icontains=q)  
<form method="GET" action="{% url 'home' %}">
    <input type="text" name="q" placeholder="Search Rooms...">

</form>

추가

더 다양한 검색 옵션 (내용, 등등)

뷰파일에서

from django.db.models import Q
...
rooms = Room.objects.filter(
        Q(topic__name__icontains=q) |
        Q(name__icontains=q) |
        Q(description__icontains=q)
    )  

이런 식으로 코드를 변경하면 됨

검색된 갯수

home.html

<h5>{{room_count}} rooms available</h5>

view 파일

def home(request) : 
    q = request.GET.get('q') if request.GET.get('q') != None else ''
    # topic__ 언더바 두개는 부모의 것을 의미 
    # icontains 는 적어도 하나의 문자를 포함할 때...
    rooms = Room.objects.filter(
        Q(topic__name__icontains=q) |
        Q(name__icontains=q) |
        Q(description__icontains=q)
    )  

    topics = Topic.objects.all()
    room_count = rooms.count()

    context = {'rooms':rooms, 'topics':topics, 'room_count':room_count}
    return render(request, 'base/home.html',context)

Log in

템플릿

페이지

{% extends 'main.html' %}

{% block content %}

<div>

    <form method="POST" action="">
        {% csrf_token %}

        <label for="">Username: </label>
        <input type="text" name="username" placeholder="Enter Username">

        <label for="">Password: </label>
        <input type="password" name="password" placeholder="Enter Password">
        
        <input type="submit" value="Login">
    </form>

</div>

{% endblock content %}

로그인 버튼

<form method="GET" action="{% url 'home' %}">
    <input type="text" name="q" placeholder="Search Rooms...">
</form>

로그인 파일

path('login/',views.loginPage, name="login"),

뷰 파일

from django.contrib.auth.models import User

...

def loginPage(request) :

    if request.method == 'POST' : 
        username = request.POST.get('username')
        password = request.POST.get('password')

        try:
            user = User.objects.get(username=usernmae)
        except:
            

    context = {}
    return render(request, 'base/login_register.html')

알림창 메시지 주기

from django.contrib import messages

...

try:
     user = User.objects.get(username=usernmae)
except:
     messages.error(request, 'User does not exist')

총 코드

뷰 파일

from django.contrib.auth.models import User
from django.contrib import messages
from django.contrib.auth import authenticate, login, logout


def loginPage(request) :

    if request.method == 'POST' : 
        username = request.POST.get('username')
        password = request.POST.get('password')

        try:
            user = User.objects.get(username=username)
        except:
            messages.error(request, 'User does not exist')
        
        user = authenticate(request,username=username, password=password)

        if user is not None : 
            login(request, user)
            return redirect('home')
        
        else : 
            messages.error(request, 'Username OR password does not exit')

    context = {}
    return render(request, 'base/login_register.html')

로그인 or 로그아웃 바

<a href="/">
    <h1>LOGO</h1>
</a>

<form method="GET" action="{% url 'home' %}">
    <input type="text" name="q" placeholder="Search Rooms...">
</form>

{% if request.user.is_authenticated %}
<a href="">Logout</a>
{% else %}
<a href="{% url 'login' %}">Login</a>
{% endif %}

<hr></hr>

로그아웃

네비게이션 바

{% if request.user.is_authenticated %}
<a href="{% url 'logout' %}">Logout</a>
{% else %}
<a href="{% url 'login' %}">Login</a>
{% endif %}

뷰 파일

def logoutUser(request) : 
    logout(request)
    return redirect('home')

url 파일

path('logout/',views.logoutUser, name="logout"),

Restricted Pages ... 로그인 권한을 가지고 있는 계속 체크하는 것

from django.contrib.auth.decorators import login_required

뷰 파일에 다음과 같은 라이브러리 임포트

@login_required(login_url='login')

업데이트, 딜리트, 크리에이트 에 위 코드 추가

업데이트,삭제 권한(자기가 만든 게시판만 처리 가능) 있을 때만 가능하게 됨

뷰 파일

from django.http import HttpResponse
...

@login_required(login_url='login')
def updateRoom(request,pk) : 
    room = Room.objects.get(id=pk)
    form = RoomForm(instance=room)

    if request.user != room.host : 
        return HttpResponse('Your are not allowed here!!!') // 요거 요거 

권한 있을 때만 버튼 나오게 됨

{% if request.user == room.host %}
        <a href="{% url 'update-room' room.id %}">Edit</a>
        <a href="{% url 'delete-room' room.id %}">Delete</a>
{% endif %}

재 로그인 불가하게 하기

def loginPage(request) :

    if request.user.is_authenticated : 
        return redirect('home')

User Register

템플릿

재사용

{% extends 'main.html' %}

{% block content %}

<div>

    <form method="POST" action="">
        {% csrf_token %}

        <label>Username: </label>
        <input type="text" name="username" placeholder="Enter Username">

        <label>Password: </label>
        <input type="password" name="password" placeholder="Enter Password">
        
        <input type="submit" value="Login">
    </form>

</div>

<div>

    <form method="POST" action="">
        {% csrf_token %}

        <input type="submit" value="Register">
    </form>

    

</div>

{% endblock content %}

뷰 파일

1차


def loginPage(request) :
    page ='login'
    ...
    context = {'page':page, }
    return render(request, 'base/login_register.html',context)
    
    ...

def registerUser(request) : 
    page = 'register'
    return render(request, 'base/login_register.html')

2차

from django.contrib.auth.forms import UserCreationForm
...
def registerPage(request) : 
    page = 'register'
    form = UserCreationForm()

    if request.method == 'POST' : 
        form = UserCreationForm(request.POST)
        if form.is_valid() : 
            user = form.save(commit=False) # 전처리 
            user.username = user.username.lower() # 대문자 소문자로 처리
            user.save()
            login(request,user)      
            return redirect('home')
        else : 
            messages.error(request, 'An error occured during registration')
            
     
<p>Hello {{request.user}}</p>

Chat Room CRUD

room.html

{% extends 'main.html' %}

{% block content %}


<h1>{{room.name}}</h1>

<p>{{room.description}}</p>

<div class="comment-wrapper">
    <h3>Conversation</h3>
    <hr>

    {% for message in room_messages %}
        <div>
            <small>@{{message.user}} {{message.created|timesince}} ago </small>
            <p>{{message.body}}</p>
        </div>

    {% endfor %}
</div>

{% if request.user.is_authenticated %}
<div class="comment-form"></div>
    <form method="POST" action="">
        {% csrf_token %}
        <input type = "text" name = "body" placeholder = "Wirte your Messge here">

    </form>
{% endif %}

{% endblock content %}

뷰 파일

def room(request,pk) :

    room = Room.objects.get(id=pk)
    room_messages = room.message_set.all().order_by('-created')
    context = {'room':room,'room_messages':room_messages}

    return render(request, 'base/room.html',context)
    

그리고

from .models import Room, Topic, Message


if request.method == 'POST' : 
     message = Message.objects.create()

댓글 만들었을 때

if request.method == 'POST' : 
        message = Message.objects.create(
            user = request.user,
            room = room,
            body = request.POST.get('body'),
        )
        return redirect('room',pk=room.id)

옆에 participants 만들기

일단 코드

{% extends 'main.html' %}

{% block content %}

<style>
   .room-container{
       display: grid;
       grid-template-columns: 3fr 1fr;
   }

</style>

<div class="room-container">

   <div>

       <h1>{{room.name}}</h1>

       <p>{{room.description}}</p>

       <div class="comment-wrapper">
           <h3>Conversation</h3>
           <hr>

           {% for message in room_messages %}
               <div>
                   <small>@{{message.user}} {{message.created|timesince}} ago </small>
                   <p>{{message.body}}</p>
               </div>
               <hr>
           {% endfor %}
           
       </div>

       {% if request.user.is_authenticated %}
       <div class="comment-form"></div>
           <form method="POST" action="">
               {% csrf_token %}
               <input type = "text" name = "body" placeholder = "Wirte your Messge here">

           </form>
       {% endif %}
   </div>

   <div>
       <h3>Participants</h3>
       <hr>
   </div>

</div>

{% endblock content %}

Room 모델에 paticipants 변수

participants = models.ManyToManyField(User, related_name='participants', blank=True)

이거 주기

view 파일

participants = room.participants.all()

context = {'room':room,'room_messages':room_messages,
                'participants':participants}

room.html

{% for user in participants %}
           <div>
               <p>@{{user.username}}</p>
           </div>
{% endfor %}

view 파일 참여 추가

if request.method == 'POST' : 
        message = Message.objects.create(
            user = request.user,
            room = room,
            body = request.POST.get('body'),
        )
        room.participants.add(request.user) # 이 부분을 통해 참여자 추가 
        return redirect('room',pk=room.id)

삭제

템플릿

<div>
        {% if request.user == message.user %}
         <a href="{% url 'delete-message' message.id %}">Delete</a>
         {% endif %}
         <small>@{{message.user}} {{message.created|timesince}} ago </small>
         <p>{{message.body}}</p>
</div>


뷰 파일

@login_required(login_url='login')
def deleteMessage(request,pk) :
    message = Message.objects.get(id=pk)

    if request.user != message.user : 
        return HttpResponse('Your are not allowed here!!!')

    if request.method == "POST" : 
        message.delete()
        return redirect('home')

    return render(request, 'base/delete.html', {'obj':message})

url 파일

path('delete-message/<str:pk>/', views.deleteMessage, name="delete-message"),

Activity Feed

템플릿

1 3 1 그리드 형식

<div>
        <h3>Recent Activity</h3>
        <hr>
        {% for message in room_messages %}
            <div>
                <small>@{{message.user}} {{message.created|timesince}}</small>
            </div>
        {% endfor %}
</div>

뷰 파일

room_messages = Message.objects.all()

context = {'rooms':rooms, 'topics':topics, 'room_count':room_count,
                'room_messages':room_messages,}

모델 파일 (시간 순으로 나오게 하기 위해서)

class Meta : 
        ordering = ['-updated','-created']
        

이 코드를 해당 클래스에 넣어주면 시간 빠른 순으로 나옴

피드 더 자세한 내용 나오게 템플릿 변경

{% for message in room_messages %}
     <div>
          <small>@{{message.user}} {{message.created|timesince}}</small>
           <small>replied to "{{message.room}}"</small>

           <p>{{message}}</p>

          {% if request.user == message.user %}
           <a href="{% url 'delete-message' message.id %}">Delete</a>
          {% endif %}
     </div>
{% endfor %}

주제별 검색 , 뷰 파일에서 홈 함수

room_messages = Message.objects.filter(Q(room__topic__name__icontains=q))

profile

템플릿 파일 ... feed_component.html

<a href="{% url 'user-profile' room.host.id %}">@{{room.host.username}}</a>

템플릿 파일 ... activity_component.html

<small><a href="{% url 'user-profile' message.user.id %}">@{{message.user}}</a> {{message.created|timesince}}</small>

템플릿 파일 ... profile.html

{% extends 'main.html' %}

{% block content %}

<style>
    .profile-container{
        display: grid;
        grid-template-columns: 1fr 3fr 1fr;
    }

</style>

<h1>{{user.username}}</h1>

<div class="profile-container"> 
    <div>
        {% include 'base/topics_component.html' %}
    </div>
    <div>
        {% include 'base/feed_component.html' %}
    </div>
    <div>
        {% include 'base/activity_component.html' %}
    </div>

</div>

{% endblock content %}

url 파일

path('profile/<str:pk>',views.userProfile, name="user-profile"),

view 파일

def userProfile(request,pk) :
    user = User.objects.get(id=pk)
    rooms = user.room_set.all()
    room_messages = user.message_set.all()
    topics = Topic.objects.all()
    context = {'user':user, 'rooms':rooms, 'room_messages': room_messages,
                'topics':topics}
    return render(request, 'base/profile.html',context)

Static Files

메인 프로젝트 파일 내부에
static/styles/main.css
만들고
settings.py 에

STATICFILES_DIRS = [
    BASE_DIR / 'static'
]

이거 만들어 주고

main.html 에

{% load static  %}


<link rel="stylesheet" type='text/css' media="screen" href="{% static 'styles/main.css' %}">

이것을 줌으로 써 완성됨

이미지는

<img src="{% static 'images/grass.jpg' %}" alt="">

이런식으로 코딩하면 됨

CREATE FORM

Forms.py

class RoomForm(ModelForm) : 
    class Meta : 
        model = Room
        field = '__all__' # 보여주고 싶은 것을 선책 
        exclude = ['host','participants']  # 안 보여주고 싶은 것 

뷰 파일

@login_required(login_url='login')
def createRoom(request) : 
    form = RoomForm()
    if request.method == 'POST' :
        form = RoomForm(request.POST)
        if form.is_valid() :
            room = form.save(commit=False) # 데이터 베이스에 추가 
            room.host = request.user
            room.save()
            return redirect('home') # url 에 이름 있어서 redirect 가능해짐

    context = {'form':form}
    return render(request, 'base/room_form.html', context)
profile
☀️☀️☀️

0개의 댓글