Form and ModelForm

.order_by()

pk ์—ญ์ˆœ์œผ๋กœ ์ •๋ ฌ

articles = Article.objects.order_by('-pk')

ModelForm

ModelForm ์ •์˜ํ•˜๊ธฐ

forms.py

from django import forms
from .models import Article

class ArticleForm(forms.ModelForm):
    title = forms.CharField(
        max_length=100,
        label='Title',
        help_text='Your title must be no more than 100 characters in length',
        widget=forms.TextInput(
            attrs={
                'class':'my_input',
                'placeholder': "What's on your mind?"
            }
        )
    )
    content = forms.CharField(
        label='Content',
        help_text='Jot down random musings and thoughts',
        widget=forms.Textarea(
            attrs={
                'row':5,
                'col':50,
            }
        )
    )
    class Meta:
        model = Article
        # ๋‹ค ๋•Œ๋ ค๋ฐ•์•„
        fields = '__all__'

View์—์„œ ModelFrom ํ™œ์šฉ

view.py

from django.shortcuts import render, redirect, get_object_or_404
from django.views.decorators.http import require_POST
from .models import Article
from .forms import ArticleForm

# Create your views here.
def index(request):
    articles = Article.objects.order_by('-pk')
    context = {
        'articles': articles
    }
    return render(request, 'articles/index.html', context)

def create(request):
    # POST /articles/create/
    if request.method == 'POST':
        # Article table์— data๋ฅผ ์ €์žฅํ•จ
        form = ArticleForm(request.POST)
        if form.is_valid():
            form.save()
            #detail๋กœ redirect
            return redirect('articles:index')
        print('errors?',form.errors)
        print('cleaned_data?',form.cleaned_data)

    # GET /articles/create    
    else:
        # ๋นˆ ๊ป๋ฐ๊ธฐ input form 
        form = ArticleForm()

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


def detail(request, pk):
    article = get_object_or_404(Article, id=pk)
    context ={
        'article':article
    }
    return render(request, 'articles/detail.html', context)

@require_POST
def delete(request, pk):
    article = get_object_or_404(Article, id=pk)
    article.delete()
    return redirect('articles:index')

def update(request, pk):
    article = get_object_or_404(Article, id=pk)
    if request.method == 'POST':
        form = ArticleForm(request.POST,instance=article)
        if form.is_valid():
            article = form.save()
            return redirect('articles:detail', article.pk)
        else:
            form = ArticleForm(instance=article)
        context = {
            'form':form
        }
        return render(request, 'articles/form.html', context)

request.resolver_match.url_name ์œผ๋กœ ์กฐ๊ฑด์— ๋”ฐ๋ฅธ ์ฒ˜๋ฆฌ

form.html

  • ๋ถ„๊ธฐ์˜ ๊ธฐ์ค€์€ url_name ์ด๋‹ค

  • path๋กœ ํ•˜๋ฉด, url์ด ๋ฐ”๋€” ๋•Œ๋งˆ๋‹ค ๋ฐ”๊ฟ”์ค˜์•ผ ํ•œ๋‹ค!

{% if request.resolver_match.url_name == 'create' %}

    <h2>Write a post</h2>

{% else %}

    <h2>Edit post</h2>

{% endif %}

loop or bootstrap4 ํ™œ์šฉํ•˜์—ฌ ์ถœ๋ ฅํ•˜๊ธฐ

form.html

{% extends 'base.html' %}
{% load bootstrap4 %}

{% block body %}


    {% if request.resolver_match.url_name == 'create' %}

    <h2>Write a post</h2>

    {% else %}

    <h2>Edit post</h2>

    {% endif %}

    <!-- loop ํ™œ์šฉ-->
    <form action="" method="POST">
        {% csrf_token %}
        {% for field in form %}
            <div class="fieldWrapper">
                {{ field.errors }}
                {{ field.label_tag }} <br> 

                {{ field }}
                {% if field.help_text %}

                <p class="help">{{ field.help_text|safe }}</p>
                {% endif %}
            </div>
        {% endfor %}

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

    <!-- bootstrap4 ์‚ฌ์šฉ -->
    <form action="" method="POST">
        {% csrf_token %}
        {% bootstrap_form form %}
        <button class="btn btn-primary"> Submit</button>
    </form>

{% endblock %}

shell ๋“ค์–ด๊ฐ€๊ธฐ

$ python manage.py shell_plus

shell

In [1]: from articles.forms import ArticleForm                                                                                               

In [2]: form = ArticleForm()                                                                                                                 

In [3]: form                                                                                                                                 
Out[3]: <ArticleForm bound=False, valid=Unknown, fields=(title;content)>

p tag ๋กœ ์ด๋ฃจ์–ด์ง„ input๋“ค์˜ ์ง‘ํ•ฉ

In [4]: form.as_p()                                                                                                                          
Out[4]: '<p><label for="id_title">Title:</label> <input type="text" name="title" maxlength="100" required id="id_title"></p>\n<p><label for="id_content">Content:</label> <textarea name="content" cols="40" rows="10" required id="id_content">\n</textarea></p>'

table๋กœ ์ด๋ฃจ์–ด์ง„ input๋“ค์˜ ์ง‘ํ•ฉ

In [5]: form.as_table()                                                                                                                      
Out[5]: '<tr><th><label for="id_title">Title:</label></th><td><input type="text" name="title" maxlength="100" required id="id_title"></td></tr>\n<tr><th><label for="id_content">Content:</label></th><td><textarea name="content" cols="40" rows="10" required id="id_content">\n</textarea></td></tr>'
In [3]: from articles.forms import ArticleForm                                                            

In [4]: form = ArticleForm({'title':'์ œ๋ชฉ'})                                                              

In [5]: print(form)                                                                                       
<tr><th><label for="id_title">Title:</label></th><td><input type="text" name="title" value="์ œ๋ชฉ" maxlength="140" required id="id_title"></td></tr>
<tr><th><label for="id_content">Content:</label></th><td><ul class="errorlist"><li>This field is required.</li></ul><textarea name="content" cols="40" rows="10" required id="id_content">
</textarea></td></tr>

Looping over the formโ€™s fields

If youโ€™re using the same HTML for each of your form fields, you can reduce duplicate code by looping through each field in turn using a `

` loop:

{% for field in form %}
    <div class="fieldWrapper">
        {{ field.errors }}
        {{ field.label_tag }} {{ field }}
        {% if field.help_text %}
        <p class="help">{{ field.help_text|safe }}</p>
        {% endif %}
    </div>
{% endfor %}

Form rendering options

There are other output options though for the / pairs:

  • {{ form.as_table }} will render them as table cells wrapped in tags

  • {{ form.as_p }} will render them wrapped in `` tags

  • {{ form.as_ul }} will render them wrapped in `` tags

Note that youโ€™ll have to provide the surrounding or elements yourself.

Hereโ€™s the output of {{ form.as_p }} for our ContactForm instance:

Django Bootstrap ์‚ฌ์šฉํ•˜๊ธฐ

Install

$ pip install django-bootstrap4

settings.py ์ˆ˜์ •

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'articles',
    'django_extensions',
    'bootstrap4',
]

base.html์— bootstrap ์‚ฌ์šฉํ• ๊ฑฐ๋ผ๊ณ  ์„ ์–ธ

<!DOCTYPE html>
{% load bootstrap4 %}
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Django Test</title>
    {% bootstrap_css %}
</head>
<body>
  <h1 class="text-center">CRUD with ModelForm</h1>
    <div class="w-75 m-auto">
    <hr>
      {% block body %}

      {% endblock %}
    </div>
    {% bootstrap_javascript jquery='full'%}
</body>
</html>

detail.html - bootstrap ์ ์šฉ๋˜๋Š” template๋“ค์—๋„ ์„ ์–ธ

{% extends 'base.html' %}
{% load bootstrap4 %}

{% block body %}
    <h2>Detail</h2>
    <hr>
    <p ><a href="{% url 'articles:index' %}"> Back</a></p>
    <h3>Post # {{article.pk}}</h3>
    <h4>{{article.title}}</h4>
    <p>Created at {{article.created_at|date:'Y-m-d H:i'}}</p>
    <p>Updated at {{article.updated_at|date:'Y-m-d H:i'}}</p>
    <hr>
    <p>{{article.content|linebreaks}}</p>
     <form action="{% url 'articles:update' article.pk %}" method="POST" class="d-inline">
        {% csrf_token %}
        <button class="btn btn-warning">์ˆ˜์ •</button>   
    </form>

    <form action="{% url 'articles:delete' article.pk %}" method="POST" class="d-inline">
        {% csrf_token %}
        <button class="btn btn-danger">์‚ญ์ œ</button>   
    </form>

{% endblock  %}

+

Git

ํŠน์ • commit์„ ๊ธฐ์ค€์œผ๋กœ ๋Œ์•„๊ฐ€๊ธฐ

$ git checkout f008d8f

test branch ๋งŒ๋“ค๋ฉด์„œ ์ด๋™ํ•˜๊ธฐ

$ git checkout -b test
$ git log --oneline
f008d8f (HEAD -> test) 05 | Article Index
c2be3bc 04 | Article Model
0d28d53 03 | startapp articles
5afc6a9 02 | settings
a046911 01 | startproject

reference log ํ™•์ธ

$ git reflog

์–ด๋””์— head ์žˆ๋Š”์ง€ ํ™•์ธ

$ git log --oneline
fc58709 (HEAD -> master, origin/master, origin/HEAD) README.md ์ถ”๊ฐ€
fd2e992 06 | Article C with ModelForm
f008d8f (test) 05 | Article Index
c2be3bc 04 | Article Model
0d28d53 03 | startapp articles
5afc6a9 02 | settings
a046911 01 | startproject

๋‹ค์‹œ test branch๋กœ ๋Œ์•„๊ฐ€๊ธฐ

$ git checkout test
Switched to branch 'test'

Last updated