پای‌دانتیکپای‌دانتیکپای‌دانتیک
  • صفحه اصلی
  • اخبار
  • آموزش
  • تجربه
  • نقشه راه
  • فریمورک
    • django
    • fastapi
خواندن: چگونه یک ویجت فرم سفارشی برای Django بسازیم
اشتراک گذاری
ورود
0

هیچ محصولی در سبد خرید نیست.

اعلان نمایش بیشتر
تغییردهنده سایز فونتAa
پای‌دانتیکپای‌دانتیک
0
تغییردهنده سایز فونتAa
Search
  • صفحه اصلی
  • آموزش
  • اخبار
  • تجربه
  • نقشه راه
  • فریمورک
    • django
    • fastapi
Have an existing account? ورود
ما را دنبال کنید
© 2022 Foxiz News Network. Ruby Design Company. All Rights Reserved.
پای‌دانتیک > فریمورک > django > چگونه یک ویجت فرم سفارشی برای Django بسازیم
django

چگونه یک ویجت فرم سفارشی برای Django بسازیم

محمد عزیززاده
آخرین به روز رسانی: شهریور 6, 1402 3:44 ب.ظ
محمد عزیززاده
اشتراک گذاری
18 دقیقه زمان مطالعه
چگونه یک ویجت فرم سفارشی برای Django بسازیم
چگونه یک ویجت فرم سفارشی برای Django بسازیم
اشتراک گذاری

Django به دلیل قابلیت‌های داخلی مدیریت فرم معروف است، که مدیریت و ارائه داده‌های فرم را برای توسعه‌دهندگان آسان‌تر می‌کند.

Contents
راه اندازی یک فرم سادهشکل دادن به فیلد فرمساخت ویجت سفارشی

با این حال، گاهی اوقات ویجت های فرم پیش فرض شرایط خاصی را برآورده نمی کنند. این مقاله نحوه ایجاد ویجت‌های فرم سفارشی در جنگو را بررسی می‌کند و اطمینان می‌دهد که می‌توانید با هر طراحی و نیازهای کاربردی مطابقت داشته باشید.

با توجه به اینکه پایه اولیه با یک فرم اولیه طراحی شده است، بیایید عمیق تر به شخصی سازی ظاهر و عملکرد آن بپردازیم.

راه اندازی یک فرم ساده

قبل از اینکه وارد ساخت ویجت‌های فرم سفارشی شویم، اجازه دهید یک فرم ساده را در Django تنظیم کنیم. این به عنوان پایه و اساس ما برای درک ساختار اصلی و متعاقبا سفارشی کردن آن عمل می کند.

ما با تعریف دیدگاه شروع می کنیم. در اینجا، ما از نماهای کلاس محور جنگو برای رسیدگی به درخواست‌های GET و POST استفاده می‌کنیم.

from django.shortcuts import render, redirect
from django.views import View

from app.forms import RatingForm

class RatingFormView(View):
    def get(self, request):
        form = RatingForm(initial={"rating": 3})
        return render(request, "app/rating.html", {"form": form})
    def post(self, request):
        form = RatingForm(request.POST)
        if form.is_valid():
            rating = form.cleaned_data["rating"]
            save_rating(rating) # This is a hypothetical function
            return redirect(somewhere) # 'somewhere' should be replaced with the actual redirect location.
        return render(request, "app/rating.html", {"form": form})

در این تنظیمات، متد دریافت RatingForm ما را با مقدار رتبه‌بندی پیش‌فرض 3 (که به «3 ستاره» ترجمه می‌شود) مقداردهی اولیه می‌کند.

از سوی دیگر، روش پست، ارسال فرم را مدیریت می کند. اگر داده‌های فرم معتبر باشد، رتبه‌بندی را پردازش کرده و کاربر را هدایت می‌کند. این اصطلاح معمولی Django برای پردازش فرم ها است.

در مرحله بعد، ما باید یک قالب برای پروژه Django شما تعریف کنیم. ما از وراثت الگو برای حفظ ظاهر و احساس ثابت در صفحات مختلف استفاده خواهیم کرد.

در اینجا قالب پایه base.html است که شامل ساختار ضروری HTML است و چارچوب بوت استرپ را برای استایل ادغام می کند.

بوت استرپ طراحی ما را بهبود می بخشد و با کمترین تلاش به فرم ها و سایر عناصر رابط کاربری ظاهری مدرن می بخشد.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Building Custom Widgets</title>
    
    <!-- Include Bootstrap for styling -->
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.1/dist/css/bootstrap.min.css" rel="stylesheet"
          integrity="sha384-4bw+/aepP/YC94hEpVNVgiZdgIC5+VKNBQNGCHeKRQN+PtmoHDEXuppvnDJzQIu9" crossorigin="anonymous">
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.1/dist/js/bootstrap.bundle.min.js"
            integrity="sha384-HwwvtgBNo3bZJJLYd8oVXjrBZt8cqVSpeBNS5n7C8IVInixGAoxmnlMuBnhbgrkm"
            crossorigin="anonymous"></script>
</head>
<body>
<div class="container-fluid">
    {% block content %}
    {% endblock %}
</div>
</body>
</html>

ما همچنین یک بلوک “محتوا” را تعریف کرده ایم که محتوای ما در آن قرار می گیرد. با مجموعه قالب پایه، بیایید الگوی مخصوص فرم خود را ایجاد کنیم (rating.html):

{% extends 'app/base.html' %}
{% block content %}
    <h1 class="m-3">Please give your rating</h1>
    <form method="post">
        {% csrf_token %}
        {{ form }}
        <input type="submit" value="Submit">
    </form>
{% endblock %}

این الگو پایه را گسترش می دهد و از یک ظاهر طراحی ثابت اطمینان می دهد. فرم را رندر می کند و دکمه ارسال را ارائه می دهد.

در نهایت، خود فرم با به ارث بردن از کلاس Form جنگو تعریف شده است. این فرم شامل یک فیلد تک انتخابی است که به کاربران امکان می دهد امتیازی از 1 تا 5 ستاره را انتخاب کنند.

import django.forms as forms
class RatingForm(forms.Form):
    rating = forms.ChoiceField(
        choices=(
            (1, "1 Star"),
            (2, "2 Stars"),
            (3, "3 Stars"),
            (4, "4 Stars"),
            (5, "5 Stars"),
        )
    )

با این مؤلفه‌ها، یک فرم اولیه را در جنگو تنظیم کرده‌ایم.

وقتی سرور توسعه را راه اندازی می کنیم و نمای تعریف شده در مرورگر را باز می کنیم، چیزی شبیه به زیر دریافت می کنیم:

در مرحله بعد، فیلدهای فرم خود را با استفاده از Bootstrap استایل می کنیم.

شکل دادن به فیلد فرم

فرم ما تا اینجا نسبتاً زشت است. ما قبلاً بوت استرپ را در قالب پایه خود وارد کرده ایم، اما هنوز از آن در فرم خود استفاده نمی کنیم!

به طور خاص، ما می‌خواهیم کلاس‌های Bootstrap را روی دکمه ارسال و همچنین در ورودی Select اعمال کنیم. حالت دادن به دکمه مستقیم به جلو است. ما به سادگی کلاس های btn btn-primary را در فرم template rating.html پیوست می کنیم:

{% extends 'app/base.html' %}
{% block content %}
    <h1 class="m-3">Please give your rating</h1>
    <div class="m-3">
        <form method="post">
            {% csrf_token %}
            {{ form }}
            <input type="submit" class="btn btn-primary" value="Submit">
        </form>
    </div>
{% endblock %}

با این حال، پیوست کردن سبک Bootstrap به فیلدهای فرم چندان ساده نیست. ما می خواهیم کلاس “form-select” را به عنصر <select> اعمال کنیم که توسط جنگو هنگام درج فرم ارائه می شود. می‌توانیم الگو را تقسیم کنیم، اما خیلی خوب است که فقط {{form}} را بگوییم و بقیه را در کد نگه داریم و نه الگو.

ما فقط باید کد تعریف فرم خود را کمی تغییر دهیم:

import django.forms as forms

class RatingForm(forms.Form):
    rating = forms.ChoiceField(
        choices=(
            (1, "1 Star"),
            (2, "2 Stars"),
            (3, "3 Stars"),
            (4, "4 Stars"),
            (5, "5 Stars"),
        ),
        widget=forms.Select(attrs={'class': 'form-select m-3'})
    )

در اینجا، من به صراحت مشخص کرده‌ام که ChoiceField باید یک ویجت Select را نمایش دهد که در واقع پیش‌فرض است.

اما پیش فرض کلاس های بوت استرپ را ضمیمه نمی کند. بنابراین ما این کار را با تعریف صریح آن در فرهنگ لغت attrs ویجت انجام می دهیم.

علاوه بر انتخاب فرم، برای نمایش بهتر، کمی حاشیه m-3 نیز اضافه کردم. حالا فرم ما به این صورت است:

ساخت ویجت سفارشی

تا کنون، ما از ویجت داخلی Django Select استفاده کرده‌ایم که به عنوان یک عنصر HTML <select> نمایش داده می‌شود. و همچنین دیده ایم که چگونه ظاهر را سفارشی کنیم.

Django  طیف گسترده‌ای از قابلیت سفارشی‌سازی را ارائه می‌کند، اما برای مورد بعدی، قابلیت سفارشی‌سازی کافی نیست. ما به توسعه پذیری نیاز داریم! خوشبختانه، جنگو در توسعه آن نیز عالی است.

اکنون می خواهیم ویجت انتخابی را با چیزی کاملا متفاوت جایگزین کنیم. به جای < select> با کادر کشویی آن، می خواهیم تصویری با پنج ستاره نمایش دهیم و برای انتخاب رتبه، کاربر می تواند روی ستاره مربوطه کلیک کند:

یک فرم در Django  از یک یا چند فیلد از نوع پایه فیلد تشکیل شده است. در مورد ما، یک فرم با یک فیلد از نوع ChoiceField داریم که یک کلاس فرزند از Field است. هر فیلد دارای یک شی از نوع ویجت است. ویجت مشخص می کند که چه چیزی در مرورگر برای فیلد نمایش داده می شود.

در مورد ما، ویجت ما یک نمونه از Select بود که یک کلاس فرزند از ویجت است. در نهایت، هر ویجت دارای یک الگو است که نحوه رندر کردن ویجت را در DOM مرورگر تعریف می کند. بنابراین چیزی که ما برای ویجت پنج ستاره خود نیاز داریم، یک ویجت فرم ارث بری کلاس جدید، همراه با برخی الگوها برای ارائه صحیح آن است.

اول از همه، فونت awesome را برای نمایش آیکون‌های ستاره و jQuery را برای آسان‌تر کردن زندگی با جاوا اسکریپت وارد می‌کنیم. بنابراین تگ های زیر را در عنصر <head> در فایل base.html خود قرار می دهیم.

<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.2/css/all.min.css" rel="stylesheet">
<script src="https://code.jquery.com/jquery-3.7.0.slim.js" integrity="sha256-7GO+jepT9gJe9LB4XFf8snVOjX3iYNb0FHYr5LI1N5c=" crossorigin="anonymous"></script>

سپس، نحوه نمایش ویجت ما را با نوشتن یک الگو با برخی از پویایی های جاوا اسکریپت تعریف می کنیم.

input id="{{ widget.attrs.id }}" hidden value="{{ widget.value }}" name="{{ widget.name }}">

<i id="id_star_1" class="fa-regular fa-star"></i>
<i id="id_star_2" class="fa-regular fa-star"></i>
<i id="id_star_3" class="fa-regular fa-star"></i>
<i id="id_star_4" class="fa-regular fa-star"></i>
<i id="id_star_5" class="fa-regular fa-star"></i>
<script>
    $(document).ready(function () {

        let hiddenInput = document.getElementById("{{ widget.attrs.id }}");
        var stars = Array.from([1, 2, 3, 4, 5], (i) => document.getElementById("id_star_" + i));
        
        function setValue(val) {
            hiddenInput.setAttribute("value", val);
            for (let i = 1; i <= 5; i++) {
                if (i <= val) {
                    stars[i - 1].setAttribute("class", "fa-solid fa-star");
                } else {
                    stars[i - 1].setAttribute("class", "fa-regular fa-star");
                }
            }
        }

        for (let i = 1; i <= 5; i++) {
            $("#id_star_" + i).click(function () {
                setValue(i);
            });
        }

    });

</script>

الگوی داده شده یک فیلد ورودی مخفی ایجاد می کند که مقدار رتبه بندی را ذخیره می کند. پس از آن پنج نماد ستاره ها را نشان می دهد. شناسه هر ستاره و ورودی پنهان به صورت پویا با استفاده از ویژگی های ویجت تولید می شوند.

در بخش اسکریپت، jQuery برای افزودن تعامل به این ستاره ها استفاده می شود. وقتی صفحه آماده شد، ابتدا ارجاعاتی را به ورودی پنهان و تمام عناصر ستاره می گیریم. سپس یک تابع setValue برای به روز رسانی تصاویر ستاره و مقدار ورودی پنهان بر اساس انتخاب کاربر تعریف می کنیم. سپس شنوندگان رویداد کلیک روی هر ستاره متصل می شوند تا وقتی کاربر کلیک می کند، تابع setValue رتبه انتخابی را به روز می کند. اساساً، وقتی کاربر روی یک ستاره کلیک می‌کند، مقدار رتبه‌بندی مربوطه در ورودی پنهان ذخیره می‌شود و این مقدار هنگام ارسال فرم ارسال می‌شود.

سپس کلاس ویجت خود را تعریف می کنیم و قالب خود را به آن سیم می کنیم:

from django.forms import Widget

class FiveStarWidget(Widget):
    template_name = "app/widgets/five-stars.html"
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

class RatingForm(forms.Form):
    rating = forms.ChoiceField(
        choices=(
            (1, "1 Star"),
            (2, "2 Stars"),
            (3, "3 Stars"),
            (4, "4 Stars"),
            (5, "5 Stars"),
        ),
        widget=FiveStarWidget
    )

کلاس FiveStarWidget ویجت سفارشی ما است که از کلاس ویجت پایه جنگو به ارث می رسد. ما الگوی رندر این ویجت را با استفاده از ویژگی template_name مشخص می کنیم. پایین تر، کلاس RatingForm برای استفاده از این ویجت جدید اصلاح شده است. آرگومان ویجت در ChoiceField با FiveStarWidget سفارشی ما جایگزین شده است، به این معنی که جنگو گزینه های رتبه بندی را با استفاده از نمادهای ستاره ما به جای یک کشویی سنتی ارائه می کند.

در این مرحله، هنگامی که با صفحه خود تماس می گیریم، در حال حاضر کاملا امیدوار کننده به نظر می رسد:

همچنین می توانیم برای انتخاب رتبه و ارسال فرم روی ستاره ها کلیک کنیم. وقتی این کار را انجام می‌دهیم، در یک تنظیمات واقعی احتمالاً با خطا مواجه می‌شویم، زیرا روشی که درخواست ارسال را مدیریت می‌کند، یا به‌ویژه تابع save_rating احتمالاً انتظار دارد که یک عدد ارسال شود.

با این حال، اگر آنچه در فرهنگ لغت form.cleaned_data موجود است را اشکال زدایی کنید، خواهید دید که مقداری که از ویجت ما برگردانده می شود یک رشته است!

پس هنوز کارمان تمام نشده است. به عنوان یک اشاره کاری که باید انجام دهیم، کلاس فرم خود را در نظر بگیرید. در آنجا، ویجت را جایگزین کردیم، اما همچنان از ChoiceField استفاده می کنیم.

اما چرا هنوز باید انتخاب ها را همراه با رشته ها تعریف کنیم؟ این دیگر منطقی نیست زیرا ما دیگر از < select > استفاده نمی کنیم. بنابراین باید به جای استفاده از ChoiceField کلاس Field خودمان را بنویسیم. بنابراین ماژول forms.py جدید ما اینجاست:

import django.forms as forms
from django.forms import Widget, IntegerField

class FiveStarWidget(Widget):
    template_name = "app/widgets/five-stars.html"
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

class RatingField(IntegerField):
    widget = FiveStarWidget

class RatingForm(forms.Form):
    rating = RatingField()

همانطور که می بینید، واقعا آسان است. ما کلاس RatingField را که از IntegerField به ارث می برد تعریف کرده ایم. با ارث بردن از IntegerField، ما قابلیت تبدیل مقدار متن به مقادیر صحیح و همچنین انجام اعتبارسنجی مناسب را به ارث می بریم. سپس ویجت پیش فرض IntegerField را با ویجت سفارشی خود جایگزین می کنیم. پس از آن، ما ChoiceField را در کلاس RatingForm با فیلد سفارشی خود جایگزین می کنیم.

با اعمال این تغییرات، کار ما تمام شده است. form.is_valid() اکنون منطق اعتبارسنجی مناسب را انجام می دهد، form.cleaned_data[“rating”]شامل یک عدد است نه یک رشته و این تمام چیزی است که ما نیاز داشتیم.

در اینجا، ما توانستیم از بسیاری از عملکردهای کلاس InputField دوباره استفاده کنیم. به طور خاص، InputField می داند که چگونه یک مقدار رشته را به یک مقدار صحیح تبدیل کند. اما اگر مقدار ویجت ما یک رشته نبود بلکه یک شی پیچیده تر بود چه؟ یا اگر فیلد ما یک مقدار صحیح نمی خواهد بلکه چیزی خاص تر است؟ سپس ما نمی توانیم از عملکرد InputField استفاده کنیم.

اگر هیچ فیلد داخلی دیگری برای جنگو وجود نداشته باشد که بتوانیم آنچه را که نیاز داریم از آن به ارث ببریم، باز هم می‌توانیم خودمان را بنویسیم!

برای اینکه ببینیم این چگونه کار می‌کند، اکنون این واقعیت را نادیده می‌گیریم که می‌توانیم زندگی خود را با ارث بردن از InputField آسان‌تر کنیم و منطق تبدیل و اعتبارسنجی خود را بنویسیم. بنابراین به جای ارث بردن از InputField، از Field ارث می بریم.

import django.forms as forms
from django.core.exceptions import ValidationError
from django.forms import Widget, IntegerField, Field
from django.forms.widgets import Input

class FiveStarWidget(Widget):
    template_name = "app/widgets/five-stars.html"
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

class RatingField(Field):
    widget = FiveStarWidget
    def to_python(self, value):
        try:
            return int(value)
        except TypeError:
            raise ValidationError("Cannot convert this string to number.", code="invalid")
    def validate(self, value):
        if not (1 <= value <= 5):
            raise ValidationError("Rating must be between 1 and 5.", code="invalid")
        return value

class RatingForm(forms.Form):
    rating = RatingField()

هنگامی که مدیریت پست ما تابع form.is_valid() را اجرا می کند، جنگو ابتدا متد to_python تمام فیلدهای فرم را فراخوانی می کند. هدف از این تابع تبدیل مقدار ذخیره شده در ویجت (در اینجا یک رشته) به فرمت مورد نیاز فیلد (در اینجا یک عدد صحیح) است. منطق اعتبارسنجی مربوط به تبدیل نیز باید در این روش قرار گیرد، همانطور که در اینجا انجام دادیم.

اگر برخی از اعتبارسنجی ناموفق باشد، باید یک ValidationError ایجاد کنیم، که باعث می شود جنگو پیام خطا را در قسمت مربوطه در مرورگر نشان دهد. پس از بازگشت از to_python، فراخوانی Django validate، در صورت وجود، برای اجرای منطق اعتبارسنجی بیشتر که به تبدیل مربوط نمی شود.

در اینجا، ما فقط بررسی می کنیم که آیا مقدار بین 1 و 5 است یا خیر. هنگامی که تمام اعتبارسنجی با موفقیت انجام شد، مقدار در فرهنگ لغت form.cleaned_data توسط جنگو ذخیره می شود.

نتیجه

اکنون شما تمام بلوک های ساختمانی کلیدی برای ساخت ویجت خود را برای فرم ها دارید:

قالب ویجت خود را به صورت اختیاری با پویایی جاوا اسکریپت در HTML بسازید.

یک کلاس ویجت بسازید که از ویجت به ارث می رسد و قالب را سیم کشی کنید.

یک کلاس فیلد فرم که از Field به ارث برده می شود بسازید و با پیاده سازی متدهای to_python و اعتبارسنجی، منطق تبدیل و اعتبارسنجی را اضافه کنید.

ویجتی که ما پیاده سازی کرده ایم بسیار ساده است. اما می توانید تصور کنید که با این رویکرد می توانید هر نوع فیلد فرم و ویجت را پیاده سازی کنید. بنابراین این یک مهارت کلیدی برای توسعه دهندگان پیشرفته جنگو است.

Sign Up For Daily Newsletter

Be keep up! Get the latest breaking news delivered straight to your inbox.
By signing up, you agree to our Terms of Use and acknowledge the data practices in our Privacy Policy. You may unsubscribe at any time.
این مقاله را به اشتراک بگذارید
Facebook Twitter Copy Link Print
اشتراک گذاری
مقاله قبلی ساختن یک گالری تصویر با Django و Bootstrap 5 ساختن یک گالری تصویر با Django و Bootstrap 5
مقاله بعدی راهنمای کامل Django CKEditor از نصب تا کانفیگ راهنمای کامل Django CKEditor : از نصب تا کانفیگ
پیام بگذارید پیام بگذارید

دیدگاهتان را بنویسید لغو پاسخ

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

همه دسته بندی ها

  • django
  • fastapi
  • آموزش
  • اخبار
  • تجربه
  • دسته‌بندی نشده
  • نقشه راه
پای‌دانتیکپای‌دانتیک
ما را دنبال کنید
قالب فاکسیز فارسی شده توسط تیم راستچین 2023
Welcome Back!

Sign in to your account