Django Views සහ URLs: සම්පූර්ණ සිංහල Tutorial එකක් | Python Web Dev

Django Views සහ URLs: සම්පූර්ණ සිංහල Tutorial එකක් | Python Web Dev

ආයුබෝවන්! Django Views සහ URLs හරහා Web App එකක් හදමු!

කොහොමද ඉතින් හැමෝටම? අද අපි කතා කරන්න යන්නේ Django web development වල ගොඩක් වැදගත් කොටසක් ගැන. ඒ තමයි Views සහ URL Routing.

ඔයා Django වලින් web application එකක් හදනවා නම්, user කෙනෙක්ගේ request එකක් අරගෙන, ඒකට අදාළ response එකක් දෙන්නේ කොහොමද කියලා දැනගන්න එක අත්‍යවශ්‍යයි. ඒක තමයි Views සහ URLs යොදාගන්නේ. මේක හරියට ඔයාගේ website එකට එන අමුත්තෙක්ට (user request) නිවැරදි තැනට ගිහින් (URL routing) එයාලට ඕන දේ (view logic) පෙන්වන එක වගේ වැඩක්.

මේ tutorial එක අවසාන වෙනකොට, ඔයාට Django Views (Function-based සහ Class-based දෙකම) සහ URL patterns හසුරවන්නේ කොහොමද කියලා පැහැදිලි අවබෝධයක් ලැබෙයි. ඒ වගේම, පොඩි blog post display application එකක් හදලා practical විදියට මේ concepts use කරන හැටිත් බලමු. ඒ නිසා අතපසු නොකර කියවන්න!

1. Django Views කියන්නේ මොනවාද?

සරලවම කිව්වොත්, Django View එකක් කියන්නේ web request එකක් process කරලා, web response එකක් return කරන Python function එකක් හරි class එකක් හරි. මේ response එක HTML document එකක් වෙන්න පුළුවන්, නැත්නම් JSON response එකක් හරි, file එකක් හරි, නැත්නම් HTTP redirect එකක් හරි වෙන්න පුළුවන්.

1.1. Function-based Views (FBVs)

මේවා Django වල Views හදන්න පුළුවන් සරලම ක්‍රමය. සාමාන්‍ය Python function එකක් විදියට මේවා ලියන්න පුළුවන්. මේ function එකට HTTP request object එක parameter එකක් විදියට ලැබෙනවා.

උදාහරණයක් විදියට, myproject/myapp/views.py file එකේ මේ වගේ view එකක් ලියන්න පුළුවන්:

# myapp/views.py

from django.http import HttpResponse

def hello_world(request):
    """
    මූලික Function-based View එකක්.
    request එකක් ආවම "Hello, Django World!" කියලා return කරනවා.
    """
    return HttpResponse("<h1>Hello, Django World from a FBV!</h1>")

මේක හරිම සරලයි නේද? Request එක ආවම, HttpResponse එකක් එක්ක string එකක් return කරනවා.

1.2. Class-based Views (CBVs)

Class-based Views කියන්නේ Python classes භාවිතා කරලා views ලියන ක්‍රමයක්. මේවා function-based views වලට වඩා ටිකක් සංකීර්ණ වුණත්, code reusability එක වැඩි කරන්න, maintain කරන්න සහ extend කරන්න ගොඩක් පහසුයි. Django වල Generic Class-based Views කියලා එකක් තියෙනවා, ඒකෙන් දේවල් තවත් පහසු වෙනවා. (ඒ ගැන පස්සේ බලමු).

අපි කලින් හදපු hello_world view එකම CBV එකක් විදියට ලියමු:

# myapp/views.py

from django.http import HttpResponse
from django.views import View # View class එක import කරගන්න ඕනේ

class HelloWorldView(View):
    """
    මූලික Class-based View එකක්.
    GET request එකක් ආවම "Hello, Django World!" කියලා return කරනවා.
    """
    def get(self, request, *args, **kwargs):
        return HttpResponse("<h1>Hello, Django World from a CBV!</h1>")

මෙතනදී django.views.View class එක inherit කරගෙන, HTTP methods (get(), post() වගේ) සඳහා methods define කරනවා. මේකෙදි අපේ view එකට GET request එකක් ආවම get() method එක run වෙනවා.

කවදාද FBVs පාවිච්චි කරන්නේ, කවදාද CBVs පාවිච්චි කරන්නේ?
සරල, එක වැඩක් විතරක් කරන views වලට FBVs හොඳයි. ඒත්, ඔයාට complex logic තියෙන, නැවත නැවත පාවිච්චි කරන්න පුළුවන් views ඕන නම්, CBVs වඩාත් සුදුසුයි. විශේෂයෙන්ම, Django වල Generic CBVs (ListView, DetailView, CreateView වගේ) පාවිච්චි කරනකොට, ගොඩක් boilerplate code අඩු කරගන්න පුළුවන්.

2. Django URL Routing (URLconf) හරහා සම්බන්ධ කරමු!

දැන් අපි views හැදුවා. ඒත් user කෙනෙක්ට මේ views පේන්නේ කොහොමද? එතනට තමයි URL Routing එන්නේ. Django වලදී, urls.py files භාවිතා කරලා web address (URLs) views වලට map කරනවා.

සාමාන්‍යයෙන් ඔයාගේ project එකේ root directory එකේ urls.py file එකක් තියෙනවා. ඒ වගේම, ඔයා හදන හැම Django app එකකම අදාළ views වලට urls.py file එකක් හදලා, main urls.py file එකට include කරන එක තමයි best practice එක.

අපි myapp app එකට urls.py file එකක් හදමු: myproject/myapp/urls.py

# myapp/urls.py

from django.urls import path
from . import views # views.py file එක import කරගන්නවා

app_name = 'myapp' # App Namespacing එකට

urlpatterns = [
    path('hello/', views.hello_world, name='hello_world_fbv'), # FBV එකට URL එක
    path('hello-cbv/', views.HelloWorldView.as_view(), name='hello_world_cbv'), # CBV එකට URL එක
]

මෙතනදී path() function එකට arguments තුනක් දෙනවා:

  1. route: URL pattern එක ('hello/').
  2. view: මේ URL එකට අදාළ view එක (FBV නම් function එක, CBV නම් .as_view() method එක).
  3. name: මේ URL pattern එකට දෙන නමක්. මේක {% url %} template tag එකේදී වගේම code එක ඇතුළතදී URLs refer කරන්න ගොඩක් ප්‍රයෝජනවත් වෙනවා.

දැන් මේ myapp එකේ urls.py file එක project එකේ main urls.py file එකට include කරන්න ඕනේ:

# myproject/myproject/urls.py (project එකේ main urls.py)

from django.contrib import admin
from django.urls import path, include # include import කරගන්න ඕනේ

urlpatterns = [
    path('admin/', admin.site.urls),
    path('my-app/', include('myapp.urls')), # අපේ app එකේ URLs include කරනවා
]

දැන් ඔයා http://127.0.0.1:8000/my-app/hello/ කියලා browser එකේ type කළොත්, FBV එකේ response එක බලාගන්න පුළුවන්. http://127.0.0.1:8000/my-app/hello-cbv/ කියලා type කළොත්, CBV එකේ response එක බලාගන්න පුළුවන්.

2.1. URL Patterns ඇතුළත parameters යවමු (URL Parameters)

ගොඩක් වෙලාවට අපිට URL එක ඇතුළතින් data view එකට යවන්න වෙනවා. උදාහරණයක් විදියට, blog post එකක ID එක. Django වලදී මේක හරිම පහසුවෙන් කරන්න පුළුවන්.

# myapp/urls.py

# ... අනෙක් import statements ...

urlpatterns = [
    # ... අනෙක් URL patterns ...
    path('posts/<int:post_id>/', views.post_detail, name='post_detail'), # post_id එක int විදියට අරගන්නවා
    path('posts/<str:slug>/', views.post_detail_by_slug, name='post_detail_by_slug'), # slug එක string විදියට අරගන්නවා
]

View එක ඇතුළතදී මේ parameters අරගන්නේ මෙහෙමයි:

# myapp/views.py

from django.shortcuts import render, get_object_or_404
# from .models import Post # පස්සේ අපි Post model එකක් හදමු

def post_detail(request, post_id):
    # post_id එකෙන් Post object එකක් find කරගන්නවා
    # post = get_object_or_404(Post, pk=post_id) # Post model එකක් තිබ්බොත්
    return HttpResponse(f"<h2>Displaying Post ID: {post_id}</h2>")

def post_detail_by_slug(request, slug):
    # slug එකෙන් Post object එකක් find කරගන්නවා
    # post = get_object_or_404(Post, slug=slug)
    return HttpResponse(f"<h2>Displaying Post with Slug: {slug}</h2>")

<int:post_id> වගේ syntax එකෙන් කියන්නේ URL එකේ ඒ කොටස post_id කියන integer parameter එක විදියට view එකට යවනවා කියන එකයි. str, slug, uuid වගේ converters තව තියෙනවා.

3. Practical Scenario: Blog Post Display එකක් හදමු!

දැන් අපි මේ concepts පාවිච්චි කරලා පොඩි blog post list එකක් සහ single post එකක් display කරන app එකක් හදමු.

3.1. Model එකක් සාදාගනිමු

ඉස්සෙල්ලම අපි Post model එකක් හදාගමු. මේක myapp/models.py file එකේ ලියන්න පුළුවන්.

# myapp/models.py

from django.db import models
from django.utils.text import slugify

class Post(models.Model):
    title = models.CharField(max_length=200)
    slug = models.SlugField(unique=True, max_length=250, blank=True)
    content = models.TextField()
    pub_date = models.DateTimeField(auto_now_add=True)

    def save(self, *args, **kwargs):
        if not self.slug:
            self.slug = slugify(self.title)
        super().save(*args, **kwargs)

    def __str__(self):
        return self.title

makemigrations සහ migrate කරන්න අමතක කරන්න එපා. python manage.py makemigrations myapp සහ python manage.py migrate.

3.2. Function-based Views වලින් (FBV)

දැන් අපි FBVs වලින් මේ posts display කරමු. අපි HTML templates ටිකකුත් පාවිච්චි කරමු. myapp/templates/myapp/ කියන folder එක ඇතුළත post_list.html සහ post_detail.html කියන files හදාගන්න.

# myapp/views.py

from django.shortcuts import render, get_object_or_404
from .models import Post

def post_list_fbv(request):
    posts = Post.objects.all().order_by('-pub_date')
    return render(request, 'myapp/post_list.html', {'posts': posts})

def post_detail_fbv(request, slug):
    post = get_object_or_404(Post, slug=slug)
    return render(request, 'myapp/post_detail.html', {'post': post})

අදාළ urls.py entries:

# myapp/urls.py

# ...
urlpatterns = [
    # ...
    path('blog/', views.post_list_fbv, name='post_list_fbv'),
    path('blog/<str:slug>/', views.post_detail_fbv, name='post_detail_fbv'),
]

My Blog Posts (FBV)

    {% for post in posts %}
        
            {{ post.title }}
            - {{ post.pub_date|date:"M d, Y" }}
        
    {% empty %}
        No posts yet.
    {% endfor %}



{{ post.title }}
Published on: {{ post.pub_date|date:"M d, Y" }}

    {{ post.content|linebreaksbr }}

Back to Posts

3.3. Class-based Views වලින් (CBV)

දැන් Generic Class-based Views (GCBVs) පාවිච්චි කරලා මේකම හදමු. මේක FBVs වලට වඩා කොච්චර code අඩු වෙනවද කියලා බලන්න!

# myapp/views.py

from django.views.generic import ListView, DetailView
# ... Post model එක import කරගන්නවා ...

class PostListView(ListView):
    model = Post
    template_name = 'myapp/post_list_cbv.html' # template path එක specify කරනවා
    context_object_name = 'posts' # template එකට යවන object එකේ නම
    ordering = ['-pub_date'] # posts publish_date එක අනුව order කරනවා

class PostDetailView(DetailView):
    model = Post
    template_name = 'myapp/post_detail_cbv.html'
    context_object_name = 'post' # template එකට යවන object එකේ නම
    slug_url_kwarg = 'slug' # URL එකේ slug parameter එක specify කරනවා

අදාළ urls.py entries:

# myapp/urls.py

# ...
urlpatterns = [
    # ...
    path('blog-cbv/', views.PostListView.as_view(), name='post_list_cbv'),
    path('blog-cbv/<str:slug>/', views.PostDetailView.as_view(), name='post_detail_cbv'),
]

My Blog Posts (CBV)

    {% for post in posts %}
        
            {{ post.title }}
            - {{ post.pub_date|date:"M d, Y" }}
        
    {% empty %}
        No posts yet.
    {% endfor %}



{{ post.title }}
Published on: {{ post.pub_date|date:"M d, Y" }}

    {{ post.content|linebreaksbr }}

Back to Posts

දැක්කනේ Class-based views කොච්චර powerful ද කියලා. ගොඩක් දේවල් Django framework එක විසින්ම handle කරනවා. Templates වල නම් පොඩි වෙනස්කම් ටිකක් තියෙන්න පුළුවන් context_object_name එක අනුව.

4. පොදු ගැටළු සහ විසඳුම් (Common Issues and Solutions)

4.1. NoReverseMatch Error එක

මේක Django developers ලාට ගොඩක් වෙලාවට එන error එකක්. ඔයා {% url 'some_name' %} template tag එකක් පාවිච්චි කරලා URL එකක් generate කරන්න හදනකොට, Django වලට ඒ 'some_name' කියන URL pattern එක හොයාගන්න බැරි වුණාම මේ error එක එනවා.

හේතු:

  1. path() function එකේ name argument එක දීලා නැති වෙන්න පුළුවන්.
  2. name එක වැරදියට දීලා වෙන්න පුළුවන් (spelling mistake).
  3. App namespacing පාවිච්චි කරනකොට, 'app_name:url_name' format එක පාවිච්චි නොකර ඉන්න පුළුවන්.

විසඳුම:

urls.py එකේ path() function එකට name argument එක දෙන්න:

# myapp/urls.py
urlpatterns = [
    path('blog/', views.post_list_fbv, name='post_list_fbv'), # මෙතන name එකක් දෙනවා
]

Template එකේදී මේක පාවිච්චි කරනකොට, app_name එකත් එක්ක දෙන්න (අපි myapp කියන app_name එක කලින් දුන්නා):

{% url 'myapp:post_list_fbv' %}

Parameters තියෙන URL එකකට නම් මෙහෙම දෙන්න:

{% url 'myapp:post_detail_fbv' post.slug %}

4.2. URL Pattern වල අනුපිළිවෙල (Order of URL Patterns)

Django URL patterns process කරන්නේ urls.py file එක ඇතුළත උඩ ඉඳලා පහළට. ඒ කියන්නේ, URL එකක් එක්ක match වෙන පළවෙනි pattern එක තෝරාගන්නවා. මේක නිසා ගැටළු ඇතිවෙන්න පුළුවන්.

උදාහරණයක් විදියට, ඔයාට මේ වගේ patterns දෙකක් තියෙනවා කියලා හිතන්න:

urlpatterns = [
    path('blog/<str:slug>/', views.post_detail_fbv, name='post_detail_fbv'), # General pattern
    path('blog/new/', views.post_create_fbv, name='post_create_fbv'),     # Specific pattern
]

දැන් ඔයා /blog/new/ කියලා request එකක් යැව්වොත්, new කියන එක <str:slug> එකට match වෙන නිසා post_detail_fbv view එක run වෙන්න පුළුවන්. ඒක වැරදියි!

විසඳුම:

වැඩි specific patterns උඩින් තියන්න, general patterns පහළින් තියන්න.

urlpatterns = [
    path('blog/new/', views.post_create_fbv, name='post_create_fbv'), # Specific pattern first
    path('blog/<str:slug>/', views.post_detail_fbv, name='post_detail_fbv'), # General pattern second
]

5. Best Practices

Django Views සහ URLs පාවිච්චි කරනකොට මේ best practices මතක තියාගන්න:

  1. Descriptive URL Names: path() function එකේ name argument එකට තේරුමක් ඇති නම් දෙන්න (උදා: 'post_list', 'user_profile'). මේක code එක කියවන්න පහසු කරනවා වගේම, URLs වෙනස් වුණත් code එක modify කරන්න වෙන අවස්ථා අඩු කරනවා.
  2. App Namespacing: හැම Django app එකකම urls.py file එකට app_name = 'your_app_name' කියලා define කරන්න. මේකෙන් එකම URL name එක project එකේ වෙන apps වලත් තිබ්බත් conflict වෙන්නේ නැතුව, නිවැරදි URL එකට යොමු කරන්න පුළුවන්. උදා: {% url 'myapp:post_list' %}.
  3. Separate urls.py for Apps: Project එකේ main urls.py file එක හැකි තරම් clean එකට තියාගන්න. හැම app එකකටම තමන්ගේම urls.py file එකක් හදලා, project urls.py එකට include() කරන්න.
  4. Use Generic CBVs: පුළුවන් හැම වෙලාවෙම, විශේෂයෙන්ම CRUD operations (Create, Read, Update, Delete) වලදී Generic Class-based Views පාවිච්චි කරන්න. මේවා boilerplate code ගොඩක් අඩු කරලා, ඔයාගේ time එක ඉතිරි කරනවා.
  5. Keep Views Thin: Views වල business logic එක තියාගන්නේ නැතුව, ඒක models, managers, forms, services වගේ තැන්වලට delegate කරන්න. View එකේ ප්‍රධාන කාර්යය වෙන්න ඕනේ request එක process කරලා, data අරගෙන, template එකක් render කරලා response එකක් දෙන එක විතරයි.

නිගමනය

ඉතින් යාලුවනේ, අද අපි Django web development වල හරිම වැදගත් කොටස් දෙකක් ගැන කතා කළා – Views (Function-based and Class-based) සහ URL Routing. මේවා හරියටම තේරුම් අරගෙන පාවිච්චි කරන එක ඔයාගේ Django project එක successful වෙන්න අනිවාර්යයි.

අපි FBVs සහ CBVs වල මූලිකාංග, URL patterns හදන හැටි, URL parameters use කරන හැටි වගේම, පොඩි blog app එකක් හදලා practical විදියට මේ concepts use කරන හැටිත් බැලුවා. ඒ වගේම NoReverseMatch වගේ පොදු ගැටළු වලට විසඳුම් සහ වැඩියෙන්ම ප්‍රයෝජනවත් best practices කිහිපයකුත් කතා කළා.

දැන් වෙලාවයි ඔයාලා මේවා ඔයාලගේම project එකකට implement කරලා බලන්න! ඔයාලට ගැටළු ආවොත්, ඒ ගැන අනිවාර්යයෙන්ම comment section එකේ අහන්න. මේ tutorial එක ගැන ඔයාලගේ අදහස් සහ අත්දැකීම් share කරන්නත් අමතක කරන්න එපා. අපි ඊළඟ tutorial එකකින් හමුවෙමු! සුභ දවසක්!