• Home
  • About
  • Posts
  • 1. Model Form

    • 1.1. Model Class
    • 1.2. Form Class
    • 1.3. ModeForm Class
  • 2. Create

    • 2.1. urls.py
    • 2.2. views.py
    • 2.3. templates.html
  • 3. Read

    • 3.1. urls.py
    • 3.2. views.py
    • 3.3. templates.html
  • 4. Update

    • 4.1. urls.py
    • 4.2. views.py
    • 4.3. templates.html
  • 5. Delete

    • 5.1. urls.py
    • 5.2. views.py
    • 5.3. templates.html
  • 6. Handling HTTP Request Methods

    • 6.1. View Decoarators
    • 6.2. urls.py
    • 6.3. views.py

Django CRUD with Model Form

📅 2022-11-08
🖋️ Byongho96
  • 1. Model Form
    • 1.1. Model Class
    • 1.2. Form Class
    • 1.3. ModeForm Class
  • 2. Create
    • 2.1. urls.py
    • 2.2. views.py
    • 2.3. templates.html
  • 3. Read
    • 3.1. urls.py
    • 3.2. views.py
    • 3.3. templates.html
  • 4. Update
    • 4.1. urls.py
    • 4.2. views.py
    • 4.3. templates.html
  • 5. Delete
    • 5.1. urls.py
    • 5.2. views.py
    • 5.3. templates.html
  • 6. Handling HTTP Request Methods
    • 6.1. View Decoarators
    • 6.2. urls.py
    • 6.3. views.py

1. Model Form

1.1. Model Class

# articles/models.py
from django.db import models

# Article inherits model.Model
class Article(models.Model):
    title = models.CharField(max_length=10)
    content = models.TextField()

1.2. Form Class

In a similar way that a model class’s fields map to database fields, a form class’s fields map to HTML form <input> elements.

  • is_valid()
    A Form instance has an is_valid() method, which runs validation routines for all its fields. When this method is called, if all fields contain valid data, it will:

    • return True
    • place the form’s data in its cleaned_data attribute.
  • Widgets
    Django Widgets 공식문서
    Each form field has a corresponding Widget class, which in turn corresponds to an HTML form widget such as <input type="text">.

  • Form rendering options

    • as_div: will render them wrapped in <div> tags.
    • as_table: will render them as table cells wrapped in <tr> tags.
    • as_p: will render them wrapped in <p> tags.
    • as_ul: will render them wrapped in <li> tags.

Example

# articles/forms.py
from django import forms

class ArticleForm(forms.Form):
    NATION_A = 'kr'
    NATION_B = 'ch'
    NATION_C = 'jp'
    NATIONS_CHOICES = [
        (NATION_A, '한국'), # (value, showing)
        (NATION_B, '중국'),
        (NATION_C, '일본'),
    ]
    title = forms.CharField(max_length=10)
    content = forms.CharField(widget=forms.Textarea())
    nation = forms.ChoiceField(choices=NATIONS_CHOICES)

1.3. ModeForm Class

The form Class that map closely to Django models.

# articles/forms.py
from django import forms
from .models import Article

class ArticleForm(forms.ModelForm):
    title = forms.CharField(
        label = 'Title',
        widget=forms.TextInput(
            attrs={
                'class': 'my-title',
                'placeholder': 'Enter the title',
            }
        )
    )

    content = forms.CharField(
        label = 'Content',
        widget=forms.Textarea(
            attrs={
                'class': 'my-content',
                'placeholder': 'Enter the content',
                'rows': 5,
                'cols': 50,
            }
            error_message={
                'required': 'Please enter your content'
            }
        )
    )

    class Meta:
        model = Article
        fields = '__all__'
        # fields = ('title', 'content',)
        # exclude = ('title', )

2. Create

2.1. urls.py

app_name = 'articles'
urlpatterns = [
    path('new/', views.new, name='new'),
    path('create/', views.create, name='create'),
]

2.2. views.py

from .forms import ArticleForm

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

def create(request):
    form = ArticleForm(request.POST)
    if form.is_valid():
        article = form.save()
        return redirect('articles:detail', article.pk)
    # the reason is saved in form.errors
    # print(f'Error: {form.errors}')

    # also by hand over the form again, the error message can be printed on the new.html
    context = {
        'form': form,
    }
    return render(request, 'articles/new.html', context)

2.3. templates.html

new.html

<h1>NEW</h1>
<form action="{% url 'articles:create' %}" method="POST">
    {% csrf_token %}
    {{ form.as_p }}
    <input type="submit">
</form>

3. Read

3.1. urls.py

app_name = 'articles'
urlpatterns = [
    path('index/', views.index, name='index'),
    path('<int:pk>/', views.detail, name='detail'),
]

3.2. views.py

def index(request):
    articles = Article.objects.all()
    context = {
        'articles': articles,
    }
    return render(request, 'articles/index.html', context)

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

3.3. templates.html

index.html

<h1>Articles</h1>
<hr>
{% for article in articles %}
    <p> title: {{ article.title }} </p>
    <p> content: {{ article.content }} </p>
    <hr>
{% endfor %}

detail.html

<h1>DETAIL</h1>
<h3>{{ article.pk }}th article</h3>
<hr>
<p> title: {{ article.title }} </p>
<p> content: {{ article.content }} </p>
<p> created at: {{ article.created_at }} </p>
<p> updated at: {{ article.updated_at }} </p>
<hr>

4. Update

4.1. urls.py

app_name = 'articles'
urlpatterns = [
    path('<int:pk>/edit/', views.edit, name='edit'),
    path('<int:pk>/update/', views.update, name='update'),
]

4.2. views.py

def edit(request, pk):
    article = Article.objects.get(pk=pk)
    # make hte instance based on another data
    form = ArticleFrom(instance=aritcle)
    context = {
        'form': form,
    }
    return render(request, 'articles/edit.html', context)

def update(request, pk):
    article = Article.objects.get(pk=pk)
    form = ArticleForm(request.POST, instance=article)
    if form.is_Valid():
        form.save()
        return redirect('articles:detial', article.pk)
    context = {
        'form': form,
    }
    return render(request, 'articles/edit.html', context)

4.3. templates.html

edit.html

<h1>EDIT</h1>
<form action="{% url 'articles:update' article.pk %}" method="POST">
    {% csrf_token %}
    {{ form.as_p }}
    <input type="submit">
</form>

5. Delete

5.1. urls.py

app_name = 'articles'
urlpatterns = [
    path('<int:pk>/delete/', views.delete, name='delete'),
]

5.2. views.py

def delete(request, pk):
    article = Article.objects.get(pk=pk)
    article.delete()
    return redirect('articles:index')

5.3. templates.html

detail.html

<h1>DETAIL</h1>
<h3>{{ article.pk }}th article</h3>
<hr>
<p> title: {{ article.title }} </p>
<p> content: {{ article.content }} </p>
<p> created at: {{ article.created_at }} </p>
<p> updated at: {{ article.updated_at }} </p>
<hr>
<form action="{% url 'articles:delete' article.pk %}" method="POST">
    {% csrf_token %}
    <input type="submit" value="DELETE">
</form>

6. Handling HTTP Request Methods

By distinguishing the request method, url and view codes can be written more concisely.

6.1. View Decoarators

from django.views.decorators.http import

  • @require_http_methods(['',])
    • Allow only the methods in the list
  • @require_POST
    • Allow POST only
  • @require_safe
    • Allow GET only

6.2. urls.py

app_name = 'articles'
urlpatterns = [
    path('create/', views.create, name='create'),
    path('index/', views.index, name='index'),
    path('<int:pk>/', views.detail, name='detail'),
    path('<int:pk>/update/', views.update, name='update'),
    path('<int:pk>/delete/', views.delete, name='delete'),
]

6.3. views.py

from django.views.decorators.http import require_http_methods, require_safe, require_POST
from .forms import ArticleForm

# Create an Article
@require_http_methods(['GET','POST'])
def create(request):
    if request.method == 'POST':    # Post an article
        form = ArticleForm(request.POST)
        if form.is_valid():
            article = form.save()
            return redirect('articles:detail', article.pk)
    else:                           # Get the article form
        form  = ArticleForm()
    context = {
        'form': form,
    }
    return render(request, 'articles/create.html', context)

# Read Article List
@require_safe
def index(request):
    articles = Article.objects.all()
    context = {
        'articles': articles,
    }
    return render(request, 'articles/index.html', context)

# Read Article Detail
@require_safe
def detail(request, pk):
    article = Article.objects.get(pk=pk)
    context = {
        'article': article,
    }
    return render(request, 'articles/detail.html', context)

# Update an Article
@require_http_methods(['GET','POST'])
def update(request, pk):
    article = Article.objects.get(pk=pk)
    if request.method == 'POST':        # Update an article
        form = ArticleForm(request.POST, instance=article)
        if form.is_Valid():
            form.save()
            return redirect('articles:detail', article.pk)
    else:                               # Get the article form with data
        form = ArticleFrom(instance=aritcle)
    context = {
        'form': form,
    }
    return render(request, 'articles/update.html', context)

# Delete an Article
@require_POST
def delete(request, pk):
    article = Article.objects.get(pk=pk)
    if reqeust.mehtod == ' POST':
        article.delete()
        return redirect('articles:index')
    return redirect('articles:detial', artilce.pk)
이전 포스트

Django Basic CRUD

다음 포스트

Django Fixtures

작성자 프로필
전체 글 (127)
  • Animation
    • Backend
      • Django
      • Spring
    • DevOps
      • AWS
      • CI&CD
      • Docker
      • Git
      • Gunicorn
      • Kubernetes
      • Nginx
    • Frontend
      • Gatsby
      • React
      • Vue
    • Knowledge
      • .etc
      • Algorithm
      • Data Structure
      • Database
      • Design Pattern
      • Interview
      • Network
      • Web
    • Language
      • CSS
      • HTML
      • Java
      • JavaScript
      • Linux
      • Python

    Copyright © 2023 Byongho96  & Powered by Gatsby