Django Forms සිංහලෙන් | Model Forms | Web Development Guide Sri Lanka

Django Forms සිංහලෙන් | Model Forms | Web Development Guide Sri Lanka

Django Forms කියන්නේ මොකක්ද?

සාමාන්‍යයෙන් වෙබ් ඇප්ලිකේෂන් එකකදී user ගෙන් data ගන්න එක (උදාහරණයක් විදියට login details, comments, blog posts වගේ දේවල්) කියන්නේ අත්‍යවශ්‍ය දෙයක්. මේකට අපි HTML Forms හදනවා. ඒත්, ඔයාලා හිතලා තියෙනවද මේ HTML Forms manage කරන එක කොච්චර සංකීර්ණ වෙන්න පුළුවන්ද කියලා? Data validation, security (විශේෂයෙන් CSRF attacks), සහ error handling වගේ දේවල් manually කරනකොට වෙලාවත් යනවා, වැරදි වෙන්න තියෙන ඉඩත් වැඩියි.

මෙන්න මේ වෙලාවට තමයි Django Forms අපේ ගලවාගැනීමට එන්නේ! Django Forms කියන්නේ Django framework එකේ තියෙන powerful feature එකක්. මේකෙන් HTML Forms හදන එක, ඒවා validate කරන එක, සහ user input handle කරන එක ගොඩක් පහසු කරනවා. හරියට ගේකට වහලක් වගේ, Form එකක් නැතුව data එකක් ගන්න බැහැනේ නේද?

Django Forms වල වාසි මොනවද?

  • සරල බව: HTML Forms manually ලියන එකට වඩා ගොඩක් සරලව forms design කරන්න පුළුවන්.
  • Data Validation: User ගෙන් එන data හරියට validate කරන්න පුළුවන් (අංක විතරක්, ඊමේල් format එකට, password strength වගේ දේවල්).
  • Security: CSRF (Cross-Site Request Forgery) වගේ පොදු security threats වලින් automatically ආරක්ෂා කරනවා.
  • Reusability: එක form එකක් හදලා ඒක project එකේ විවිධ තැන්වල use කරන්න පුළුවන්.
  • Error Handling: Validation errors user ට පැහැදිලිව පෙන්වන්න පුළුවන් විදියට manage කරනවා.

මූලික Form එකක් හදමු!

මුලින්ම අපි සරල contact form එකක් හදලා බලමු. මේකට ඔයාගේ Django project එකේ app එක ඇතුලේ forms.py කියලා file එකක් හදන්න ඕනේ. (නැත්නම් හදන්න)

# myproject/myapp/forms.py

from django import forms

class ContactForm(forms.Form):
    name = forms.CharField(label='ඔබේ නම', max_length=100)
    email = forms.EmailField(label='ඔබේ ඊමේල් ලිපිනය')
    message = forms.CharField(label='ඔබේ පණිවිඩය', widget=forms.Textarea)

මේ ContactForm එක forms.Form class එකෙන් inherit කරනවා. ඒ කියන්නේ මේක සාමාන්‍ය Django Form එකක්. අපි මේකට fields තුනක් එකතු කරලා තියෙනවා:

  • name: මේක CharField එකක්, ඒ කියන්නේ text input එකක්. max_length එක 100 ට සීමා කරලා තියෙනවා.
  • email: මේක EmailField එකක්. Django automatically මේක ඊමේල් format එකට validate කරනවා.
  • message: මේකත් CharField එකක්, ඒත් widget=forms.Textarea කියලා දුන්න නිසා මේක text area එකක් විදියට පෙන්නනවා.

label එකෙන් form එකේ field එකට උඩින් පෙන්නන නම define කරනවා. මේක අනිවාර්ය නැති වුණත්, user-friendly forms හදන්න ගොඩක් වැදගත්.

Form එකක් Render කරලා Submit කරමු

Form එකක් හැදුවට මදි, ඒක user ට පේන්න render කරන්නත් ඕනේ, user ගෙන් එන data handle කරන්නත් ඕනේ. හරියට කඩේකට බඩු ගත්තට මදි, ඒවාට හොඳට අසුරලා අලෙවි කරන්නත්, අලෙවි වුණාම ඒවයේ බිල්පත් හදන්නත් ඕනේ වගේ වැඩක්.

Template එකේ Form එක පෙන්නන හැටි

Form එකක් template එකකට යවන්න කලින්, අපි views.py file එකේ view function එකක් හදන්න ඕනේ. මේකෙන් form instance එකක් හදලා template එකට pass කරනවා.

# myproject/myapp/views.py

from django.shortcuts import render, redirect
from .forms import ContactForm # අපි හදපු ContactForm එක import කරගන්නවා

def contact_view(request):
    if request.method == 'POST':
        form = ContactForm(request.POST) # POST request එකකින් ආපු data වලින් Form එක fill කරනවා
        if form.is_valid():
            # Form data valid නම්, මෙතනින් අපිට ඒ data use කරන්න පුළුවන්
            name = form.cleaned_data['name']
            email = form.cleaned_data['email']
            message = form.cleaned_data['message']
            
            # මෙතනින් අපිට email එකක් යවන්න පුළුවන්, database එකට save කරන්න පුළුවන්...
            # දැන් අපි redirect කරමු successful message එකක් පෙන්නන්න
            return redirect('success_page') # success_page කියන්නේ ඔයාගේ url එකක්
    else:
        form = ContactForm() # GET request එකකට හිස් form එකක් හදනවා

    return render(request, 'myapp/contact.html', {'form': form})

def success_view(request):
    return render(request, 'myapp/success.html') # සාර්ථකව submission එකෙන් පස්සේ පෙන්නන page එක

ඊළඟට, urls.py file එකේ මේ views වලට URLs define කරන්න ඕනේ:

# myproject/myapp/urls.py

from django.urls import path
from . import views

urlpatterns = [
    path('contact/', views.contact_view, name='contact'),
    path('success/', views.success_view, name='success_page'),
]

දැන් myapp/contact.html template file එක හදමු:

<!-- myproject/myapp/templates/myapp/contact.html -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Contact Us</title>
    <style>
        body { font-family: Arial, sans-serif; margin: 20px; }
        .form-container { max-width: 500px; margin: 0 auto; padding: 20px; border: 1px solid #ddd; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }
        h1 { text-align: center; color: #333; }
        .form-field p { margin-bottom: 15px; }
        .form-field label { display: block; margin-bottom: 5px; font-weight: bold; color: #555; }
        .form-field input[type="text"],
        .form-field input[type="email"],
        .form-field textarea {
            width: 100%;
            padding: 10px;
            border: 1px solid #ccc;
            border-radius: 4px;
            box-sizing: border-box; /* Ensures padding doesn't affect overall width */
        }
        .form-field textarea { resize: vertical; min-height: 100px; }
        .form-field ul.errorlist { color: red; list-style-type: none; padding: 0; margin-top: 5px; font-size: 0.9em; }
        .form-field ul.errorlist li { margin-bottom: 3px; }
        button {
            background-color: #007bff;
            color: white;
            padding: 10px 20px;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            font-size: 16px;
            width: 100%;
        }
        button:hover { background-color: #0056b3; }
    </style>
</head>
<body>
    <div class="form-container">
        <h1>අපිට කතා කරන්න!</h1>
        <form method="post">
            {% csrf_token %} <!-- මේක අනිවාර්යයි! -->
            <div class="form-field">
                {{ form.as_p }} <!-- මේකෙන් form එකේ හැම field එකක්ම <p> tag එකක් ඇතුලේ render කරනවා -->
            </div>
            <button type="submit">පණිවිඩය යවන්න</button>
        </form>
    </div>
</body>
</html>

myapp/success.html එකත් මේ විදියට හදමු:

<!-- myproject/myapp/templates/myapp/success.html -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Success!</title>
    <style>
        body { font-family: Arial, sans-serif; margin: 20px; display: flex; justify-content: center; align-items: center; min-height: 80vh; }
        .message-container { text-align: center; padding: 30px; border: 1px solid #d4edda; border-radius: 8px; background-color: #d4edda; color: #155724; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }
        h1 { color: #155724; }
        p { font-size: 1.1em; }
        a { color: #007bff; text-decoration: none; }
        a:hover { text-decoration: underline; }
    </style>
</head>
<body>
    <div class="message-container">
        <h1>සාර්ථකයි!</h1>
        <p>ඔබගේ පණිවිඩය සාර්ථකව ලැබුණා. ඉක්මනින්ම අපි ඔබව සම්බන්ධ කරගන්නම්.</p>
        <p><a href="{% url 'contact' %}">තවත් පණිවිඩයක් යවන්න?</a></p>
    </div>
</body>
</html>

මෙහිදී වැදගත්ම දේ තමයි {% csrf_token %} tag එක. මේක අනිවාර්යයෙන්ම ඔයාගේ form එක ඇතුලේ දාන්න ඕනේ. මේක Django වලට Cross-Site Request Forgery (CSRF) attacks වලින් ඔයාගේ form එක ආරක්ෂා කරන්න උදව් කරනවා.

{{ form.as_p }} කියන එකෙන් Django ට කියනවා form එකේ හැම field එකක්ම <p> tag එකක් ඇතුලේ render කරන්න කියලා. ඒ වගේම {{ form.as_ul }} (<li> tag ඇතුලේ), {{ form.as_table }} (<tr> tag ඇතුලේ) වගේ options තියෙනවා. මේවා basic forms ඉක්මනින් render කරන්න ගොඩක් හොඳයි. Custom HTML වලින් forms render කරන්නත් පුළුවන්, ඒක ගැන අපි ටිකක් පස්සේ කතා කරමු.

Form Submission Handle කරන හැටි

views.py එකේ contact_view function එක දිහා ආයෙත් බලමු:

def contact_view(request):
    if request.method == 'POST':
        form = ContactForm(request.POST) # POST request එකෙන් ආපු data වලින් Form එක fill කරනවා
        if form.is_valid():
            # Form data valid නම්, මෙතනින් අපිට ඒ data use කරන්න පුළුවන්
            name = form.cleaned_data['name']
            email = form.cleaned_data['email']
            message = form.cleaned_data['message']
            
            # ... database එකට save කරනවා හෝ email එකක් යවනවා ...
            return redirect('success_page') 
    else:
        form = ContactForm() # GET request එකකට හිස් form එකක් හදනවා

    return render(request, 'myapp/contact.html', {'form': form})

මෙතනදී වැදගත් කරුණු කිහිපයක් තියෙනවා:

  • request.method == 'POST': User submit කරලා තියෙන්නේ POST method එකෙන්ද කියලා බලනවා. Forms submit වෙන්නේ හැමවිටම POST method එකකින්.
  • form = ContactForm(request.POST): POST request එකත් එක්ක එන data (request.POST) අරගෙන ඒකෙන් අපේ form instance එක populate කරනවා.
  • if form.is_valid():: මේක තමයි මැජික් එක! මේ function එකෙන් Django Forms වලට අපි define කරපු validations (උදා: max_length, EmailField වල ඊමේල් format එක) ඔක්කොම check කරනවා. හැම validation එකක්ම pass නම් True return කරනවා.
  • form.cleaned_data: form.is_valid() එක True නම්, validation pass වුණු, clean කරපු data set එකක් form.cleaned_data dictionary එකෙන් අපිට access කරන්න පුළුවන්. මේක ගොඩක් වැදගත්, මොකද මේ data ආරක්ෂිතයි සහ අපිට database එකට save කරන්න වගේ දේවල් වලට කෙලින්ම use කරන්න පුළුවන්.
  • return redirect('success_page'): Form එක successful නම්, user ව වෙනත් page එකකට redirect කරන එක හොඳ practice එකක්. නැත්නම් user page එක refresh කරොත් form එක ආයෙත් submit වෙන්න පුළුවන්.

Model Forms - ඉක්මනින් වැඩේ කරමු!

බොහෝ වෙලාවට අපිට forms අවශ්‍ය වෙන්නේ database එකේ තියෙන Models එක්ක වැඩ කරන්න. උදාහරණයක් විදියට, අලුත් Blog Post එකක් database එකට add කරන්න, තියෙන එකක් update කරන්න. මේ වගේ අවස්ථාවලදී forms.Form class එක use කරනවාට වඩා forms.ModelForm class එක use කරන එක ගොඩක් වාසිදායකයි. මේක හරියට "කෑම එකක් හදන්න අවශ්‍ය බඩු ලැයිස්තුව" වගේ වැඩක්. Django ට අපි කියනවා මේ Model එකට අදාළ form එක හදලා දෙන්න කියලා, එතකොට Django ඒක automatically හදනවා.

Model Form එකක් හදමු

මුලින්ම අපි සරල Blog Post Model එකක් හදමු.

# myproject/myapp/models.py

from django.db import models
from django.utils import timezone # timestamp එකට

class BlogPost(models.Model):
    title = models.CharField(max_length=200, verbose_name="පෝස්ට් එකේ මාතෘකාව")
    content = models.TextField(verbose_name="අන්තර්ගතය")
    author = models.CharField(max_length=100, verbose_name="කතෘ")
    published_date = models.DateTimeField(default=timezone.now)

    def __str__(self):
        return self.title

දැන් මේ BlogPost Model එකට අදාළ ModelForm එක හදමු. මේකත් forms.py file එකේම දාන්න පුළුවන්.

# myproject/myapp/forms.py

from django import forms
from .models import BlogPost # අපි හදපු Model එක import කරගන්නවා

class BlogPostForm(forms.ModelForm):
    class Meta:
        model = BlogPost # මේ form එක ಯಾವ Model එකටද අදාළ වෙන්නේ කියලා කියනවා
        fields = ['title', 'content', 'author'] # form එකේ පෙන්නන්න ඕනේ fields මොනවද?
        # නැත්නම් fields = '__all__' කියලා දුන්නොත් හැම field එකක්ම පෙන්නනවා
        # exclude = ['published_date'] # මේ field එක form එකේ පෙන්නන්න එපා කියලා කියනවා
        labels = { # fields වලට custom labels දෙන්නත් පුළුවන්
            'title': 'මාතෘකාව',
            'content': 'පෝස්ට් අන්තර්ගතය',
            'author': 'කතෘගේ නම',
        }
        widgets = { # fields වලට custom widgets දෙන්නත් පුළුවන් (උදා: textarea for content)
            'content': forms.Textarea(attrs={'rows': 4, 'cols': 40}),
        }

BlogPostForm එක forms.ModelForm එකෙන් inherit කරනවා. මෙතනදී වැදගත් දේ තමයි Meta class එක.

  • model = BlogPost: මේකෙන් Django ට කියනවා මේ form එක BlogPost Model එකට අදාළයි කියලා.
  • fields = ['title', 'content', 'author']: මේකෙන් කියනවා Model එකේ තියෙන title, content, author කියන fields form එකේ පෙන්නන්න කියලා. published_date එක අපි exclude කළා, මොකද ඒක automatically generate වෙන නිසා.
  • fields = '__all__': මේකෙන් Model එකේ තියෙන හැම field එකක්ම form එකේ පෙන්නනවා.
  • exclude = ['published_date']: මේකෙන් කියනවා මේ field එක හැර අනිත් හැම field එකක්ම form එකේ පෙන්නන්න කියලා.
  • labels සහ widgets: මේවා අමතර options. labels වලින් fields වලට වඩා user-friendly නම් දෙන්න පුළුවන්. widgets වලින් field එක render වෙන HTML element එක modify කරන්න පුළුවන්.

Model Form එකකින් Data Save කරන හැටි

Model Form එකක් handle කරන views සාමාන්‍ය Form එකක් handle කරනවාට වඩා පහසුයි, විශේෂයෙන් data save කරනකොට.

# myproject/myapp/views.py

from django.shortcuts import render, redirect, get_object_or_404
from .forms import BlogPostForm # අපි හදපු ModelForm එක import කරගන්නවා
from .models import BlogPost # BlogPost Model එකත් import කරගන්නවා

def create_blog_post(request):
    if request.method == 'POST':
        form = BlogPostForm(request.POST)
        if form.is_valid():
            form.save() # මෙන්න මේක තමයි ModelForm එකේ මැජික් එක!
            return redirect('blog_list') # blog_list කියන්නේ blog posts පෙන්නන page එකට redirect කරන URL එක
    else:
        form = BlogPostForm()
    return render(request, 'myapp/create_post.html', {'form': form})

def edit_blog_post(request, pk):
    post = get_object_or_404(BlogPost, pk=pk) # edit කරන්න ඕන post එක ගන්නවා
    if request.method == 'POST':
        form = BlogPostForm(request.POST, instance=post) # තියෙන post එකෙන් form එක populate කරනවා
        if form.is_valid():
            form.save() # update කරනවා
            return redirect('blog_list')
    else:
        form = BlogPostForm(instance=post) # GET request එකකට තියෙන post එකේ data එක්ක form එක පෙන්නනවා
    return render(request, 'myapp/edit_post.html', {'form': form, 'post': post})

create_blog_post view එකේදී, form.save() කියන method එකෙන් validation pass වුණු data අරගෙන අලුත් BlogPost object එකක් database එකට save කරනවා. මේක කොච්චර ලේසිද නේද?

edit_blog_post view එකේදී, අපි තියෙන BlogPost object එකක් edit කරනවා. මෙතනදී BlogPostForm(request.POST, instance=post) කියලා දුන්නහම Django ට කියනවා POST data වලින් මේ form එක fill කරන්න, හැබැයි මේ post object එක update කරන්නයි ඕනේ කියලා. form.save() ඒ වැඩේ බලාගන්නවා.

Template එකත් කලින් වගේමයි, {{ form.as_p }} use කරන්න පුළුවන්:

<!-- myproject/myapp/templates/myapp/create_post.html -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Create New Blog Post</title>
    <style>
        body { font-family: Arial, sans-serif; margin: 20px; }
        .form-container { max-width: 600px; margin: 0 auto; padding: 20px; border: 1px solid #ddd; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }
        h1 { text-align: center; color: #333; }
        .form-field p { margin-bottom: 15px; }
        .form-field label { display: block; margin-bottom: 5px; font-weight: bold; color: #555; }
        .form-field input[type="text"],
        .form-field textarea {
            width: 100%;
            padding: 10px;
            border: 1px solid #ccc;
            border-radius: 4px;
            box-sizing: border-box;
        }
        .form-field textarea { resize: vertical; min-height: 150px; }
        .form-field ul.errorlist { color: red; list-style-type: none; padding: 0; margin-top: 5px; font-size: 0.9em; }
        .form-field ul.errorlist li { margin-bottom: 3px; }
        button {
            background-color: #28a745;
            color: white;
            padding: 10px 20px;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            font-size: 16px;
            width: 100%;
        }
        button:hover { background-color: #218838; }
    </style>
</head>
<body>
    <div class="form-container">
        <h1>අලුත් Blog Post එකක් හදන්න</h1>
        <form method="post">
            {% csrf_token %}
            {{ form.as_p }}
            <button type="submit">Post එක Save කරන්න</button>
        </form>
    </div>
</body>
<!-- (edit_post.html එකත් මේ වගේමයි, මාතෘකාව edit post කියලා දාන්න) -->
</html>

URLs ටිකත් urls.py එකට එකතු කරන්න අමතක කරන්න එපා:

# myproject/myapp/urls.py

from django.urls import path
from . import views

urlpatterns = [
    # ... contact form urls ...
    path('blog/new/', views.create_blog_post, name='create_blog_post'),
    path('blog/edit/<int:pk>/', views.edit_blog_post, name='edit_blog_post'),
    # path('blog/', views.blog_list_view, name='blog_list'), # blog list page එකක් තියෙනවා නම්
]

Validation සහ Error Handling

Django Forms වල තියෙන ප්‍රධානම වාසියක් තමයි robust validation system එක. වැරදි data database එකට යන එක මේකෙන් නවත්වනවා, ඒ වගේම user ට වැරැද්ද පෙන්නලා නිවැරදි කරන්න උපකාර කරනවා. හරියට exam එකකට කලින් පොත් check කරනවා වගේ වැඩක්!

Built-in Validation

අපි කලින් දැක්කා වගේ, CharField(max_length=...), EmailField වගේ field types වලින් already validation ගොඩක් එනවා.

  • required=True (default): Field එකක් අනිවාර්යයෙන්ම fill කරන්න ඕනේ කියලා කියනවා.
  • max_length, min_length: String fields වල දිග පාලනය කරනවා.
  • max_value, min_value: Number fields වල අගය පාලනය කරනවා.
  • EmailField, URLField, RegexField: නිශ්චිත format වලට validate කරනවා.

මේ validation rules වලින් fail වුණොත්, form.is_valid() එක False return කරනවා. Template එකේදී errors පෙන්නන්න මේ විදියට කරන්න පුළුවන්:

<!-- myproject/myapp/templates/myapp/contact.html (සමහර කොටස්) -->
<div class="form-field">
    <label for="{{ form.name.id_for_label }}">{{ form.name.label }}:</label>
    <input type="text" id="{{ form.name.id_for_label }}" name="{{ form.name.html_name }}" value="{{ form.name.value|default_if_none:'' }}">
    {% if form.name.errors %}
        <ul class="errorlist">
            {% for error in form.name.errors %}
                <li>{{ error }}</li>
            {% endfor %}
        </ul>
    {% endif %}
</div>

<!-- මේක {{ form.as_p }} වලින් auto generate වෙනවා -->

{{ form.name.errors }} කියලා දැම්මොත් ඒ field එකට අදාළ හැම error එකක්ම පෙන්නනවා. {{ form.errors }} කියලා දැම්මොත් මුළු form එකටම අදාළ errors පෙන්නනවා.

Custom Validation

සමහර වෙලාවට අපිට Django වල built-in validators වලින් කරන්න බැරි custom validation rules ඕනේ වෙනවා. උදාහරණයක් විදියට, "මාතෘකාවට 'Django' කියන වචනය අනිවාර්යයෙන්ම තියෙන්න ඕනේ" වගේ දෙයක්. මේකට clean_<field_name> methods සහ form එකේ clean() method එක use කරන්න පුළුවන්.

Field-specific Validation: clean_<field_name>

මේ method එක define කරන්නේ form class එක ඇතුලේ. මේකෙන් කරන්නේ නිශ්චිත field එකක data validate කරන එක.

# myproject/myapp/forms.py (BlogPostForm එකට එකතු කරමු)

from django import forms
from .models import BlogPost
from django.core.exceptions import ValidationError # Error එකක් පෙන්නන්න මේක ඕනේ

class BlogPostForm(forms.ModelForm):
    class Meta:
        model = BlogPost
        fields = ['title', 'content', 'author']
        labels = {
            'title': 'මාතෘකාව',
            'content': 'පෝස්ට් අන්තර්ගතය',
            'author': 'කතෘගේ නම',
        }

    def clean_title(self): # title field එකට custom validation
        title = self.cleaned_data['title']
        if "Django" not in title:
            raise ValidationError("මාතෘකාවට 'Django' කියන වචනය අනිවාර්යයෙන්ම තිබිය යුතුය.")
        return title

    def clean_author(self): # author field එකට custom validation
        author = self.cleaned_data['author']
        # 'Admin' කෙනෙක් විදියට Post කරන්න බෑ කියමු
        if author.lower() == 'admin':
            raise ValidationError("Admin නමින් Post කිරීම තහනම්.")
        return author

clean_title method එක ඇතුලේ අපි self.cleaned_data['title'] කියලා කලින් validate වුණු title එක ගන්නවා. ඊට පස්සේ අපේ custom logic එක implement කරලා, validation fail වුණොත් ValidationError එකක් raise කරනවා.

Global Form Validation: clean()

සමහර වෙලාවට validation එකක් කරන්න form එකේ fields කිහිපයක data අවශ්‍ය වෙනවා. උදාහරණයක් විදියට, "කතෘගේ නම 'Guest' නම්, Post එකේ මාතෘකාව 'Guest Post' කියලා පටන් ගන්න ඕනේ" වගේ දෙයක්. මේ වගේ අවස්ථාවලට clean() method එක use කරනවා. මේ method එක හැම field-specific validation එකකින් පස්සේ call වෙනවා.

# myproject/myapp/forms.py (BlogPostForm එකට එකතු කරමු)

# ... (ඉහත කේතය) ...

class BlogPostForm(forms.ModelForm):
    # ... (Meta class සහ clean_title, clean_author methods) ...

    def clean(self): # මුළු form එකටම අදාළ validation
        cleaned_data = super().clean() # මුලින්ම parent class එකේ clean method එක call කරනවා
        title = cleaned_data.get('title')
        author = cleaned_data.get('author')

        if author and title and author.lower() == 'guest' and not title.startswith('Guest Post'):
            self.add_error('title', "ඔබ Guest කෙනෙක් නම්, මාතෘකාව 'Guest Post' ලෙස ආරම්භ විය යුතුය.")
            # නැත්නම් raise ValidationError("ඔබ Guest කෙනෙක් නම්, මාතෘකාව 'Guest Post' ලෙස ආරම්භ විය යුතුය.")

        return cleaned_data

clean() method එක ඇතුලේ super().clean() කියලා මුලින්ම call කරන්නේ, කලින් කරපු field-specific validations ඔක්කොම run වෙලා cleaned_data ටික ලබාගන්න. ඊට පස්සේ self.add_error() use කරලා නිශ්චිත field එකකට error එකක් add කරන්න පුළුවන්. ValidationError එකක් raise කරොත් ඒක form එකේ non-field errors විදියට පෙන්නනවා.

CSRF Protection

{% csrf_token %} tag එක ගැන අපි කලින් කතා කළා. මේක නැති වුණොත් ඔයාට "CSRF verification failed" වගේ error එකක් එන්න පුළුවන්. මේක Django වල ගොඩක් වැදගත් security feature එකක්, ඒ නිසා හැම POST form එකකම මේක දාන්න අමතක කරන්න එපා. හරියට ගෙදරට අගුලක් දානවා වගේ දෙයක්, නැත්නම් නිකන්ම අරින්න පුළුවන්.

Best Practices සහ Tips

Django Forms use කරනකොට ඔයාගේ project එකේ quality එක වැඩි කරගන්න පුළුවන් පොඩි tricks කිහිපයක් මෙන්න:

  • හැමවිටම ModelForm use කරන්න පුළුවන් නම් use කරන්න: Database එකත් එක්ක වැඩ කරන forms වලට ModelForm use කරන එක ඔයාගේ code එක සරල කරනවා වගේම error chances අඩු කරනවා.
  • forms.py file එකක් පාවිච්චි කරන්න: ඔයාගේ app එක ඇතුලේ forms ටික වෙනම forms.py file එකක organize කරන්න. මේක code readability එක වැඩි කරනවා.
  • Redirect after POST (PRG pattern): Form එකක් submit කරාට පස්සේ user ව වෙනත් URL එකකට redirect කරන්න. (Post/Redirect/Get pattern). මේකෙන් user ට browser එකේ refresh කරද්දි form එක ආයෙත් submit වීම වළක්වනවා.
  • Django Crispy Forms: මේක third-party library එකක්. මේකෙන් Bootstrap, Tailwind CSS වගේ frontend frameworks වලට අදාළව forms ලස්සනට style කරන්න පුළුවන්. Manual HTML styling කරදරයෙන් බේරෙන්න පුළුවන්. pip install django-crispy-forms කරලා INSTALLED_APPS වලට එකතු කරලා {% load crispy_forms_tags %} කරලා {{ form|crispy }} වගේ use කරන්න පුළුවන්.
  • Error Messages User-Friendly කරන්න: labels සහ custom validation messages වලින් user ට වැරැද්ද තේරුම් ගන්න පහසු කරන්න.

Customizing Form Rendering: {{ form.as_p }} වගේ දේවල් basic forms වලට හොඳ වුණත්, complex layouts වලට ඔයාට manually fields render කරන්න පුළුවන්.

<div class="form-group">
    <label for="{{ form.title.id_for_label }}">{{ form.title.label }}</label>
    <input type="text" name="{{ form.title.html_name }}" id="{{ form.title.id_for_label }}" class="form-control" value="{{ form.title.value|default_if_none:'' }}">
    {% if form.title.errors %}<div class="text-danger">{{ form.title.errors }}</div>{% endif %}
</div>

මේ වගේ code block එකක් හරහා ඔයාට හැම field එකක්ම ඔයාට ඕන විදියට style කරගන්න පුළුවන්.

නිගමනය

ඉතින් යාලුවනේ, Django Forms කියන්නේ Django Web Development වලදී නැතුවම බැරි කොටසක්. මේක අපේ වැඩ ගොඩක් පහසු කරනවා වගේම, web application එකට security සහ robustness එකතු කරනවා. අද අපි සාමාන්‍ය Django Forms වලින් පටන් අරන්, Model Forms වල පහසුව, data submit කරන හැටි, ඒ වගේම validation සහ error handling කොහොමද කරන්නේ කියලා ගැඹුරින් ඉගෙන ගත්තා.

මේ tutorial එකෙන් ඔයාලට Django Forms ගැන හොඳ අවබෝධයක් ලැබෙන්න ඇති කියලා මම හිතනවා. මේ concepts ඔයාලගේ project වලට implement කරලා බලන්න. එතකොට තමයි මේවා ඔලුවට හොඳටම යන්නේ.

මේ ලිපිය ගැන ඔයාගේ අදහස්, ප්‍රශ්න, නැත්නම් ඔයා මේවා use කරනකොට මුහුණ දීපු අත්දැකීම් පහළින් comment කරන්න. අපි හැමෝටම එකතු වෙලා ඉගෙන ගන්න පුළුවන්!

ඊළඟ tutorial එකකින් හමුවෙමු! Happy Coding!