Class-based Forms:/Model Forms:
Django-তে ফর্ম তৈরি করার দুইটি প্রধান উপায় রয়েছে:
- Class-based Forms:
- Model Forms:
Class-based Forms:
Django-এ Class-based ফর্ম তৈরি করতে, forms মডিউল থেকে Form ক্লাস ইনহেরিট করতে হয়। উদাহরণ
from django import forms
class MyForm(forms.Form):
name = forms.CharField(label='নাম', max_length=100)
email = forms.EmailField(label='ইমেইল')
message = forms.CharField(label='মেসেজ', widget=forms.Textarea)
Model Forms:
Model Forms ব্যবহার করে, আপনি আপনার মডেলের সাথে সহজেই ফর্ম তৈরি করতে পারেন। উদাহরণ:
from django import forms
from .models import MyModel
class MyModelForm(forms.ModelForm):
class Meta:
model = MyModel
fields = ['name', 'email', 'message']
পরবর্তী টিউটোরিয়ালে আমরা প্রাক্টিক্যালি দেখবো
forms.Form
একটি সিম্পল ফর্ম বানানোর উদাহরণ হিসেবে, আমরা একটি নাম এবং ইমেইল ইনপুট ফিল্ড থাকা ফর্ম বানাবো:
ধাপ 1: একটি নতুন ফাইল তৈরি করুন এবং এটিকে “forms.py” নাম দিন।
ধাপ 2: ফাইলটিতে নিম্নলিখিত কোডটি যোগ করুন:
# forms.py
from django import forms
class SimpleForm(forms.Form):
name = forms.CharField(label='নাম', max_length=100)
email = forms.EmailField(label='ইমেইল')
ফর্মটি একটি ভিউতে ব্যবহার করতে নিচের মডিউলটি তৈরি করুন:
# views.py
from django.shortcuts import render
from .forms import SimpleForm
def simple_form_view(request):
if request.method == 'POST':
form = SimpleForm(request.POST)
if form.is_valid():
# ফর্ম ডাটা প্রসেস করুন
name = form.cleaned_data['name']
email = form.cleaned_data['email']
# এই ডাটার সাথে কিছু করতে চাইলে তার কোড লিখুন
else:
# ফর্ম ভুল তথ্য দেখাতে চাইলে এখানে কোড লিখুন
pass
else:
form = SimpleForm()
return render(request, 'simple_form_template.html', {'form': form})
আমাদের HTML টেমপ্লেট (simple_form_template.html) তৈরি করতে নিচের কোডটি ব্যবহার করতে পারেন:
<!-- simple_form_template.html -->
<!DOCTYPE html>
<html>
<head>
<title>সিম্পল ফর্ম</title>
</head>
<body>
<h2>সিম্পল ফর্ম</h2>
<form method="post" action="{% url 'simple_form_view' %}">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">সাবমিট</button>
</form>
</body>
</html>
এখানে, আমরা SimpleForm ক্লাসের ইনস্ট্যান্টটি একটি HTML ফর্মে রেন্ডার করছি এবং ফর্মটি সাবমিট হলে এই ফর্ম ডাটা প্রসেস করার জন্য ভিউতে লজিক যোগ করছি।
forms.Form এ widget()
widget প্যারামিটার ব্যবহার করে ফিল্ডগুলির ইনপুটের ধরণ কাস্টমাইজ করতে পারেন
forms.Form ব্যবহার করে একটি ফর্ম তৈরি করার সময়, আপনি widget প্যারামিটার ব্যবহার করে ফিল্ডগুলির ইনপুটের ধরণ কাস্টমাইজ করতে পারেন। ইনপুট ধরনের পরিবর্তে বিভিন্ন ধরণের উইজেট ব্যবহার করতে এটি ব্যবহার করা হয়।
নিচে একটি উদাহরণ দেওয়া হয়েছে এমন একটি ফর্মের জন্য যেখানে নাম এবং ইমেইল ফিল্ডগুলির জন্য বিশেষ উইজেট ব্যবহার হয়েছে:
# forms.py
from django import forms
class CustomWidgetForm(forms.Form):
name = forms.CharField(label='নাম', max_length=100, widget=forms.TextInput(attrs={'placeholder': 'আপনার নাম'}))
email = forms.EmailField(label='ইমেইল', widget=forms.EmailInput(attrs={'placeholder': 'আপনার ইমেইল'}))
উপরের উদাহরণে, forms.TextInput এবং forms.EmailInput উইজেটগুলি ব্যবহার হয়েছে যারা নাম এবং ইমেইল ফিল্ডগুলির জন্য কাস্টম উইজেট। attrs প্যারামিটারটি ব্যবহার করে আপনি ইনপুটের HTML এট্রিবিউট যোগ করতে পারেন, যেমন প্লেসহোল্ডার এট্রিবিউট।
এবার এই ফর্মটি রেন্ডার করার জন্য একটি ভিউ তৈরি করতে পারেন:
# views.py
from django.shortcuts import render
from .forms import CustomWidgetForm
def custom_widget_form_view(request):
if request.method == 'POST':
form = CustomWidgetForm(request.POST)
if form.is_valid():
# ফর্ম ডাটা প্রসেস করুন
name = form.cleaned_data['name']
email = form.cleaned_data['email']
# এই ডাটার সাথে কিছু করতে চাইলে তার কোড লিখুন
else:
# ফর্ম ভুল তথ্য দেখাতে চাইলে এখানে কোড লিখুন
pass
else:
form = CustomWidgetForm()
return render(request, 'custom_widget_form_template.html', {'form': form})
এবার custom_widget_form_template.html ফাইলটি তৈরি করুন:
<!-- custom_widget_form_template.html -->
<!DOCTYPE html>
<html>
<head>
<title>কাস্টম উইজেট ফর্ম</title>
</head>
<body>
<h2>কাস্টম উইজেট ফর্ম</h2>
<form method="post" action="{% url 'custom_widget_form_view' %}">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">সাবমিট</button>
</form>
</body>
</html>
ModelForm
একটি সিম্পল মডেল ব্যবহার করে ModelForm তৈরি করতে দেখানো হচ্ছে। একটি উদাহরণ হিসেবে, একটি মডেল এবং এর জন্য ModelForm তৈরি করা হয়েছে:
# models.py
from django.db import models
class Person(models.Model):
name = models.CharField(max_length=100)
email = models.EmailField()
def __str__(self):
return self.name
এবার ModelForm তৈরি করতে নিচের কোডটি ব্যবহার করুন:
# forms.py
from django import forms
from .models import Person
class PersonForm(forms.ModelForm):
class Meta:
model = Person
fields = ['name', 'email']
এবার এই ModelForm এবং মডেলটি ব্যবহার করে একটি ভিউ তৈরি করতে নিচের কোডটি ব্যবহার করুন:
# views.py
from django.shortcuts import render
from .forms import PersonForm
def person_form_view(request):
if request.method == 'POST':
form = PersonForm(request.POST)
if form.is_valid():
# ফর্ম ডাটা প্রসেস করুন
form.save()
# এই ডাটার সাথে কিছু করতে চাইলে তার কোড লিখুন
else:
form = PersonForm()
return render(request, 'person_form_template.html', {'form': form})
এবার এই ফর্মটি রেন্ডার করার জন্য একটি টেমপ্লেট ফাইল তৈরি করুন:
<!-- person_form_template.html -->
<!DOCTYPE html>
<html>
<head>
<title>ব্যক্তি ফর্ম</title>
</head>
<body>
<h2>ব্যক্তি ফর্ম</h2>
<form method="post" action="{% url 'person_form_view' %}">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">সাবমিট</button>
</form>
</body>
</html>
এই উদাহরণে, আমরা ModelForm ব্যবহার করে একটি মডেল ফর্ম তৈরি করেছি এবং তারপরে একটি ভিউ তৈরি করেছি যা এই ফর্মটি রেন্ডার করতে ব্যবহার করে।
মডেল ফর্ম customization
মডেল
আমাদের মডেলটি models.py আগেরটি ই রয়েছে সহজ করার জন্য আমি কোন পরিবর্তন করিনি।
from django.db import models
class Student(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
email = models.EmailField(max_length=254)
phone_number = models.CharField(max_length=20)
registration_number = models.CharField(max_length=20, unique=True)
department = models.CharField(max_length=50)
semester = models.CharField(max_length=10)
section = models.CharField(max_length=10)
def __str__(self):
return self.first_name + " " + self.last_nameসকল ফিল্ড দিয়ে ফর্ম বানানো
from django import forms
from .models import Student
class StudentForm(forms.ModelForm):
class Meta:
model = Student
fields = '__all__'এই কোডটি মডেল এর সকল ফিল্ড ধারণ করে।
নির্দিষ্ট ফিল্ড দিয়ে ফর্ম বানানো
যদি কোন ফিল্ড বাদ দেয়ার দরকার পরে তাহলে exclude নামে আরেকটি অপসন ব্যবহার করবো। আমি চাচ্ছি exclude এ যা ফিল্ড লিখবো তা ফর্ম এ শো করবে না
from django import forms
from .models import Student
class StudentForm(forms.ModelForm):
class Meta:
model = Student
exclude = ['email', 'phone_number', 'registration_number', 'department', 'semester', 'section']
আবার চাইলে নিজের ইচ্ছামত ফিল্ড গুলোকে সিরিয়াল করে লিখতে পারি। শুধু first_name, last_name ফিল্ড শো করবে
from django import forms
from .models import Student
class StudentForm(forms.ModelForm):
class Meta:
model = Student
fields = ['first_name', 'last_name']
এর পরের টিউটোরিয়ালে আমরা ফর্ম কে বিভিন্ন ভাবে কাস্টমাইজ করে ব্যবহার করতে শিখতে পারবো।
ফর্মের লেআউট
আমরা দুইভাবে ফর্ম লেআউট বানাতে পারি :
- সম্পূর্ণ কাস্টমাইজ | normal form
- ব্যাসিক কাস্টমাইজ | loop form
উদাহরণ সম্পূর্ণ কাস্টমাইজ : ডিফল্ট ফর্ম
from django.forms import ModelForm
class MyForm(ModelForm):
class Meta:
model = MyModel
fields = ['name', 'email']
{% extends 'base.html' %}
{% block content %}
<form action="/" method="post">
{% csrf_token %}
{{ form.as_p() }}
<input type="submit" value="Submit">
</form>
{% endblock %}
এই উদাহরণটি MyModel মডেলের জন্য একটি ডিফল্ট ফর্ম তৈরি করে। ফর্মটি name এবং email ক্ষেত্রগুলিকে সংজ্ঞায়িত করে। ফর্মটি base.html টেমপ্লেট থেকে উত্তরাধিকার সূত্রে প্রাপ্ত হয়। base.html টেমপ্লেটটি একটি সাধারণ HTML ফর্ম তৈরি করে।
এই উদাহরণটি form.as_p() টেমপ্লেট ট্যাগ ব্যবহার করে ফর্মের ক্ষেত্রগুলি প্রদর্শন করে। form.as_p() ট্যাগটি ফর্মের ক্ষেত্রগুলির একটি HTML তালিকা তৈরি করে।
উদাহরণ সম্পূর্ণ কাস্টমাইজ : কাস্টম ফর্ম
from django.forms import ModelForm
class MyForm(ModelForm):
class Meta:
model = MyModel
fields = ['name', 'email']
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['name'].label = 'Your name (required)'
self.fields['email'].label = 'Your email (required)'
{% extends 'base.html' %}
{% block content %}
<form action="/" method="post">
{% csrf_token %}
<input type="text" name="name" placeholder="Your name (required)">
<input type="email" name="email" placeholder="Your email (required)">
<input type="submit" value="Submit">
</form>
{% endblock %}
উদাহরণ সম্পূর্ণ কাস্টমাইজ : বুটস্ট্র্যাপ লেআউট ফর্ম
from django.forms import ModelForm
class MyForm(ModelForm):
class Meta:
model = MyModel
fields = ['name', 'email']
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['name'].widget = forms.TextInput(attrs={'class': 'form-control'})
self.fields['email'].widget = forms.EmailInput(attrs={'class': 'form-control'})
{% extends 'base.html' %}
{% block content %}
<form action="/" method="post">
{% csrf_token %}
<div class="form-group">
<label for="name">Your name (required)</label>
<input type="text" name="name" id="name" class="form-control" placeholder="Your name">
</div>
<div class="form-group">
<label for="email">Your email (required)</label>
<input type="email" name="email" id="email" class="form-control" placeholder="Your email">
</div>
<input type="submit" value="Submit" class="btn btn-primary">
</form>
{% endblock %}
এই উদাহরণটি MyModel মডেলের জন্য একটি বুটস্ট্র্যাপ লেআউট ফর্ম তৈরি
উদাহরণ ব্যাসিক কাস্টমাইজ : Loop ফর্ম
লুপ দিয়ে ডাইনামিক ভাবে একটা একটা নাকরে একসাথে সব ফর্ম এর কাজ করতে পারি।
class EmployeeIDDateFilterForm(forms.Form):
id_no = forms.CharField(max_length=20, label='Employee ID')
start_date = forms.DateField(label='Start Date', required=True,)
end_date = forms.DateField(label='End Date', required=True)
def __init__(self, *args, **kwargs):
super(EmployeeIDDateFilterForm, self).__init__(*args, **kwargs)
for field_name, field in self.fields.items():
field.widget.attrs.update({
'class': 'form-control form-control-sm',
'id': f"{field_name}",
})
<form action="" method="post">
{% csrf_token %}
{% for field_name, field in form %}
<div class="form-group">
<label for="{{ field_name }}">{{ field.label }}</label>
{{ field }}
</div>
{% endfor %}
<button type="submit" class="btn btn-primary">Submit</button>
</form>
উদাহরণ ব্যাসিক কাস্টমাইজ : Loop ফর্ম স্পেসিফিক কোনো ফর্ম ফিল্ড এর স্টাইল পরিবর্তন
যদি স্পেসিফিক কোনো ফর্ম ফিল্ড এর স্টাইল পরিবর্তন করতে হয়
class EmployeeIDDateFilterForm(forms.Form):
id_no = forms.CharField(max_length=20, label='Employee ID')
start_date = forms.DateField(label='Start Date', required=True,)
end_date = forms.DateField(label='End Date', required=True)
def __init__(self, *args, **kwargs):
super(EmployeeIDDateFilterForm, self).__init__(*args, **kwargs)
for field_name, field in self.fields.items():
if field_name == 'id_no':
field.widget.attrs.update({
'class': 'form-control form-control-sm abc-class',
'id': f"{field_name}",
})
else:
field.widget.attrs.update({
'class': 'form-control form-control-sm',
'id': f"{field_name}",
})
উদাহরণ Bootstrap : Loop ফর্ম
আমরা ৩ কলামের ফরম চাচ্ছি এবং ইনপুট ক্লাস(”form-control”) ব্যবহার করতে চাচ্ছি এজন্য নিচের মত করবো
class ItemForm(forms.Form):
name = forms.CharField(widget=forms.TextInput)
description = forms.CharField(widget=forms.TextInput)
def __init__(self, *args, **kwargs):
super(ItemForm, self).__init__(*args, **kwargs)
for field_name, field in self.fields.items():
field.widget.attrs.update({
'class': 'form-control',
'id': f"defaultForm-{field_name}",
})<form method="post">
{% csrf_token %}
<div class="row">
{% for field in form %}
<div class="col-md-4 mb-4">
<div class="form-group">
<label for="{{ field.auto_id }}">{{ field.label }}</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text">
<i class="fas fa-envelope"></i>
</span>
</div>
{{ field }}
</div>
</div>
</div>
{% endfor %}
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>Django ফর্ম এ ব্যবহৃত বিভিন্ন মেথড
Django ফর্মে ব্যবহৃত কিছু গুরুত্বপূর্ণ মেথড রয়েছে, যা ফর্ম ইনস্ট্যান্স তৈরি এবং এটির মাধ্যমে ডেটা ভ্যালিডেট করতে ব্যবহৃত হয়।
এটি একটি ফিল্ডে কাস্টম এরর যোগ করতে ব্যবহৃত হয়।
__init__():
ফর্ম ইনস্ট্যান্স তৈরি করতে এই মেথডটি ব্যবহার করা হয়। এটি ফর্মের ইনস্ট্যান্স তৈরির সাথে সাথে একটি কাস্টম ইনিশিয়ালাইজশন বুঝাতে ব্যবহৃত হয়।
cleaned_data:
এটি ফর্ম থেকে ভ্যালিডেট করা ডেটা প্রকাশ করে, যেটি ফর্মের সকল মেথড দ্বারা ভ্যালিডেট করা হয়েছে।
is_valid():
এটি ফর্মের ভ্যালিডেশন সঠিক কিনা তা চেক করে এবং তা ফলাফল হিসেবে ফ্রু করে।
is_multipart():
এটি যাচাই করে যে, ফর্মের ইনকোডিং যদি “multipart/form-data” হয় তাহলে ইতোমধ্যে ফর্মে কোনো যাচাই করার জন্য সৌজন্য তৈরি করেছে কিনা।
clean_<field_name>():
এটি একটি নির্দিষ্ট ফিল্ডের ডেটা ভ্যালিডেট করতে ব্যবহৃত হয়, এটি মূলত একটি ইনডিভিজুয়াল ফিল্ড এর জন্য কাস্টম ভ্যালিডেশন প্রদান করতে ব্যবহৃত হয়।
clean():
এটি ফর্মের সার্ভার সাইড ভ্যালিডেশনের জন্য ব্যবহৃত হয়, এটি ফর্মের সকল ফিল্ডের ডেটা এবং একটি সাধারিত স্টেটিক ভ্যালিডেশন প্রদান করতে ব্যবহৃত হয়।
has_changed():
এটি যাচাই করে যে, কোনো ফর্ম ডেটা পরিবর্তন হয়েছে কিনা।
add_error(field, error):
ফর্ম যখন প্রথম লোড হবে __init__ ()
মনে করুন আপনি একটি ফিল্ড ফর্ম এ দিয়েছেন ইন্টিজার নাম্বার এখন যখন আপনি ফরমটি তে কোনো ডেটা দিতে যাবেন দেখবেন নাম্বার শো করছে কিন্তু আপনি চাচ্ছেন ফিল্ড এর টাইপ যেন অন্য কিছু হয় তাহলে ফর্ম এ init () মেথড ব্যবহার করতে হবে।
from django import forms
class StudentForm(forms.Form):
phone_number = forms.CharField(max_length=20)
registration_number = forms.CharField(max_length=20, widget=forms.TextInput(attrs={'readonly': 'readonly'}))
def __init__(self, *args, **kwargs):
# Custom initialization goes here
super(StudentForm, self).__init__(*args, **kwargs)
# You can add custom attributes or modify fields here if needed
self.fields['phone_number'].widget.attrs['placeholder'] = 'Enter phone number'
# Example of using the form in a view
# student_form = StudentForm()
ফর্ম ভ্যালিডেশন
Django বিল্ট-ইন যাচাইকরণ নিয়ম
Django ফর্মগুলি ব্যবহার করে, ব্যবহারকারীদের কাছ থেকে তথ্য সংগ্রহ করা এবং সেই তথ্যটি যাচাই করা সহজ। Django ফর্মগুলিতে বিল্ট-ইন যাচাইকরণ রয়েছে যা আপনাকে সাধারণ যাচাইকরণ নিয়মগুলি প্রয়োগ করতে দেয়, যেমন ফাঁকা ক্ষেত্রগুলির জন্য যাচাই করা।
বিল্ট-ইন যাচাইকরণ নিয়ম
Django ফর্মগুলিতে বেশ কয়েকটি বিল্ট-ইন যাচাইকরণ নিয়ম রয়েছে। এই নিয়মগুলির মধ্যে রয়েছে:
max_length– ক্ষেত্রটির মান সর্বোচ্চ কত অক্ষর দীর্ঘ হতে পারে তা নির্দিষ্ট করে।min_length– ক্ষেত্রটির মান সর্বনিম্ন কত অক্ষর দীর্ঘ হতে পারে তা নির্দিষ্ট করে।required– ক্ষেত্রটি পূরণ করা বাধ্যতামূলক কিনা তা নির্দিষ্ট করে।unique– ক্ষেত্রটির মান ডেটাবেসে অবশ্যই অনন্য হতে হবে।
নিজস্ব যাচাইকরণ নিয়ম
- clean_<field_name>(): এটি একটি নির্দিষ্ট ফিল্ডের ডেটা ভ্যালিডেট করতে ব্যবহৃত হয়, এটি মূলত একটি ইনডিভিজুয়াল ফিল্ড এর জন্য কাস্টম ভ্যালিডেশন প্রদান করতে ব্যবহৃত হয়।
- clean(): এটি ফর্মের সার্ভার সাইড ভ্যালিডেশনের জন্য ব্যবহৃত হয়, এটি ফর্মের সকল ফিল্ডের ডেটা এবং একটি সাধারিত স্টেটিক ভ্যালিডেশন প্রদান করতে ব্যবহৃত হয়।
- cleaned_data: এটি ফর্ম থেকে ভ্যালিডেট করা ডেটা প্রকাশ করে, যেটি ফর্মের সকল মেথড দ্বারা ভ্যালিডেট করা হয়েছে। যেমন যদি forms.IntegerField() ব্যবহার করি এটা forms ক্লাসের IntegerField() এর ভ্যালিডেশন প্রথমে ব্যবহার করে ভ্যালিডেট হলে ভ্যালিডেট ডেটা দেবে। পরে কাস্টম ভ্যালিডেশন এ যাবে।
- is_valid(): এটা views.py বা আমরা যেখানে লজিক লিখবো সেখানে ফর্ম ভ্যালিড চেক করার জন্য ব্যবহার করা হয়।
clean_<field_name>() | Validating Single fields
class MyForm(forms.Form):
age = forms.IntegerField()
def clean_age(self):
age = self.cleaned_data['age']
if age < 18 or age > 120:
raise forms.ValidationError("Age must be between 18 and 120.")
clean() | Validating multiple fields
class MyForm(forms.Form):
password = forms.CharField(max_length=100)
password_confirm = forms.CharField(max_length=100)
def clean(self):
cleaned_data = super().clean()
password = cleaned_data.get('password')
password_confirm = cleaned_data.get('password_confirm')
if password != password_confirm:
raise forms.ValidationError({"password_confirm": "Passwords must match."})
return cleaned_data
মডেল ফর্ম ভ্যালিডেশন
আমরা একই নিয়মে মডেল ফর্ম ভ্যালিডেশন করতে পারি
Single Field validation
from django import forms
from .models import MyModel
class MyModelForm(forms.ModelForm):
class Meta:
model = MyModel
fields = ['name']
def clean_name(self):
name = self.cleaned_data['name']
if len(name) < 5:
raise forms.ValidationError("Name must be at least 5 characters long.")
return name
multiple Field validation
from django import forms
from .models import MyModel
class MyModelForm(forms.ModelForm):
class Meta:
model = MyModel
fields = ['name', 'age']
def clean(self):
cleaned_data = super().clean()
password = cleaned_data.get('password')
password_confirm = cleaned_data.get('password_confirm')
if password != password_confirm:
raise forms.ValidationError({"password_confirm": "Passwords must match."})
return cleaned_data
is_valid() :
form = MyForm(request.POST)
if form.is_valid():
# Process the form data
else:
# Handle the form errors
if not form.is_valid():
for field, errors in form.errors.items():
for error in errors:
print(f"{field}: {error}")
is_multipart
if request.method == 'POST':
# Create an instance of the form with the posted data
my_form = MyForm(request.POST, request.FILES)
# Check if the form is multipart
if my_form.is_multipart():
print("The form is multipart.")
else:
print("The form is not multipart.")from django import forms
class MyForm(forms.Form):
text_field = forms.CharField()
file_field = forms.FileField()
# In a view or somewhere else
if request.method == 'POST':
# Create an instance of the form with the posted data
my_form = MyForm(request.POST, request.FILES)
# Check if the form is valid and multipart
if my_form.is_valid() and my_form.is_multipart():
# Form is valid, process the data
text_data = my_form.cleaned_data['text_field']
file_data = my_form.cleaned_data['file_field']
# Additional processing logic
print("Form is valid and multipart.")
else:
# Form is not valid or not multipart, handle errors
print("Form is not valid or not multipart.")
else:
# Create an empty form for GET requests
my_form = MyForm()
# Check if the form is multipart
if my_form.is_multipart():
print("The form is multipart.")
else:
print("The form is not multipart.")
has_changed()
my_form = MyForm()
# Check if the form data has changed
if my_form.has_changed():
print("Form data has changed.")
else:
print("Form data has not changed.")