# Form & ModelForm

\ <br>

### `.order_by()`

> Sort in reverse order by pk

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

\ <br>

## ModelForm

<br>

### Defining ModelForm

> forms.py

```python
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
        # Include all fields
        fields = '__all__'
```

<br>

### Using `ModelForm` in View

> view\.py

```python
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':
        # Save data to Article table
        form = ArticleForm(request.POST)
        if form.is_valid():
            form.save()
            # redirect to detail
            return redirect('articles:index')
        print('errors?',form.errors)
        print('cleaned_data?',form.cleaned_data)
        
    # GET /articles/create    
    else:
        # Empty 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)
```

<br>

### Conditional processing with `request.resolver_match.url_name`

> form.html

* The basis for branching is `url_name`
* If you use `path`, you have to change it every time the `url` changes!

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

    <h2>Write a post</h2>
    
{% else %}

    <h2>Edit post</h2>

{% endif %}
```

\ <br>

### Output using `loop` or `bootstrap4`

> form.html

```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 %}
    
    <!-- Using 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>

    <!-- Using bootstrap4 -->
    <form action="" method="POST">
        {% csrf_token %}
        {% bootstrap_form form %}
        <button class="btn btn-primary"> Submit</button>
    </form>

{% endblock %}
```

\ <br>

> Enter shell

```bash
python manage.py shell_plus
```

<br>

> shell

```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)>
```

<br>

> Collection of inputs composed of `p` tags

```shell
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>'
```

<br>

> Collection of inputs composed of table

```shell
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>'
```

<br>

```shell
In [3]: from articles.forms import ArticleForm                                                            

In [4]: form = ArticleForm({'title':'title'})                                                              

In [5]: print(form)                                                                                       
<tr><th><label for="id_title">Title:</label></th><td><input type="text" name="title" value="title" 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>
```

\ <br>

### 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 `{% for %}` 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 %}
```

\ <br>

### Form rendering options

> There are other output options though for the `<label>`/`<input>` pairs:

* `{{ form.as_table }}` will render them as table cells wrapped in `<tr>` tags
* `{{ form.as_p }}` will render them wrapped in `<p>` tags
* `{{ form.as_ul }}` will render them wrapped in `<li>` tags

Note that you'll have to provide the surrounding `<table>` or `<ul>` elements yourself.

Here's the output of `{{ form.as_p }}` for our `ContactForm` instance:

\ <br>

### Using Django Bootstrap

<br>

> Install

```bash
pip install django-bootstrap4
```

<br>

> Modify settings.py

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

<br>

> Declare that you will use bootstrap in base.html

```html
<!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>
```

<br>

> detail.html - Also declare in templates where bootstrap is applied

```html
{% 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">Edit</button>   
    </form>

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

{% endblock  %}
```

\ <br>

`+`

### Git

> Go back to specific commit

```bash
git checkout f008d8f
```

<br>

> Create test branch and move

```bash
$ 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
```

<br>

> Check reference log

```bash
git reflog
```

<br>

> Check where head is

```bash
$ git log --oneline
fc58709 (HEAD -> master, origin/master, origin/HEAD) README.md added
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
```

<br>

> Go back to test branch

```bash
$ git checkout test
Switched to branch 'test'
```

<br>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://chloe-codes1.gitbook.io/til/django/django-101/06_form_and_modelform.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
