Avage Django vormide täielik potentsiaal. Õppige looma robustseid, taaskasutatavaid kohandatud validaatoreid igasuguste andmete valideerimise väljakutsete jaoks, alates lihtsatest funktsioonidest kuni keerukate klassideni.
Django vormide valideerimise meisterklass: põhjalik sukeldumine kohandatud validaatoritesse
Veebiarenduse maailmas on andmed kuningas. Teie rakenduse terviklikkus, turvalisus ja kasutatavus sõltuvad ühest kriitilisest protsessist: andmete valideerimisest. Tugev valideerimissüsteem tagab, et teie andmebaasi sisenevad andmed on puhtad, korrektsed ja turvalised. See kaitseb turvaaukude eest, ennetab frustreerivaid kasutajavigu ja hoiab teie rakenduse üldist tervist.
Django, oma "kõik vajalik kaasas" filosoofiaga, pakub võimsat ja paindlikku vormide raamistikku, mis on andmete valideerimisel silmapaistev. Kuigi selle sisseehitatud validaatorid katavad paljud levinud kasutusjuhud – alates e-posti vormingute kontrollimisest kuni miinimum- ja maksimumväärtuste kontrollimiseni – nõuavad reaalse maailma rakendused sageli spetsiifilisemaid, ärile orienteeritud reegleid. Just siin muutub kohandatud validaatorite loomise oskus mitte lihtsalt kasulikuks, vaid lausa professionaalseks vajaduseks.
See põhjalik juhend on mõeldud arendajatele üle maailma, kes soovivad liikuda põhitõdedest edasi. Me uurime kogu Django kohandatud valideerimise maastikku, alates lihtsatest eraldiseisvatest funktsioonidest kuni keerukate, taaskasutatavate ja seadistatavate klassideni. Lõpuks olete valmis lahendama mis tahes andmete valideerimise väljakutse puhta, tõhusa ja hooldatava koodiga.
Django valideerimismaastik: kiire ĂĽlevaade
Enne kui hakkame looma oma validaatoreid, on oluline mõista, kuhu nad Django mitmekihilises valideerimisprotsessis sobivad. Valideerimine Django vormis toimub tavaliselt järgmises järjekorras:
- Välja
to_python()
: Esimene samm on toorandmete teisendamine HTML-vormist sobivasse Pythoni andmetüüpi. NäiteksIntegerField
proovib sisendi teisendada täisarvuks. Kui see ebaõnnestub, tõstatatakse koheValidationError
. - Välja
validate()
: See meetod käivitab välja põhilise valideerimisloogika.EmailField
'i puhul kontrollitakse siin, kas väärtus näeb välja nagu kehtiv e-posti aadress. - Välja validaatorid: Siin tulevad mängu meie kohandatud validaatorid. Django käivitab kõik validaatorid, mis on loetletud välja
validators
argumendis. Need on taaskasutatavad "callable"-objektid, mis kontrollivad ühte väärtust. - Vormi
clean_<fieldname>()
: Pärast üldiste välja validaatorite käivitamist otsib Django teie vormiklassist meetodit nimegaclean_
, millele järgneb välja nimi. See on koht väljaspetsiifilisele valideerimisloogikale, mida pole vaja mujal taaskasutada. - Vormi
clean()
: Lõpuks kutsutakse välja see meetod. See on ideaalne koht valideerimiseks, mis nõuab mitme välja väärtuste võrdlemist (nt tagades, et 'parooli kinnituse' väli vastab 'parooli' väljale).
Selle järjestuse mõistmine on ülioluline. See aitab teil otsustada, kuhu paigutada oma kohandatud loogika maksimaalse tõhususe ja selguse saavutamiseks.
Samm edasi põhitõdedest: millal luua kohandatud validaatoreid
Django sisseehitatud validaatorid nagu EmailValidator
, MinValueValidator
ja RegexValidator
on võimsad, kuid paratamatult puutute kokku stsenaariumitega, mida need ei kata. Mõelge nendele levinud globaalsetele ärinõuetele:
- Kasutajanime reeglid: Vältida kasutajatel valida kasutajanimesid, mis sisaldavad reserveeritud sõnu, roppusi või sarnanevad e-posti aadressidega.
- Valdkonnaspetsiifilised identifikaatorid: Vormingute valideerimine nagu rahvusvaheline standardne raamatunumber (ISBN), ettevõtte sisene toote SKU või riiklik isikukood.
- Vanusepiirangud: Tagada, et kasutaja sisestatud sünnikuupäev vastab teatud vanusepiirist kõrgemale vanusele (nt 18 aastat).
- Sisu reeglid: Nõuda, et blogipostituse sisu oleks minimaalse sõnade arvuga või ei sisaldaks teatud HTML-märgiseid.
- API-võtme valideerimine: Kontrollida, kas sisestatud string vastab konkreetsele keerukale mustrile, mida kasutatakse sisemiste või väliste API-võtmete jaoks.
Nendel juhtudel on kohandatud validaatori loomine kõige puhtam ja taaskasutatavam lahendus.
Ehituskivid: funktsioonipõhised validaatorid
Lihtsaim viis kohandatud validaatori loomiseks on kirjutada funktsioon. Validaatorfunktsioon on otsekohene "callable", mis aktsepteerib ühte argumenti – valideeritavat väärtust – ja tõstatab django.core.exceptions.ValidationError
, kui andmed on valed. Kui andmed on kehtivad, peaks funktsioon lihtsalt väärtust tagastamata lõpetama (st tagastama None
).
Kõigepealt impordime vajaliku erandi. Kõik meie validaatorid vajavad seda.
# In a validators.py file within your Django app
from django.core.exceptions import ValidationError
from django.utils.translation import gettext_lazy as _
Pange tähele gettext_lazy as _
kasutamist. See on kriitiline parim praktika globaalsele publikule mõeldud rakenduste loomisel. See märgib stringid tõlkimiseks, nii et teie veateateid saab kuvada kasutaja eelistatud keeles.
Näide 1: minimaalse sõnade arvu validaator
Kujutage ette, et teil on tagasisidevorm tekstialaga ja te soovite tagada, et tagasiside oleks piisavalt sisukas, nõudes vähemalt 10 sõna.
def validate_min_words(value):
"""Validates that the text has at least 10 words."""
word_count = len(str(value).split())
if word_count < 10:
raise ValidationError(
_('Please provide more detailed feedback. A minimum of 10 words is required.'),
code='min_words'
)
Põhipunktid:
- Funktsioon võtab ühe argumendi,
value
. - See teostab oma loogika (sõnade lugemine).
- Kui tingimus ei ole täidetud, tõstatab see
ValidationError
kasutajasõbraliku, tõlgitava teatega. - Oleme lisanud ka valikulise
code
parameetri. See annab veale unikaalse identifikaatori, mis võib olla kasulik peenemaks veakäsitluseks teie vaadetes või mallides.
Selle validaatori kasutamiseks importige see lihtsalt oma forms.py
faili ja lisage see välja validators
nimekirja:
# In your forms.py
from django import forms
from .validators import validate_min_words
class FeedbackForm(forms.Form):
email = forms.EmailField()
feedback_text = forms.CharField(
widget=forms.Textarea,
validators=[validate_min_words] # Attaching the validator
)
Näide 2: keelatud kasutajanimede validaator
Loome validaatori, et takistada kasutajatel registreerumast levinud, reserveeritud või sobimatute kasutajanimedega.
# In your validators.py
BANNED_USERNAMES = ['admin', 'root', 'support', 'contact', 'webmaster']
def validate_banned_username(value):
"""Raises a ValidationError if the username is in the banned list."""
if value.lower() in BANNED_USERNAMES:
raise ValidationError(
_('This username is reserved and cannot be used.'),
code='reserved_username'
)
Seda funktsiooni on sama lihtne rakendada registreerimisvormi kasutajanime väljale. See lähenemine on puhas, modulaarne ja hoiab teie valideerimisloogika vormide definitsioonidest eraldi.
Võimsus ja taaskasutatavus: klassipõhised validaatorid
Funktsioonipõhised validaatorid sobivad suurepäraselt lihtsate, fikseeritud reeglite jaoks. Aga mis siis, kui vajate konfigureeritavat validaatorit? Näiteks, mis siis, kui soovite minimaalse sõnade arvu validaatorit, kuid nõutav arv peaks ühel vormil olema 5 ja teisel 50?
Siin säravad klassipõhised validaatorid. Need võimaldavad parameetrite määramist, muutes need uskumatult paindlikuks ja taaskasutatavaks kogu teie projektis.
Klassipõhine validaator on tavaliselt klass, mis implementeerib __call__(self, value)
meetodi. Kui klassi eksemplari kasutatakse validaatorina, kutsub Django välja selle __call__
meetodi. Me saame kasutada __init__
meetodit konfiguratsiooniparameetrite vastuvõtmiseks ja salvestamiseks.
Näide 1: konfigureeritav miinimumvanuse validaator
Loome validaatori, et tagada kasutaja vanus üle teatud piiri, tuginedes tema sisestatud sünnikuupäevale. See on levinud nõue teenustele, mille vanusepiirangud võivad erineda piirkonniti või toodete lõikes.
# In your validators.py
from datetime import date
from django.utils.deconstruct import deconstructible
@deconstructible
class MinimumAgeValidator:
"""Validates that the user is at least a certain age."""
def __init__(self, min_age):
self.min_age = min_age
def __call__(self, value):
today = date.today()
# Calculate age based on the year difference, then adjust for birthday not yet passed this year
age = today.year - value.year - ((today.month, today.day) < (value.month, value.day))
if age < self.min_age:
raise ValidationError(
_('You must be at least %(min_age)s years old to register.'),
params={'min_age': self.min_age},
code='min_age'
)
def __eq__(self, other):
return isinstance(other, MinimumAgeValidator) and self.min_age == other.min_age
Vaatame selle ĂĽksikasjalikumalt ĂĽle:
__init__(self, min_age)
: Konstruktor võtab meie parameetri,min_age
, ja salvestab selle eksemplarile (self.min_age
).__call__(self, value)
: See on valideerimise põhilogika. See saab välja väärtuse (mis peaks olemadate
objekt) ja teostab vanuse arvutuse. See kasutab võrdluseks salvestatudself.min_age
väärtust.- Veateate parameetrid: Pange tähele
params
sõnastikkuValidationError
'is. See on puhas viis muutujate süstimiseks oma veateate stringi. Sõnumis olev%(min_age)s
asendatakse sõnastiku väärtusega. @deconstructible
: See dekoraatordjango.utils.deconstruct
'ist on väga oluline. See ütleb Djangole, kuidas validaatori eksemplari serialiseerida. See on hädavajalik, kui kasutate validaatorit mudeli väljal, kuna see võimaldab Django migratsiooniraamistikul validaatori ja selle konfiguratsiooni korrektselt migratsioonifailidesse salvestada.__eq__(self, other)
: Seda meetodit on vaja ka migratsioonide jaoks. See võimaldab Djangol võrrelda kahte validaatori eksemplari, et näha, kas need on samad.
Selle klassi kasutamine vormis on intuitiivne:
# In your forms.py
from django import forms
from .validators import MinimumAgeValidator
class RegistrationForm(forms.Form):
username = forms.CharField()
# We can instantiate the validator with our desired age
date_of_birth = forms.DateField(validators=[MinimumAgeValidator(18)])
Nüüd saate hõlpsasti kasutada MinimumAgeValidator(21)
või MinimumAgeValidator(16)
mujal oma projektis ilma loogikat ĂĽmber kirjutamata.
Kontekst on võtmetähtsusega: väljaspetsiifiline ja vormiülene valideerimine
Mõnikord on valideerimisloogika kas liiga spetsiifiline ühele vormiväljale, et õigustada taaskasutatava validaatori loomist, või see sõltub mitme välja väärtustest korraga. Nendeks juhtudeks pakub Django valideerimiskonksusid otse vormiklassi sees.
Meetod clean_<fieldname>()
Saate lisada oma vormiklassile meetodi mustriga clean_<fieldname>
, et teostada konkreetse välja jaoks kohandatud valideerimist. See meetod käivitatakse pärast välja vaikimisi validaatorite käivitamist.
See meetod peab alati tagastama välja puhastatud väärtuse, olenemata sellest, kas seda on muudetud või mitte. See tagastatud väärtus asendab olemasoleva väärtuse vormi cleaned_data
's.
Näide: kutsekoodi validaator
Kujutage ette registreerimisvormi, kus kasutaja peab sisestama spetsiaalse kutsekoodi ja see kood peab sisaldama alamsõnet "-PROMO-". See on väga spetsiifiline reegel, mida tõenäoliselt uuesti ei kasutata.
# In your forms.py
from django import forms
from django.core.exceptions import ValidationError
from django.utils.translation import gettext_lazy as _
class InvitationForm(forms.Form):
email = forms.EmailField()
invitation_code = forms.CharField()
def clean_invitation_code(self):
# The data for the field is in self.cleaned_data
data = self.cleaned_data['invitation_code']
if "-PROMO-" not in data:
raise ValidationError(
_("Invalid invitation code. The code must be a promotional code."),
code='not_promo_code'
)
# Always return the cleaned data!
return data
Meetod clean()
mitme välja valideerimiseks
Kõige võimsam valideerimiskonks on vormi globaalne clean()
meetod. See käivitub pärast kõigi individuaalsete clean_<fieldname>
meetodite lõpuleviimist. See annab teile juurdepääsu kogu self.cleaned_data
sõnastikule, võimaldades teil kirjutada valideerimisloogikat, mis võrdleb mitut välja.
Kui leiate valideerimisvea clean()
meetodis, ei tohiks te otse ValidationError
'i tõstatada. Selle asemel kasutage vormi add_error()
meetodit. See seostab vea korrektselt asjakohase välja (väljadega) või kogu vormiga.
Näide: kuupäevavahemiku valideerimine
Klassikaline ja universaalselt mõistetav näide on sündmuse broneerimisvormi valideerimine, et tagada 'lõppkuupäev' on pärast 'alguskuupäeva'.
# In your forms.py
class EventBookingForm(forms.Form):
event_name = forms.CharField()
start_date = forms.DateField()
end_date = forms.DateField()
def clean(self):
# Super() is called first to get the cleaned_data from the parent.
cleaned_data = super().clean()
start_date = cleaned_data.get("start_date")
end_date = cleaned_data.get("end_date")
# Check if both fields are present before comparing
if start_date and end_date:
if end_date < start_date:
# Associate the error with the 'end_date' field
self.add_error('end_date', _("The end date cannot be before the start date."))
# You can also associate it with the form in general (a non-field error)
# self.add_error(None, _("Invalid date range provided."))
return cleaned_data
Põhipunktid clean()
meetodi kohta:
- Kutsuge alati alguses
super().clean()
, et pärida vanemklassi valideerimisloogika. - Kasutage
cleaned_data.get('fieldname')
väljade väärtustele turvaliseks juurdepääsuks, kuna need ei pruugi olla olemas, kui nad varasemates valideerimisetappides ebaõnnestusid. - Kasutage
self.add_error('fieldname', 'Veateade')
, et teatada veast konkreetse välja puhul. - Kasutage
self.add_error(None, 'Veateade')
, et teatada väljaga mitteseotud veast, mis ilmub vormi ülaosas. - Te ei pea
cleaned_data
sõnastikku tagastama, kuid see on hea tava.
Validaatorite integreerimine mudelite ja ModelFormidega
Üks Django võimsamaid omadusi on võime lisada validaatoreid otse oma mudeli väljadele. Kui teete seda, muutub valideerimine teie andmekihi lahutamatuks osaks.
See tähendab, et iga sellest mudelist loodud ModelForm
pärib ja rakendab need validaatorid automaatselt. Lisaks käivitab mudeli full_clean()
meetodi kutsumine (mida ModelForm
id teevad automaatselt) ka need validaatorid, tagades andmete terviklikkuse isegi objektide programmilisel loomisel või Django admini kaudu.
Näide: validaatori lisamine mudeli väljale
Võtame meie varasema validate_banned_username
funktsiooni ja rakendame selle otse kohandatud kasutajaprofiili mudelile.
# In your models.py
from django.db import models
from .validators import validate_banned_username
class UserProfile(models.Model):
username = models.CharField(
max_length=150,
unique=True,
validators=[validate_banned_username] # Validator applied here
)
# ... other fields
Ongi kõik! Nüüd käivitab iga UserProfile
'il põhinev ModelForm
automaatselt meie kohandatud validaatori username
väljal. See jõustab reegli andmeallika tasemel, mis on kõige robustsem lähenemine.
Edasijõudnute teemad ja parimad praktikad
Oma validaatorite testimine
Testimata kood on katkine kood. Validaatorid on puhas äriloogika ja on tavaliselt väga lihtsad ühiktestimiseks. Peaksite looma test_validators.py
faili ja kirjutama testid, mis katavad nii kehtivaid kui ka kehtetuid sisendeid.
# In your test_validators.py
from django.test import TestCase
from django.core.exceptions import ValidationError
from .validators import validate_min_words, MinimumAgeValidator
from datetime import date, timedelta
class ValidatorTests(TestCase):
def test_min_words_validator_valid(self):
# This should not raise an error
try:
validate_min_words("This is a perfectly valid sentence with more than ten words.")
except ValidationError:
self.fail("validate_min_words() raised ValidationError unexpectedly!")
def test_min_words_validator_invalid(self):
# This should raise an error
with self.assertRaises(ValidationError):
validate_min_words("Too short.")
def test_minimum_age_validator_valid(self):
validator = MinimumAgeValidator(18)
eighteen_years_ago = date.today() - timedelta(days=18*365 + 4) # Add leap years
try:
validator(eighteen_years_ago)
except ValidationError:
self.fail("MinimumAgeValidator raised ValidationError unexpectedly!")
def test_minimum_age_validator_invalid(self):
validator = MinimumAgeValidator(18)
seventeen_years_ago = date.today() - timedelta(days=17*365)
with self.assertRaises(ValidationError):
validator(seventeen_years_ago)
Veateadete sõnastikud
Veelgi puhtama koodi jaoks saate määratleda kõik oma veateated otse vormiväljal, kasutades error_messages
argumenti. See on eriti kasulik vaikesõnumite üle kirjutamiseks.
class MyForm(forms.Form):
email = forms.EmailField(
error_messages={
'required': _('Please enter your email address.'),
'invalid': _('Please enter a valid email address format.')
}
)
Kokkuvõte: robustsete ja kasutajasõbralike rakenduste loomine
Kohandatud valideerimine on iga tõsise Django arendaja jaoks hädavajalik oskus. Sisseehitatud tööriistadest kaugemale liikudes saate võime jõustada keerulisi ärireegleid, parandada andmete terviklikkust ja luua oma kasutajatele üle maailma intuitiivsema ja veakindlama kogemuse.
Pidage meeles neid põhipunkte:
- Kasutage funktsioonipõhiseid validaatoreid lihtsate, mittekonfigureeritavate reeglite jaoks.
- Võtke omaks klassipõhised validaatorid võimsa, konfigureeritava ja taaskasutatava loogika jaoks. Ärge unustage kasutada
@deconstructible
'i. - Kasutage
clean_<fieldname>()
ühekordseks valideerimiseks, mis on spetsiifiline ühele väljale ühel vormil. - Kasutage
clean()
meetodit keeruliseks valideerimiseks, mis hõlmab mitut välja. - Lisage validaatorid mudeli väljadele alati, kui võimalik, et jõustada andmete terviklikkust allikas.
- Kirjutage alati oma validaatoritele ühiktestid, et tagada nende ootuspärane toimimine.
- Kasutage alati
gettext_lazy
't veateadete jaoks, et luua globaalsele publikule valmis rakendusi.
Nende tehnikate valdamisega saate tagada, et teie Django rakendused pole mitte ainult funktsionaalsed, vaid ka robustsed, turvalised ja professionaalsed. Olete nüüd varustatud, et tulla toime mis tahes valideerimise väljakutsega, mis teie teele satub, luues kõigile paremat ja usaldusväärsemat tarkvara.