Oʻzbekiston respublikasi oliy ta’lim,fan va inovatsiya vazirligi Sana 14.12.2023 Hajmi 105,45 Kb. #118214
Bog'liq
mustaqil ta\'lim
OʻZBEKISTON RESPUBLIKASI OLIY TA’LIM,FAN VA INOVATSIYA VAZIRLIGI
MIRZO ULUG‘BEK NOMIDAGI MILLIY UNIVERSITETININIG JIZZAX FILIALI
AMALIY MATEMATIKA FAKULTETI
«KAMPYUTER ILIMLARI VA DASTURLASH» kafedrasi
“Python advance” FANIDAN
MUSTAQIL ISH
Mavzu: Modellarning tashqi ko'rinishini maxsus amaliy vazifaga moslashtirish.
Bajardi: “Axborot xavfsizligi” yoʻnalishi 4-kurs 130-20 guruh
Talabasi: Begimqulov Saidqosim
Tekshirdi: ULASHEV A. N.
Jizzax – 2023
Mavzu: Modellarning tashqi ko'rinishini maxsus amaliy vazifaga moslashtirish
Reja:
Django modellari -
Django modellari tashqi ko’rinishi
Modellar
Model ma'lumotlaringiz haqidagi yagona, aniq ma'lumot manbaidir. U siz saqlayotgan ma'lumotlarning muhim maydonlari va xatti-harakatlarini o'z ichiga oladi. Odatda, har bir model bitta ma'lumotlar bazasi jadvaliga mos keladi.
Asosiylari :
Har bir model quyi sinflarga ega bo'lgan Python sinfidir django.db.models.Model.
Modelning har bir atributi ma'lumotlar bazasi maydonini ifodalaydi.
Bularning barchasi bilan Django sizga avtomatik ravishda yaratilgan ma'lumotlar bazasiga kirish API'sini beradi; so'rovlar qilish- ga qarang .
Tez misol ¶
Ushbu misol modeli va ga Personega bo'lgan a ni belgilaydi :first_namelast_name
from django.db import models
class Person(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
first_nameva modelninglast_name maydonlaridir . Har bir maydon sinf atributi sifatida belgilanadi va har bir atribut ma'lumotlar bazasi ustuniga mos keladi.
Yuqoridagi Personmodel quyidagi kabi ma'lumotlar bazasi jadvalini yaratadi:
CREATE TABLE myapp_person (
"id" serial NOT NULL PRIMARY KEY,
"first_name" varchar(30) NOT NULL,
"last_name" varchar(30) NOT NULL
);
Ba'zi texnik eslatmalar:
Jadval nomi, myapp_person, ba'zi model metama'lumotlaridan avtomatik ravishda olinadi, lekin uni bekor qilish mumkin. Batafsil ma'lumot uchun Jadval nomlariga qarang .
Maydon idavtomatik ravishda qo'shiladi, ammo bu xatti-harakatni bekor qilish mumkin. Avtomatik asosiy kalit maydonlariga qarang .
Ushbu misoldagi SQL PostgreSQL sintaksisi yordamida formatlangan, ammo shuni ta'kidlash kerakki, Django sozlamalar faylida ko'rsatilgan ma'lumotlar bazasi serveriga moslashtirilgan SQL dan foydalanadi .CREATE TABLE
Modellardan foydalanish ¶
Modellaringizni aniqlaganingizdan so'ng, Djangoga ushbu modellardan foydalanmoqchi ekanligingizni aytishingiz kerak . Buni sozlamalar faylingizni tahrirlash va INSTALLED_APPSo'z ichiga olgan modul nomini qo'shish uchun sozlamani o'zgartirish orqali bajaring models.py.
Misol uchun, agar ilovangiz uchun modellar modulda yashasa myapp.models(skript tomonidan ilova uchun yaratilgan paket tuzilishi ), qisman o'qilishi kerak:manage.py startappINSTALLED_APPS
INSTALLED_APPS = [
#...
'myapp',
#...
]
Yangi ilovalarni qo'shsangiz INSTALLED_APPS, ishga tushirishni unutmang , ixtiyoriy ravishda avval ular uchun migratsiya qiling .manage.py migratemanage.py makemigrations
Maydonlar ¶
Modelning eng muhim qismi va modelning yagona talab qilinadigan qismi - u belgilaydigan ma'lumotlar bazasi maydonlarining ro'yxati. Maydonlar sinf atributlari bilan belgilanadi. , yoki kabi API modellariga zid bo'lgan maydon nomlarini tanlashdan ehtiyot bo'ling .cleansavedelete
Misol:
from django.db import models
class Musician(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
instrument = models.CharField(max_length=100)
class Album(models.Model):
artist = models.ForeignKey(Musician, on_delete=models.CASCADE)
name = models.CharField(max_length=100)
release_date = models.DateField()
num_stars = models.IntegerField()
Maydon turlari ¶
Modelingizdagi har bir maydon tegishli Fieldsinfning namunasi bo'lishi kerak. Django bir nechta narsalarni aniqlash uchun maydon sinfi turlaridan foydalanadi:
Ma'lumotlar bazasiga qanday ma'lumotlarni saqlash kerakligini ko'rsatadigan ustun turi (masalan INTEGER, VARCHAR, , TEXT).
Shakl maydonini ko'rsatishda foydalanish uchun standart HTML vidjeti (masalan , , ).
Django administratorida va avtomatik ravishda yaratilgan shakllarda qo'llaniladigan minimal tekshirish talablari.
O'nlab o'rnatilgan dala turlariga ega Django kemalari; to'liq ro'yxatni model maydoni ma'lumotnomasida topishingiz mumkin . Agar Django-ning o'rnatilganlari yordam bermasa, siz o'zingizning maydonlaringizni osongina yozishingiz mumkin; Maxsus model maydonlarini yozishga qarang .
Maydon variantlari
Har bir maydon maydonga xos argumentlarning ma'lum to'plamini oladi ( model maydoniga havolada hujjatlashtirilgan ). Masalan, CharField(va uning pastki sinflari) ma'lumotlarni saqlash uchun ishlatiladigan ma'lumotlar bazasi maydonining max_lengthhajmini belgilaydigan argumentni talab qiladi.VARCHAR
Bundan tashqari, barcha maydon turlari uchun mavjud bo'lgan umumiy argumentlar to'plami mavjud. Hammasi ixtiyoriy. Ular ma'lumotnomada to'liq tushuntirilgan , ammo bu erda eng ko'p ishlatiladiganlarning qisqacha xulosasi:
null
Agar bo'lsa , Django ma'lumotlar bazasidagi Truekabi bo'sh qiymatlarni saqlaydi . NULLStandart hisoblanadi False.
blank
Agar bo'lsa True, maydon bo'sh bo'lishiga ruxsat beriladi. Standart hisoblanadi False.
E'tibor bering, bu dan farq qiladi null. nullfaqat ma'lumotlar bazasi bilan bog'liq bo'lsa, blanktekshirish bilan bog'liq. Agar maydon mavjud bo'lsa blank=True, shaklni tekshirish bo'sh qiymatni kiritish imkonini beradi. Agar maydonda bo'lsa blank=False, maydon talab qilinadi.
choices
Ushbu maydon uchun tanlov sifatida foydalanish uchun 2-kartadan iborat ketma -ketlik . Agar bu berilgan bo'lsa, standart shakl vidjeti standart matn maydoni o'rniga tanlash maydoni bo'ladi va tanlovlarni berilgan tanlovlar bilan cheklaydi.
Tanlovlar ro'yxati quyidagicha ko'rinadi:
YEAR_IN_SCHOOL_CHOICES = [
('FR', 'Freshman'),
('SO', 'Sophomore'),
('JR', 'Junior'),
('SR', 'Senior'),
('GR', 'Graduate'),
]
Eslatma
Har safar o'zgarishlar tartibida yangi migratsiya yaratiladi choices.
Har bir kortejdagi birinchi element ma'lumotlar bazasida saqlanadigan qiymatdir. Ikkinchi element maydonning forma vidjeti tomonidan ko'rsatiladi.
Model misolini hisobga olgan holda, maydonning ko'rsatish qiymatiga usul choicesyordamida kirish mumkin get_FOO_display() . Masalan:
from django.db import models
class Person(models.Model):
SHIRT_SIZES = (
('S', 'Small'),
('M', 'Medium'),
('L', 'Large'),
)
name = models.CharField(max_length=60)
shirt_size = models.CharField(max_length=1, choices=SHIRT_SIZES)
>>> p = Person(name="Fred Flintstone", shirt_size="L")
>>> p.save()
>>> p.shirt_size
'L'
>>> p.get_shirt_size_display()
'Large'
choicesQisqacha aniqlash uchun sanab o'tish sinflaridan ham foydalanishingiz mumkin :
from django.db import models
class Runner(models.Model):
MedalType = models.TextChoices('MedalType', 'GOLD SILVER BRONZE')
name = models.CharField(max_length=60)
medal = models.CharField(blank=True, choices=MedalType.choices, max_length=10)
Qo'shimcha misollar model maydoniga havolada mavjud .
default
Maydon uchun standart qiymat. Bu qiymat yoki chaqiriladigan ob'ekt bo'lishi mumkin. Agar chaqirish mumkin bo'lsa, u har safar yangi ob'ekt yaratilganda chaqiriladi.
help_text
Shakl vidjeti bilan ko'rsatiladigan qo'shimcha "yordam" matni. Bu sizning maydoningiz formada ishlatilmasa ham, hujjatlar uchun foydalidir.
primary_key
Agar bo'lsa True, bu maydon model uchun asosiy kalit hisoblanadi.
primary_key=TrueAgar siz modelingizdagi biron bir maydonni belgilamasangiz , Django avtomatik ravishda asosiy kalitni ushlab turish uchun belgi qo'yadi, shuning uchun siz standart asosiy kalit xatti-harakatini bekor qilishni xohlamaguningizcha biron bir maydonga IntegerFieldo'rnatishingiz shart emas . primary_key=TrueQo'shimcha ma'lumot uchun Avtomatik asosiy kalit maydonlari ga qarang .
Asosiy kalit maydoni faqat o'qish uchun mo'ljallangan. Agar siz mavjud ob'ektdagi asosiy kalitning qiymatini o'zgartirib, keyin uni saqlasangiz, eskisi bilan birga yangi ob'ekt yaratiladi. Masalan:
from django.db import models
class Fruit(models.Model):
name = models.CharField(max_length=100, primary_key=True)
>>> fruit = Fruit.objects.create(name='Apple')
>>> fruit.name = 'Pear'
>>> fruit.save()
>>> Fruit.objects.values_list('name', flat=True)
unique
Agar bo'lsa True, bu maydon butun jadvalda yagona bo'lishi kerak.
Shunga qaramay, bu eng keng tarqalgan maydon variantlarining qisqacha tavsiflari. To'liq ma'lumotlarni umumiy model maydoni variant mos yozuvlar topish mumkin
Avtomatik asosiy kalit maydonlari ¶
AppConfig.default_auto_fieldOdatiy bo'lib, Django har bir modelga sozlamada har bir ilovada yoki global miqyosda ko'rsatilgan turga ega avtomatik oshiruvchi asosiy kalitni beradi DEFAULT_AUTO_FIELD. Masalan:
id = models.BigAutoField(primary_key=True)
Shaxsiy asosiy kalitni belgilamoqchi bo'lsangiz, primary_key=Truemaydonlaringizdan birida belgilang. Agar Django ni aniq belgilaganingizni ko'rsa Field.primary_key, u avtomatik ustunni qo'shmaydi id.
Har bir model aniq bir maydonga ega bo'lishini talab qiladi primary_key=True(aniq e'lon qilingan yoki avtomatik ravishda qo'shilgan).
Django 3.2 da o'zgartirildi:
Eski versiyalarda avtomatik yaratilgan asosiy kalit maydonlari har doim AutoFields edi.
Batafsil maydon nomlari ¶
ForeignKeyHar bir maydon turi , ManyToManyFieldva dan tashqari OneToOneField, ixtiyoriy birinchi pozitsion argumentni oladi - batafsil nom. Agar batafsil nom berilmagan bo'lsa, Django uni avtomatik ravishda maydonning atribut nomidan foydalanib yaratadi va pastki chiziqni bo'sh joylarga aylantiradi.
Ushbu misolda batafsil ism :"person's first name"
first_name = models.CharField("person's first name", max_length=30)
Ushbu misolda batafsil ism :"first name"
first_name = models.CharField(max_length=30)
ForeignKey, ManyToManyFieldva OneToOneFieldbirinchi argument namunaviy sinf boʻlishini talab qiladi, shuning uchun verbose_nameargument kalit soʻzidan foydalaning:
poll = models.ForeignKey(
Poll,
on_delete=models.CASCADE,
verbose_name="the related poll",
)
sites = models.ManyToManyField(Site, verbose_name="list of sites")
place = models.OneToOneField(
Place,
on_delete=models.CASCADE,
verbose_name="related place",
)
Konventsiya birinchi harfini bosh harf bilan yozishdan iborat emas verbose_name. Django kerak bo'lganda birinchi harfni avtomatik ravishda bosh harf bilan yozadi.
Aloqalar ¶
Shubhasiz, relyatsion ma'lumotlar bazalarining kuchi jadvallarni bir-biriga bog'lashda yotadi. Django ma'lumotlar bazasi munosabatlarining uchta eng keng tarqalgan turini aniqlash usullarini taklif qiladi: ko'pdan birga, ko'pdan ko'pga va birdan birga.
Ko'pdan-birga munosabatlar ¶
Ko'p-bir munosabatni aniqlash uchun dan foydalaning django.db.models.ForeignKey. Siz uni har qanday boshqa turdagi kabi ishlatasiz Field: uni modelingizning sinf atributi sifatida qo'shish orqali.
ForeignKeypozitsion argumentni talab qiladi: model bog'langan sinf.
Misol uchun, agar Carmodelda a bo'lsa Manufacturer, ya'ni a Manufacturerbir nechta avtomobillarni ishlab chiqaradi, lekin har birida Carfaqat bitta bo'lsa Manufacturer, quyidagi ta'riflardan foydalaning:
from django.db import models
class Manufacturer(models.Model):
# ...
pass
class Car(models.Model):
manufacturer = models.ForeignKey(Manufacturer, on_delete=models.CASCADE)
# ...
Shuningdek, siz rekursiv aloqalarni (o'ziga ko'p-bir munosabatga ega bo'lgan ob'ekt) va hali aniqlanmagan modellarga munosabatlarni yaratishingiz mumkin ; batafsil ma'lumot uchun model maydoni ma'lumotnomasiga qarang .
Maydon nomi ForeignKey( manufactureryuqoridagi misolda) model nomi kichik harf bilan bo'lishi tavsiya etiladi, lekin shart emas. Maydonni xohlaganingizcha chaqirishingiz mumkin. Masalan:
class Car(models.Model):
company_that_makes_it = models.ForeignKey(
Manufacturer,
on_delete=models.CASCADE,
)
# ...
Shuningdek qarang
ForeignKeymaydonlar model maydoni ma'lumotnomasida tushuntirilgan bir qator qo'shimcha argumentlarni qabul qiladi . Bu variantlar munosabatlar qanday ishlashi kerakligini aniqlashga yordam beradi; hammasi ixtiyoriy.
Orqaga bog'liq ob'ektlarga kirish bo'yicha batafsil ma'lumot uchun Quyidagi munosabatlarning orqaga qarab misoliga qarang .
Kod namunasi uchun Ko'p-bir munosabatlar modeli misoliga qarang .
Ko'pdan ko'pga munosabatlar ¶
Ko'p-ko'p munosabatini aniqlash uchun dan foydalaning ManyToManyField. Siz uni har qanday boshqa turdagi kabi ishlatasiz Field: uni modelingizning sinf atributi sifatida qo'shish orqali.
ManyToManyFieldpozitsion argumentni talab qiladi: model bog'langan sinf.
Misol uchun, agar a Pizzabir nechta ob'ektga ega bo'lsa Topping, ya'ni a Toppingbir nechta pitsalarda bo'lishi mumkin va har birida Pizzabir nechta qo'shimchalar mavjud bo'lsa, buni quyidagicha ifodalaysiz:
from django.db import models
class Topping(models.Model):
# ...
pass
class Pizza(models.Model):
# ...
toppings = models.ManyToManyField(Topping)
bilan bo'lgani kabi ForeignKey, siz ham rekursiv munosabatlarni (o'ziga ko'pdan ko'pga bog'liq bo'lgan ob'ekt) va hali aniqlanmagan modellarga munosabatlarni yaratishingiz mumkin .
Tavsiya etiladi, lekin talab qilinmaydi, a nomi ManyToManyField( toppingsyuqoridagi misolda) tegishli model ob'ektlari to'plamini tavsiflovchi ko'plik bo'lishi kerak.
Qaysi modelda bo'lishi muhim emas ManyToManyField, lekin siz uni faqat bitta modelga qo'yishingiz kerak - ikkalasini ham emas.
Odatda, ManyToManyFieldmisollar formada tahrir qilinadigan ob'ektga kirishi kerak. Yuqoridagi misolda ( a ga ega bo'lishdan ko'ra ) toppingsmavjud , chunki pitsa bir nechta pitsada bo'lganidan ko'ra, to'ldirishlari haqida o'ylash tabiiyroqdir. Shakl yuqorida qanday sozlangan bo'lsa, foydalanuvchilarga qo'shimchalarni tanlash imkonini beradi.PizzaToppingpizzas ManyToManyFieldPizza
Shuningdek qarang
To'liq misol uchun Ko'pdan ko'pga munosabatlar modeli misoliga qarang .
ManyToManyFieldmaydonlar, shuningdek , model maydoni ma'lumotnomasida tushuntirilgan bir qator qo'shimcha argumentlarni qabul qiladi . Bu variantlar munosabatlar qanday ishlashi kerakligini aniqlashga yordam beradi; hammasi ixtiyoriy.
Koʻpdan koʻpga munosabatlar boʻyicha qoʻshimcha maydonlar ¶
Agar siz faqat ko'p-ko'p munosabatlar bilan shug'ullanayotgan bo'lsangiz, masalan, pitsa va qo'shimchalarni aralashtirish va moslashtirish, ManyToManyFieldsizga kerak bo'lgan narsa standartdir. Biroq, ba'zida siz ma'lumotlarni ikkita model o'rtasidagi munosabatlar bilan bog'lashingiz kerak bo'lishi mumkin.
Masalan, musiqachilar mansub musiqiy guruhlarni kuzatuvchi ilova misolini ko'rib chiqing. Shaxs va ular a'zosi bo'lgan guruhlar o'rtasida ko'pdan ko'pga bog'liqlik mavjud, shuning uchun ManyToManyFieldbu munosabatlarni ifodalash uchun a dan foydalanishingiz mumkin. Biroq, siz to'plashni xohlashingiz mumkin bo'lgan a'zolik haqida juda ko'p tafsilotlar mavjud, masalan, odam guruhga qo'shilgan sana.
Bunday holatlar uchun Django sizga ko'p-ko'p munosabatlarini boshqarish uchun ishlatiladigan modelni belgilash imkonini beradi. Keyin oraliq modelga qo'shimcha maydonlarni qo'yishingiz mumkin. Oraliq model vositachi vazifasini bajaradigan modelga ishora qilish uchun argumentdan ManyToManyFieldfoydalanish bilan bog'liq . throughBizning musiqachi misolimiz uchun kod quyidagicha ko'rinadi:
from django.db import models
class Person(models.Model):
name = models.CharField(max_length=128)
def __str__(self):
return self.name
class Group(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField(Person, through='Membership')
def __str__(self):
return self.name
class Membership(models.Model):
person = models.ForeignKey(Person, on_delete=models.CASCADE)
group = models.ForeignKey(Group, on_delete=models.CASCADE)
date_joined = models.DateField()
invite_reason = models.CharField(max_length=64)
Vositachi modelni o'rnatganingizda, siz ko'p-ko'p munosabatlarida ishtirok etadigan modellarga tashqi kalitlarni aniq belgilaysiz. Ushbu aniq deklaratsiya ikkala modelning qanday bog'liqligini belgilaydi.
Oraliq modelda bir nechta cheklovlar mavjud:
Sizning oraliq modelingiz manba modeli uchun bitta va faqatGroup bitta xorijiy kalitni o'z ichiga olishi kerak (bu bizning misolimizda bo'ladi) yoki Django yordamida aloqa uchun foydalanishi kerak bo'lgan tashqi kalitlarni aniq ko'rsatishingiz kerak ManyToManyField.through_fields. Agar sizda bir nechta xorijiy kalit bo'lsa va through_fieldsko'rsatilmagan bo'lsa, tekshirish xatosi ko'tariladi. Xuddi shunday cheklov maqsadli modelning tashqi kalitiga ham tegishli (bu Personbizning misolimizda bo'ladi).
Vositachi model orqali o'ziga ko'p-ko'p munosabatiga ega bo'lgan model uchun bir xil modelning ikkita tashqi kalitiga ruxsat beriladi, lekin ular ko'p-ko'p munosabatlarining ikki (turli) tomoni sifatida ko'rib chiqiladi. Agar ikkitadan ortiq xorijiy kalit mavjud bo'lsa, siz ham through_fieldsyuqoridagi kabi belgilashingiz kerak, aks holda tekshirish xatosi paydo bo'ladi.
ManyToManyFieldEndi siz o'zingizning vositachi modelingizni (, bu holda) ishlatish uchun sozlaganingizdan so'ng Membership, siz ko'pdan ko'pga munosabatlarni yaratishga tayyormiz. Buni oraliq model namunalarini yaratish orqali amalga oshirasiz:
>>> ringo = Person.objects.create(name="Ringo Starr")
>>> paul = Person.objects.create(name="Paul McCartney")
>>> beatles = Group.objects.create(name="The Beatles")
>>> m1 = Membership(person=ringo, group=beatles,
... date_joined=date(1962, 8, 16),
... invite_reason="Needed a new drummer.")
>>> m1.save()
>>> beatles.members.all()
]>
>>> ringo.group_set.all()
]>
>>> m2 = Membership.objects.create(person=paul, group=beatles,
... date_joined=date(1960, 8, 1),
... invite_reason="Wanted to form a band.")
>>> beatles.members.all()
,
]>
Har qanday talab qilinadigan maydonlar uchun belgilaganingizdek, aloqalarni yaratish uchun ham , add()yoki create()dan foydalanishingiz mumkin :set()through_defaults
>>> beatles.members.add(john, through_defaults={'date_joined': date(1960, 8, 1)})
>>> beatles.members.create(name="George Harrison", through_defaults={'date_joined': date(1960, 8, 1)})
>>> beatles.members.set([john, paul, ringo, george], through_defaults={'date_joined': date(1960, 8, 1)})
Siz to'g'ridan-to'g'ri oraliq modelning namunalarini yaratishni afzal ko'rishingiz mumkin.
Agar oraliq model tomonidan aniqlangan maxsus jadval juftlikda bir nechta qiymatlarga ruxsat berib, o'ziga xoslikni ta'minlamasa, qo'ng'iroq barcha oraliq model misollarini olib tashlaydi:(model1, model2)remove()
>>> Membership.objects.create(person=ringo, group=beatles,
... date_joined=date(1968, 9, 4),
... invite_reason="You've been gone for a month and we miss you.")
>>> beatles.members.all()
,
,
]>
>>> # This deletes both of the intermediate model instances for Ringo Starr
>>> beatles.members.remove(ringo)
>>> beatles.members.all()
]>
Usul clear() misol uchun barcha ko'p-ko'p munosabatlarni olib tashlash uchun ishlatilishi mumkin:
>>> # Beatles have broken up
>>> beatles.members.clear()
>>> # Note that this deletes the intermediate model instances
>>> Membership.objects.all()
Ko'p-ko'p munosabatlarni o'rnatganingizdan so'ng, siz so'rovlar berishingiz mumkin. Oddiy ko'p-ko'p munosabatlaridagi kabi, siz ko'pdan-ko'pga bog'liq modelning atributlari yordamida so'rov qilishingiz mumkin:
# Find all the groups with a member whose name starts with 'Paul'
>>> Group.objects.filter(members__name__startswith='Paul')
]>
Oraliq modeldan foydalanayotganingizda, uning atributlari bo'yicha ham so'rashingiz mumkin:
# Find all the members of the Beatles that joined after 1 Jan 1961
>>> Person.objects.filter(
... group__name='The Beatles',
... membership__date_joined__gt=date(1961,1,1))
Agar aʼzolik maʼlumotlariga kirish zarur boʻlsa, buni toʻgʻridan-toʻgʻri Membershipmodelni soʻrash orqali amalga oshirishingiz mumkin:
>>> ringos_membership = Membership.objects.get(group=beatles, person=ringo)
>>> ringos_membership.date_joined
datetime.date(1962, 8, 16)
>>> ringos_membership.invite_reason
'Needed a new drummer.'
Xuddi shu ma'lumotga kirishning yana bir usuli - ob'ektdan ko'pdan ko'pga teskari munosabatni so'rash Person:
>>> ringos_membership = ringo.membership_set.get(group=beatles)
>>> ringos_membership.date_joined
datetime.date(1962, 8, 16)
>>> ringos_membership.invite_reason
'Needed a new drummer.'
Yakkama-yakka munosabatlar ¶
Birga bir munosabatni aniqlash uchun dan foydalaning OneToOneField. Siz uni har qanday boshqa turdagi kabi ishlatasiz Field: uni modelingizning sinf atributi sifatida qo'shish orqali.
Bu ob'ektning asosiy kalitida, agar u boshqa ob'ektni qandaydir tarzda "kengaytirsa" eng foydali bo'ladi.
OneToOneFieldpozitsion argumentni talab qiladi: model bog'langan sinf.
Misol uchun, agar siz "joylar" ma'lumotlar bazasini qurayotgan bo'lsangiz, ma'lumotlar bazasida manzil, telefon raqami va boshqalar kabi juda standart narsalarni qurasiz. Keyin, agar siz joylarning tepasida restoranlarning ma'lumotlar bazasini yaratmoqchi bo'lsangiz, o'zingizni takrorlash va modeldagi ushbu maydonlarni ko'paytirish o'rniga , to'g'ri kelishi Restaurantmumkin (chunki restoran "bu" joy; aslida, ishlov berish uchun bu odatda inheritance dan foydalanasiz , bu esa yashirin birma-bir munosabatni o'z ichiga oladi).RestaurantOneToOneFieldPlace
ga o'xshab ForeignKey, rekursiv munosabatni aniqlash va hali aniqlanmagan modellarga havola qilish mumkin.
Shuningdek qarang
To'liq misol uchun Yakka-bir munosabatlar modeli misoliga qarang .
OneToOneFieldmaydonlar ixtiyoriy parent_linkargumentni ham qabul qiladi.
OneToOneFieldsinflar avtomatik ravishda modeldagi asosiy kalitga aylanish uchun ishlatiladi. primary_keyBu endi to'g'ri emas (garchi xohlasangiz, argumentni qo'lda kiritishingiz mumkin ). OneToOneFieldShunday qilib, endi bitta modelda bir nechta turdagi maydonlarga ega bo'lish mumkin .
Fayllardagi modellar ¶
Modelni boshqa ilovadagi model bilan bog'lash juda yaxshi. Buni amalga oshirish uchun modelingiz belgilangan faylning yuqori qismidagi tegishli modelni import qiling. Keyin, kerak bo'lganda, boshqa model sinfiga murojaat qiling. Masalan:
from django.db import models
from geography.models import ZipCode
class Restaurant(models.Model):
# ...
zip_code = models.ForeignKey(
ZipCode,
on_delete=models.SET_NULL,
blank=True,
null=True,
)
Maydon nomi cheklovlari ¶
Django model maydon nomlariga ba'zi cheklovlar qo'yadi:
Maydon nomi Python uchun ajratilgan so'z bo'lishi mumkin emas, chunki bu Python sintaksisi xatosiga olib keladi. Masalan:
class Example(models.Model):
pass = models.IntegerField() # 'pass' is a reserved word!
Django so'rovlarini qidirish sintaksisi ishlashi tufayli maydon nomi qatorda bir nechta pastki chiziqni o'z ichiga olmaydi. Masalan:
class Example(models.Model):
foo__bar = models.IntegerField() # 'foo__bar' has two underscores!
Maydon nomi shunga o'xshash sabablarga ko'ra pastki chiziq bilan tugamaydi.
Ushbu cheklovlarni hal qilish mumkin, chunki sizning maydoningiz nomi ma'lumotlar bazasi ustun nomiga mos kelishi shart emas. Variantga qarang db_column.
join, whereyoki kabi SQL tomonidan zahiralangan so'zlar model maydon nomlari sifatida ruxsat etiladiselect , chunki Django har bir asosiy SQL so'rovida barcha ma'lumotlar bazasi jadvallari va ustun nomlaridan qochadi. U ma'lum ma'lumotlar bazasi dvigatelingizning iqtibos sintaksisidan foydalanadi.
Maxsus maydon turlari ¶
Mavjud model maydonlaridan birini maqsadlaringizga moslash uchun ishlatib bo'lmasa yoki kamroq tarqalgan ma'lumotlar bazasi ustun turlaridan foydalanmoqchi bo'lsangiz, o'zingizning maydon sinfingizni yaratishingiz mumkin. O'z maydonlaringizni yaratishning to'liq yoritilishi Maxsus model maydonlarini yozishda taqdim etiladi .
Metavariantlar ¶
Inner dan foydalanib modelingiz metamaʼlumotlarini bering , masalan:class Meta
from django.db import models
class Ox(models.Model):
horn_length = models.IntegerField()
class Meta:
ordering = ["horn_length"]
verbose_name_plural = "oxen"
Model meta-ma'lumotlari "maydon bo'lmagan har qanday narsa", masalan, buyurtma variantlari ( ordering), ma'lumotlar bazasi jadvali nomi ( db_table) yoki odam o'qiy oladigan birlik va ko'plik nomlari ( verbose_nameva verbose_name_plural). Hech kim talab qilinmaydi va modelga qo'shish butunlay ixtiyoriy.class Meta
Barcha mumkin bo'lgan variantlarning to'liq ro'yxatini model varianti ma'lumotnomasidaMeta topish mumkin .
Model atributlari ¶
objects
Modelning eng muhim atributi Manager. Bu Django modellariga ma'lumotlar bazasi so'rovi operatsiyalari taqdim etiladigan va ma'lumotlar bazasidan misollarni olish uchun foydalaniladigan interfeys . Hech qanday maxsus Managerbelgilanmagan bo'lsa, standart nom objects. Menejerlarga model misollari emas, balki faqat model sinflari orqali kirish mumkin.
Model usullari ¶
Ob'ektlaringizga maxsus "qator darajasidagi" funksiyalarni qo'shish uchun modeldagi maxsus usullarni belgilang. Usullar "jadval bo'ylab" ishlarni bajarish uchun mo'ljallangan bo'lsa-da Manager, model usullari ma'lum bir model misolida harakat qilishi kerak.
Bu biznes mantig'ini bir joyda saqlashning qimmatli usuli - model.
Masalan, ushbu modelda bir nechta maxsus usullar mavjud:
from django.db import models
class Person(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
birth_date = models.DateField()
def baby_boomer_status(self):
"Returns the person's baby-boomer status."
import datetime
if self.birth_date < datetime.date(1945, 8, 1):
return "Pre-boomer"
elif self.birth_date < datetime.date(1965, 1, 1):
return "Baby boomer"
else:
return "Post-boomer"
@property
def full_name(self):
"Returns the person's full name."
return '%s %s' % (self.first_name, self.last_name)
Ushbu misoldagi oxirgi usul xususiyatdir .
Model namunasi ma'lumotnomasida har bir modelga avtomatik ravishda berilgan usullarning to'liq ro'yxati mavjud . Ularning aksariyatini bekor qilishingiz mumkin – quyida oldindan belgilangan model usullarini bekor qilish ga qarang – lekin siz deyarli har doim aniqlamoqchi bo‘lgan ikkita juftlik mavjud:
__str__()
Har qanday ob'ektning satr tasvirini qaytaradigan Python "sehrli usuli". Python va Django har doim namunani majburlash va oddiy satr sifatida ko'rsatish kerak bo'lganda foydalanadi. Eng muhimi, bu ob'ektni interaktiv konsolda yoki administratorda ko'rsatganingizda sodir bo'ladi.
Siz har doim ushbu usulni belgilashni xohlaysiz; sukut bo'yicha unchalik foydali emas.
get_absolute_url()
Bu Djangoga ob'ektning URL manzilini qanday hisoblashni aytadi. Django buni o'zining administrator interfeysida ishlatadi va istalgan vaqtda ob'ektning URL manzilini aniqlashi kerak.
Uni noyob tarzda aniqlaydigan URL manziliga ega bo'lgan har qanday ob'ekt ushbu usulni belgilashi kerak.
Oldindan belgilangan model usullarini bekor qilish ¶
Siz moslashtirmoqchi bo'lgan ma'lumotlar bazasi xatti-harakatlarini qamrab oluvchi yana bir model usullari to'plami mavjud . save()Xususan, siz tez-tez yo'l va ishlashni o'zgartirishni xohlaysiz delete().
Siz xatti-harakatni o'zgartirish uchun ushbu usullarni (va boshqa har qanday model usulini) bekor qilishingiz mumkin.
O'rnatilgan usullarni bekor qilish uchun klassik foydalanish holati, agar siz ob'ektni saqlaganingizda biror narsa sodir bo'lishini xohlasangiz. Masalan ( save()qabul qilingan parametrlarning hujjatlari uchun qarang):
from django.db import models
class Blog(models.Model):
name = models.CharField(max_length=100)
tagline = models.TextField()
def save(self, *args, **kwargs):
do_something()
super().save(*args, **kwargs) # Call the "real" save() method.
do_something_else()
Shuningdek, saqlashni oldini olishingiz mumkin:
from django.db import models
class Blog(models.Model):
name = models.CharField(max_length=100)
tagline = models.TextField()
def save(self, *args, **kwargs):
if self.name == "Yoko Ono's blog":
return # Yoko shall never have her own blog!
else:
super().save(*args, **kwargs) # Call the "real" save() method.
Ob'ektning ma'lumotlar bazasida saqlanib qolishiga ishonch hosil qilish uchun superklass usulini chaqirishni esdan chiqarmaslik kerak - bu o'sha biznesdir. Agar siz superklass usulini chaqirishni unutib qo'ysangiz, standart xatti-harakatlar sodir bo'lmaydi va ma'lumotlar bazasiga tegmaydi.super().save(*args, **kwargs)
Model usuliga o'tilishi mumkin bo'lgan argumentlar orqali o'tishingiz ham muhim - bit shunday qiladi . Django vaqti-vaqti bilan yangi argumentlar qo'shib, o'rnatilgan model usullari imkoniyatlarini kengaytiradi. Agar siz usul ta'riflarida foydalansangiz, ular qo'shilganda kodingiz ushbu argumentlarni avtomatik ravishda qo'llab-quvvatlashiga kafolat beriladi.*args, **kwargs*args, **kwargs
O'chirilgan model usullari ommaviy operatsiyalarda chaqirilmaydi
E'tibor bering, delete()ob'ekt uchun usul QuerySet yordamida yoki natijasida ob'ektlarni ommaviy ravishda o'chirishda chaqirilishi shart emas . Moslashtirilgan o'chirish mantig'i bajarilishini ta'minlash uchun siz va/yoki signallardan foydalanishingiz mumkin.cascading deletepre_deletepost_delete
Afsuski, , va dan hech biri chaqirilmagani uchun qachon creatingyoki updatingommaviy ob'ektlarni hal qilishning iloji yo'q .save()pre_savepost_save
Maxsus SQL ni ishga tushirish ¶
Yana bir keng tarqalgan naqsh model usullari va modul darajasidagi usullarda maxsus SQL iboralarini yozishdir. Xom SQL dan foydalanish bo'yicha batafsil ma'lumot olish uchun raw SQL dan foydalanish bo'yicha hujjatlarga qarang .
Model merosi ¶
Django-da namunaviy meros Python-da oddiy sinf merosi bilan deyarli bir xil ishlaydi, ammo sahifaning boshidagi asoslarga hali ham amal qilish kerak. Bu shuni anglatadiki, asosiy sinf pastki sinfga ega bo'lishi kerak django.db.models.Model.
Siz qilishingiz kerak bo'lgan yagona qaror - siz ota-ona modellarining o'ziga xos model bo'lishini xohlaysizmi (o'z ma'lumotlar bazasi jadvallari bilan) yoki ota-onalar faqat bolalar modellari orqali ko'rinadigan umumiy ma'lumotlarga ega bo'lsa.
Djangoda mumkin bo'lgan uchta meros uslubi mavjud.
Ko'pincha, har bir bola modeli uchun yozishni istamaydigan ma'lumotlarni saqlash uchun ota-ona sinfidan foydalanishni xohlaysiz. Bu sinf hech qachon alohida ishlatilmaydi, shuning uchun abstrakt tayanch sinflar siz istagan narsadir.
Agar siz mavjud modelni (ehtimol, butunlay boshqa ilovadan biror narsa) subklassga ajratmoqchi bo'lsangiz va har bir modelning o'z ma'lumotlar bazasi jadvaliga ega bo'lishini xohlasangiz, ko'p jadvalli meros bu yo'ldir.
Nihoyat, agar siz modelning Python darajasidagi xatti-harakatlarini hech qanday tarzda modellar maydonlarini o'zgartirmasdan o'zgartirmoqchi bo'lsangiz, Proksi-server modellaridan foydalanishingiz mumkin .
Mavhum asosiy sinflar ¶
Mavhum tayanch sinflar ba'zi umumiy ma'lumotlarni boshqa bir qator modellarga qo'yishni xohlaganingizda foydalidir. Siz o'zingizning asosiy sinfingizni yozasiz va Metaabstract=True sinfiga qo'yasiz . Keyinchalik bu model hech qanday ma'lumotlar bazasi jadvalini yaratish uchun ishlatilmaydi. Buning o'rniga, u boshqa modellar uchun asosiy sinf sifatida foydalanilganda, uning maydonlari bolalar sinfiga qo'shiladi.
Misol:
from django.db import models
class CommonInfo(models.Model):
name = models.CharField(max_length=100)
age = models.PositiveIntegerField()
class Meta:
abstract = True
class Student(CommonInfo):
home_group = models.CharField(max_length=5)
Model Studentuchta maydonga ega bo'ladi: name, ageva home_group. Modeldan CommonInfooddiy Django modeli sifatida foydalanish mumkin emas, chunki u mavhum tayanch sinfdir. U ma'lumotlar bazasi jadvalini yaratmaydi yoki boshqaruvchiga ega emas va uni to'g'ridan-to'g'ri yaratish yoki saqlash mumkin emas.
Mavhum asosiy sinflardan meros bo'lib qolgan maydonlar boshqa maydon yoki qiymat bilan bekor qilinishi yoki bilan olib tashlanishi mumkin None.
Ko'p foydalanish uchun ushbu turdagi model merosi aynan siz xohlagan narsaga aylanadi. Bu Python darajasida umumiy ma'lumotlarni hisobga olish usulini taqdim etadi, shu bilan birga ma'lumotlar bazasi darajasida har bir bola modeli uchun faqat bitta ma'lumotlar bazasi jadvalini yaratadi.
Metameros olish ¶
Mavhum tayanch sinf yaratilganda, Django siz asosiy sinfda e'lon qilgan har qanday Meta ichki sinfini atribut sifatida mavjud qiladi. Agar bolalar sinfi o'zining Meta sinfini e'lon qilmasa, u ota-onaning Meta sinfini meros qilib oladi . Agar bola ota-onasining Meta sinfini kengaytirmoqchi bo'lsa , u uni pastki sinfga kiritishi mumkin. Masalan:
from django.db import models
class CommonInfo(models.Model):
# ...
class Meta:
abstract = True
ordering = ['name']
class Student(CommonInfo):
# ...
class Meta(CommonInfo.Meta):
db_table = 'student_info'
Django mavhum asosiy sinfning Meta sinfiga bitta tuzatish kiritadi : Meta atributini o'rnatishdan oldin u ni o'rnatadi abstract=False. Bu shuni anglatadiki, mavhum asosiy sinflarning bolalari avtomatik ravishda mavhum sinflarga aylanmaydi. Boshqa mavhum tayanch sinfdan meros bo'lgan mavhum asosiy sinfni yaratish uchun siz abstract=Truebolaga aniq o'rnatishingiz kerak.
Ba'zi atributlarni mavhum asosiy sinfning Meta sinfiga kiritish mantiqiy bo'lmaydi . Misol uchun, shu jumladan, barcha bolalar sinflari (o'z Meta nidb_table ko'rsatmaydiganlar ) bir xil ma'lumotlar bazasi jadvalidan foydalanishini anglatadi, bu deyarli siz xohlagan narsa emas.
Python merosining ishlash usuli tufayli, agar bolalar sinfi bir nechta mavhum asosiy sinflardan meros bo'lsa, sukut bo'yicha faqat birinchi sanab o'tilgan sinfdagi Meta variantlari meros qilib olinadi. Bir nechta mavhum asosiy sinflardan Meta variantlarini meros qilib olish uchun siz Meta merosini aniq e'lon qilishingiz kerak. Masalan:
from django.db import models
class CommonInfo(models.Model):
name = models.CharField(max_length=100)
age = models.PositiveIntegerField()
class Meta:
abstract = True
ordering = ['name']
class Unmanaged(models.Model):
class Meta:
abstract = True
managed = False
class Student(CommonInfo, Unmanaged):
home_group = models.CharField(max_length=5)
class Meta(CommonInfo.Meta, Unmanaged.Meta):
pass
related_nameva ¶ bilan ehtiyot bo'lingrelated_query_name
related_nameAgar siz yoki related_query_namedan foydalanayotgan bo'lsangiz ForeignKey, har doim maydon uchun noyobManyToManyField teskari nom va so'rov nomini ko'rsatishingiz kerak . Bu odatda mavhum asosiy sinflarda muammo tug'diradi, chunki bu sinfdagi maydonlar har bir bola sinfiga kiritilgan bo'lib, atributlar (shu jumladan va ) uchun har safar aynan bir xil qiymatlarga ega.related_namerelated_query_name
related_nameUshbu muammoni hal qilish uchun mavhum asosiy sinfdan foydalanayotganingizda related_query_name(faqat) qiymatning bir qismi '%(app_label)s'va ni o'z ichiga olishi kerak '%(class)s'.
'%(class)s'maydon ishlatiladigan bolalar sinfining kichik harflari nomi bilan almashtiriladi.
'%(app_label)s'bolalar sinfi joylashgan ilovaning kichik harf nomi bilan almashtiriladi. Har bir o'rnatilgan dastur nomi noyob bo'lishi kerak va har bir ilova ichidagi model sinf nomlari ham noyob bo'lishi kerak, shuning uchun natijada olingan nom boshqacha bo'ladi.
Misol uchun, berilgan ilova common/models.py:
from django.db import models
class Base(models.Model):
m2m = models.ManyToManyField(
OtherModel,
related_name="%(app_label)s_%(class)s_related",
related_query_name="%(app_label)s_%(class)ss",
)
class Meta:
abstract = True
class ChildA(Base):
pass
class ChildB(Base):
pass
Boshqa ilova bilan birga rare/models.py:
from common.models import Base
class ChildB(Base):
pass
common.ChildA.m2mMaydonning teskari nomi common_childa_relatedva teskari so'rov nomi bo'ladi common_childas. common.ChildB.m2mMaydonning teskari nomi common_childb_relatedva teskari so'rov nomi bo'ladi common_childbs. Nihoyat, maydonning teskari nomi rare.ChildB.m2mva rare_childb_relatedteskari so'rov nomi bo'ladi rare_childbs. Tegishli ism yoki soʻrov nomini yaratish uchun '%(class)s'va qismidan qanday foydalanish sizga bogʻliq , lekin agar siz undan foydalanishni unutib qoʻysangiz, Django tizimni tekshirishda (yoki ishga tushirishda ) xatoliklarni keltirib chiqaradi.'%(app_label)s'migrate
Agar siz mavhum tayanch sinfdagi maydon uchun atributni belgilamasangiz related_name , standart teskari nom bolalar sinfining nomi va undan keyin bo'ladi '_set', xuddi siz maydonni bevosita bolalar sinfida e'lon qilganingizda bo'lgani kabi. . Misol uchun, yuqoridagi kodda, agar related_name atribut o'tkazib yuborilgan bo'lsa, maydonning teskari nomi case va maydon uchun m2mbo'ladi .childa_setChildAchildb_setChildB
Ko'p jadvalli meros ¶
Django tomonidan qo'llab-quvvatlanadigan merosning ikkinchi turi - bu ierarxiyadagi har bir model o'z-o'zidan model bo'lganda. Har bir model o'zining ma'lumotlar bazasi jadvaliga to'g'ri keladi va ularni so'rash va alohida yaratish mumkin. Meros munosabatlari bola modeli va uning har bir ota-onasi o'rtasida bog'lanishni keltirib chiqaradi (avtomatik ravishda yaratilgan orqali OneToOneField). Masalan:
from django.db import models
class Place(models.Model):
name = models.CharField(max_length=50)
address = models.CharField(max_length=80)
class Restaurant(Place):
serves_hot_dogs = models.BooleanField(default=False)
serves_pizza = models.BooleanField(default=False)
ning barcha maydonlari Placeham mavjud bo'ladi Restaurant, garchi ma'lumotlar boshqa ma'lumotlar bazasi jadvalida joylashgan bo'lsa. Shunday qilib, bu ikkalasi ham mumkin:
>>> Place.objects.filter(name="Bob's Cafe")
>>> Restaurant.objects.filter(name="Bob's Cafe")
Agar sizda a bo'lsa , Placeu ham a bo'lsa , siz model nomining kichik harflar versiyasidan foydalanib ob'ektdan ob'ektga o'tishingiz Restaurantmumkin :PlaceRestaurant
>>> p = Place.objects.get(id=12)
# If p is a Restaurant object, this will give the child class:
>>> p.restaurant
Biroq, agar pyuqoridagi misolda a bo'lmasaRestaurant (u to'g'ridan-to'g'ri ob'ekt sifatida yaratilgan Placeyoki boshqa sinfning ota-onasi bo'lgan), ga murojaat qilish p.restaurantistisnoga olib keladi Restaurant.DoesNotExist .
OneToOneFieldUnda avtomatik ravishda yaratilgan Restauranthavola Placequyidagicha ko'rinadi:
place_ptr = models.OneToOneField(
Place, on_delete=models.CASCADE,
parent_link=True,
primary_key=True,
)
On OneToOneFieldbilan o'zingiznikini e'lon qilish orqali ushbu maydonni bekor qilishingiz mumkin .parent_link=TrueRestaurant
Metava ko'p jadvalli meros ¶
Ko'p jadvalli meros holatida bolalar sinfi uchun ota-onasining Meta sinfidan meros bo'lib qolish mantiqiy emas . Barcha Meta variantlari allaqachon ota-sinfga qo'llanilgan va ularni qayta qo'llash odatda faqat qarama-qarshi xatti-harakatlarga olib keladi (bu mavhum asosiy sinf holatidan farqli o'laroq, asosiy sinf o'z-o'zidan mavjud emas).
Shunday qilib, bola modeli ota-onasining Meta sinfiga kirish huquqiga ega emas . orderingBiroq, bola ota-onadan xatti-harakatni meros qilib oladigan bir nechta cheklangan holatlar mavjud: agar bola biror xususiyat yoki xususiyatni ko'rsatmasa get_latest_by, u ota-onasidan meros qilib oladi.
Agar ota-onaning buyurtmasi bo'lsa va siz bolada tabiiy tartib bo'lishini xohlamasangiz, uni aniq o'chirib qo'yishingiz mumkin:
class ChildModel(ParentModel):
# ...
class Meta:
# Remove parent's ordering effect
ordering = []
Meros va teskari munosabatlar ¶
Ko'p jadvalli meros bola va ota-onani bog'lash uchun yashirindan foydalanganligi sababli OneToOneField, yuqoridagi misolda bo'lgani kabi, ota-onadan bolaga o'tish mumkin. Biroq, bu va munosabatlar related_nameuchun standart qiymat bo'lgan nomdan foydalanadi . Agar siz ushbu turdagi munosabatlarni asosiy modelning pastki sinfiga qo'ysangiz, har bir bunday maydonda atributni ko'rsatishingiz kerak . Agar unutsangiz, Django tekshirish xatosini keltirib chiqaradi.ForeignKeyManyToManyFieldrelated_name
Masalan, yuqoridagi Placesinfdan yana foydalanib, quyidagi bilan boshqa kichik sinf yaratamiz ManyToManyField:
class Supplier(Place):
customers = models.ManyToManyField(Place)
Bu xatoga olib keladi:
Reverse query name for 'Supplier.customers' clashes with reverse query
name for 'Supplier.place_ptr'.
HINT: Add or change a related_name argument to the definition for
'Supplier.customers' or 'Supplier.place_ptr'.
related_nameMaydonga quyidagi tarzda qo'shish customersxatoni hal qiladi: .models.ManyToManyField(Place, related_name='provider')
Asosiy havola maydonini belgilash ¶
Yuqorida aytib o'tilganidek, Django avtomatik ravishda OneToOneFieldbolalar sinfini har qanday mavhum bo'lmagan ota-onalar modellari bilan bog'laydi. Agar siz ota-onaga qayta bog'langan atribut nomini nazorat qilmoqchi bo'lsangiz, o'zingizni yaratishingiz OneToOneFieldva parent_link=True maydoningiz ota-klassga havola ekanligini ko'rsatish uchun sozlashingiz mumkin.
Proksi-server modellari ¶
Ko'p jadvalli merosdan foydalanilganda , modelning har bir kichik sinfi uchun yangi ma'lumotlar bazasi jadvali yaratiladi. Bu odatda kerakli xatti-harakatdir, chunki quyi sinfga asosiy sinfda mavjud bo'lmagan qo'shimcha ma'lumotlar maydonlarini saqlash uchun joy kerak. Biroq, ba'zida siz faqat modelning Python harakatini o'zgartirishni xohlaysiz - ehtimol standart menejerni o'zgartirish yoki yangi usul qo'shish.
Bu proksi-server modeli merosi uchun: original model uchun proksi-server yaratish. Siz proksi-server modelining nusxalarini yaratishingiz, o'chirishingiz va yangilashingiz mumkin va barcha ma'lumotlar asl (proksisiz) modeldan foydalanayotgandek saqlanadi. Farqi shundaki, siz asl nusxani o'zgartirmasdan, standart model buyurtmasi yoki proksi-serverdagi standart menejer kabi narsalarni o'zgartirishingiz mumkin.
Proksi-serverlar oddiy modellar kabi e'lon qilinadi. proxySiz Djangoga sinfning atributini Metaga o'rnatish orqali uning proksi modeli ekanligini aytasiz True.
Misol uchun, siz modelga usul qo'shmoqchisiz deylik Person. Siz buni shunday qilishingiz mumkin:
from django.db import models
class Person(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
class MyPerson(Person):
class Meta:
proxy = True
def do_something(self):
# ...
pass
Sinf MyPersono'zining asosiy sinfi bilan bir xil ma'lumotlar bazasi jadvalida ishlaydi Person. Xususan, har qanday yangi misollar Personorqali ham kirish mumkin bo'ladi MyPersonva aksincha:
>>> p = Person.objects.create(first_name="foobar")
>>> MyPerson.objects.get(first_name="foobar")
Modeldagi boshqa standart tartibni belgilash uchun proksi-modeldan ham foydalanishingiz mumkin. Siz har doim modelga buyurtma berishni xohlamasligingiz mumkin Person, lekin last_nameproksi-serverdan foydalanganda atribut bo'yicha muntazam ravishda buyurtma bering:
class OrderedPerson(Person):
class Meta:
ordering = ["last_name"]
proxy = True
Endi oddiy Personso'rovlar tartibsiz bo'ladi va OrderedPersonso'rovlar tomonidan buyurtma qilinadi last_name.
Proksi modellari Metaatributlarni oddiy modellar kabi meros qilib oladi .
QuerySets hali ham so'ralgan modelni qaytaradi ¶
MyPersonOb'ektlarni so'raganingizda, masalan, Django ob'ektni qaytarishning hech qanday usuli yo'q Person. Ob'ektlar uchun so'rovlar to'plami Personushbu turdagi ob'ektlarni qaytaradi. Proksi ob'ektlarning mohiyati shundaki, asl nusxaga tayanadigan kod Personulardan foydalanadi va sizning kodingiz siz kiritgan kengaytmalardan foydalanishi mumkin (baribir boshqa hech qanday kod tayanmaydi). PersonBu (yoki boshqa) modelni hamma joyda o'zingiz yaratgan narsa bilan almashtirishning bir usuli emas .
Asosiy sinf cheklovlari ¶
Proksi-model aynan bitta mavhum bo'lmagan model sinfidan meros bo'lishi kerak. Siz bir nechta mavhum bo'lmagan modellarni meros qilib olmaysiz, chunki proksi-server modeli turli ma'lumotlar bazasi jadvallaridagi qatorlar o'rtasida hech qanday aloqani ta'minlamaydi. Proksi-model mavhum model sinflarining istalgan sonidan meros olishi mumkin, agar ular hech qanday model maydonlarini aniqlamasa . Proksi modeli, shuningdek, umumiy mavhum bo'lmagan ota-klassga ega bo'lgan har qanday miqdordagi proksi-modellardan meros bo'lishi mumkin.
Proksi-server modeli menejerlari ¶
Agar proksi-server modelida biron bir model menejerini ko'rsatmasangiz, u menejerlarni namunaviy ota-onadan meros qilib oladi. Agar siz proksi-server modelida menejerni aniqlasangiz, u birlamchi bo'ladi, lekin ota-ona sinflarida belgilangan barcha menejerlar mavjud bo'ladi.
PersonYuqoridagi misolimizni davom ettiradigan bo'lsak, siz ushbu modelni so'rashda ishlatiladigan standart menejerni o'zgartirishingiz mumkin :
from django.db import models
class NewManager(models.Manager):
# ...
pass
class MyPerson(Person):
objects = NewManager()
class Meta:
proxy = True
Agar siz proksi-serverga yangi menejerni mavjud standartni almashtirmasdan qo'shmoqchi bo'lsangiz, maxsus boshqaruv hujjatlarida tasvirlangan usullardan foydalanishingiz mumkin: yangi menejerlarni o'z ichiga olgan asosiy sinf yarating va uni asosiy tayanch sinfdan keyin meros qilib oling:
# Create an abstract class for the new manager.
class ExtraManagers(models.Model):
secondary = NewManager()
class Meta:
abstract = True
class MyPerson(Person, ExtraManagers):
class Meta:
proxy = True
Ehtimol, buni tez-tez qilishingiz shart emas, lekin buni qilsangiz, bu mumkin.
Proksi-server merosi va boshqarilmaydigan modellar o'rtasidagi farqlar ¶
managedProksi-server modelining merosi model sinfidagi atributdan foydalangan holda boshqarilmaydigan model yaratishga juda o'xshash bo'lishi mumkin Meta.
Ehtiyotkorlik bilan sozlash bilan Meta.db_tablesiz mavjud modelni soya qiladigan va unga Python usullarini qo'shadigan boshqarilmaydigan modelni yaratishingiz mumkin. Biroq, bu juda takrorlanadigan va mo'rt bo'ladi, chunki har qanday o'zgartirish kiritsangiz, ikkala nusxani ham sinxronlashtirishingiz kerak.
Boshqa tomondan, proksi-server modellari xuddi o'zlari proksi-server qilayotgan model kabi harakat qilishlari kerak. Ular har doim asosiy model bilan hamohang bo'ladi, chunki ular bevosita uning sohalari va menejerlarini meros qilib oladilar.
Umumiy qoidalar quyidagilar:
Agar siz mavjud model yoki ma'lumotlar bazasi jadvalini aks ettirayotgan bo'lsangiz va barcha asl ma'lumotlar bazasi jadvali ustunlarini xohlamasangiz, dan foydalaning Meta.managed=False. Ushbu parametr odatda Django nazorati ostida bo'lmagan ma'lumotlar bazasi ko'rinishlari va jadvallarini modellashtirish uchun foydalidir.
Agar siz modelning faqat Python xatti-harakatlarini o'zgartirmoqchi bo'lsangiz, lekin asl nusxadagi kabi barcha maydonlarni saqlasangiz, dan foydalaning Meta.proxy=True. Bu proksi modeli ma'lumotlar saqlanganida asl modelning saqlash tuzilishining aniq nusxasi bo'lishi uchun narsalarni o'rnatadi.
Bir nechta meros ¶
Xuddi Pythonning pastki klassifikatorida bo'lgani kabi, Django modeli ham bir nechta ota-ona modellaridan meros bo'lishi mumkin. Oddiy Python nomini aniqlash qoidalari qo'llanilishini yodda tuting. Muayyan nom (masalan, Meta ) paydo bo'ladigan birinchi asosiy sinf foydalaniladigan sinf bo'ladi; masalan, bu shuni anglatadiki, agar bir nechta ota-onalar Meta sinfiga ega bo'lsa, faqat birinchisi ishlatiladi va qolganlari e'tiborga olinmaydi.
Umuman olganda, siz bir nechta ota-onadan meros olishingiz shart emas. Bu foydali bo'lgan asosiy holat "aralash" sinflari uchundir: aralashmani meros qilib olgan har bir sinfga ma'lum bir qo'shimcha maydon yoki usul qo'shish. Meros ierarxiyasini iloji boricha sodda va tushunarli saqlashga harakat qiling, shunda ma'lum bir ma'lumot qayerdan kelganini aniqlash uchun qiynalmasligingiz kerak.
E'tibor bering, umumiy idasosiy kalit maydoniga ega bo'lgan bir nechta modellarni meros qilib olish xatolikni keltirib chiqaradi. AutoFieldBir nechta merosdan to'g'ri foydalanish uchun siz asosiy modellarda aniq foydalanishingiz mumkin :
class Article(models.Model):
article_id = models.AutoField(primary_key=True)
...
class Book(models.Model):
book_id = models.AutoField(primary_key=True)
...
class BookReview(Book, Article):
pass
Yoki ushlab turish uchun umumiy ajdoddan foydalaning AutoField. OneToOneFieldBu avtomatik ravishda yaratiladigan va bola tomonidan meros qilib olinadigan maydonlar o'rtasida to'qnashuvning oldini olish uchun har bir ota-ona modelidan umumiy ajdodga aniq foydalanishni talab qiladi :
class Piece(models.Model):
pass
class Article(Piece):
article_piece = models.OneToOneField(Piece, on_delete=models.CASCADE, parent_link=True)
...
class Book(Piece):
book_piece = models.OneToOneField(Piece, on_delete=models.CASCADE, parent_link=True)
...
class BookReview(Book, Article):
pass
“Yashirish” maydoni nomiga ruxsat berilmagan ¶
Oddiy Python klassi merosida, bolalar sinfiga ota-sinfdagi har qanday atributni bekor qilishga ruxsat beriladi. Djangoda bu odatda model maydonlari uchun ruxsat etilmaydi. Agar mavhum bo'lmagan modelning asosiy sinfida deb nomlangan maydon bo'lsa author, siz boshqa model maydonini yarata olmaysiz yoki authorushbu asosiy sinfdan meros bo'lgan har qanday sinfda chaqirilgan atributni aniqlay olmaysiz.
Ushbu cheklov mavhum modeldan meros bo'lib qolgan model maydonlariga taalluqli emas. Bunday maydonlar boshqa maydon yoki qiymat bilan bekor qilinishi yoki sozlash orqali olib tashlanishi mumkin .field_name = None
Ogohlantirish
Model menejerlari mavhum tayanch sinflardan meros bo'lib qolgan. Meros tomonidan havola qilingan meros maydonini bekor qilish Managernozik xatolarga olib kelishi mumkin. Maxsus menejerlar va model merosini ko'ring .
Eslatma
Ba'zi maydonlar modeldagi qo'shimcha atributlarni belgilaydi, masalan, a maydon nomiga qo'shilgan ForeignKeyqo'shimcha atributni , shuningdek , chet el modelida ham belgilaydi._idrelated_namerelated_query_name
Ushbu qo'shimcha atributlarni bekor qilib bo'lmaydi, agar uni belgilaydigan maydon qo'shimcha atributni belgilamasligi uchun o'zgartirilmasa yoki o'chirilmasa.
Asosiy modeldagi maydonlarni bekor qilish yangi misollarni ishga tushirish (qaysi maydonda ishga tushirilayotganini belgilash Model.__init__) va ketma-ketlashtirish kabi sohalarda qiyinchiliklarga olib keladi. Bu oddiy Python klassi merosi bilan bir xil tarzda shug'ullanishi shart bo'lmagan xususiyatlardir, shuning uchun Django modeli merosi va Python klassi merosi o'rtasidagi farq o'zboshimchalik bilan emas.
Ushbu cheklov faqat misollar bo'lgan atributlar uchun amal qiladi Field. Agar xohlasangiz, oddiy Python atributlari bekor qilinishi mumkin. Bu, shuningdek, Python koʻrgan atribut nomiga ham tegishli: agar siz maʼlumotlar bazasi ustuni nomini qoʻlda koʻrsatayotgan boʻlsangiz, bir xil ustun nomi koʻp jadvalli meros uchun ham kichik, ham ajdod modelida paydo boʻlishi mumkin (ular ustunlardir) ikki xil ma'lumotlar bazasi jadvallarida).
FieldErrorAgar siz har qanday ajdod modelidagi har qanday model maydonini bekor qilsangiz, Django a ko'taradi .
Paketdagi modellarni tartibga solish ¶
Buyruq faylni o'z ichiga olgan dastur tuzilmasini yaratadi . Agar sizda ko'plab modellar bo'lsa, ularni alohida fayllarda tashkil qilish foydali bo'lishi mumkin.manage.py startappmodels.py
Buning uchun modelspaketni yarating. Modellaringizni saqlash uchun fayl va fayllar bilan katalogni olib tashlang models.pyva yarating . Fayldagi modellarni import qilishingiz kerak .myapp/models/__init__.py__init__.py
Misol uchun, agar sizda organic.pyva synthetic.pykatalogda bo'lsa models :
myapp/models/__init__.py¶
from .organic import Person
from .synthetic import Robot
Foydalanishdan ko'ra har bir modelni aniq import qilish nomlar maydonini chalkashtirmaslik, kodni o'qishni osonlashtirish va kodni tahlil qilish vositalarini foydali saqlash kabi afzalliklarga ega.from .models import *
Model _metaAPI ¶
sinf Options[manba] ¶
Model _metaAPI Django ORM ning asosini tashkil etadi. Bu tizimning qidiruvlar, so'rovlar, shakllar va administrator kabi boshqa qismlariga har bir modelning imkoniyatlarini tushunish imkonini beradi. API-ga _metaob'ektning namunasi bo'lgan har bir model sinfining atributi orqali kirish mumkin django.db.models.options.Options.
U taqdim etgan usullardan quyidagilar uchun foydalanish mumkin:
Modelning barcha maydon misollarini oling
Modelning bitta maydon namunasini nomi bilan oling
Maydonga kirish API ¶
Modelning bitta maydon namunasini nomi bilan olish ¶
Options.get_field( maydon_nomi ) [manba] ¶
Maydon nomi berilgan maydon misolini qaytaradi.
field_namemodeldagi maydon nomi, mavhum yoki meros modeldagi maydon yoki modelga ishora qiluvchi boshqa modelda aniqlangan maydon bo'lishi mumkin. Ikkinchi holda, field_name (afzallik tartibida) related_query_name foydalanuvchi tomonidan to'plam, related_namefoydalanuvchi tomonidan to'plam yoki Django tomonidan avtomatik ravishda yaratilgan nom bo'ladi.
Hidden fieldsnomi bilan qaytarib bo'lmaydi.
Agar berilgan nomli maydon topilmasa, FieldDoesNotExististisno ko'tariladi.
>>> from django.contrib.auth.models import User
# A field on the model
>>> User._meta.get_field('username')
# A field from another model that has a relation with the current model
>>> User._meta.get_field('logentry')
# A non existent field
>>> User._meta.get_field('does_not_exist')
Traceback (most recent call last):
...
FieldDoesNotExist: User has no field named 'does_not_exist'
Modelning barcha maydon misollarini olish ¶
Options.get_fields( include_parents = True , include_hidden = False ) [manba] ¶
Model bilan bog'langan maydonlar to'plamini qaytaradi. get_fields()Qaysi maydonlar qaytarilishini boshqarish uchun ishlatilishi mumkin bo'lgan ikkita parametrni qabul qiladi:
include_parents
Trueavvalboshdan. Rekursiv ravishda ota-sinflarda belgilangan maydonlarni o'z ichiga oladi. ga o'rnatilgan bo'lsa False, get_fields()faqat joriy modelda to'g'ridan-to'g'ri e'lon qilingan maydonlarni qidiradi. Abstrakt modellar yoki proksi-sinflardan to'g'ridan-to'g'ri meros qilib olingan modellardagi maydonlar ota-onada emas, mahalliy deb hisoblanadi.
include_hidden
Falseavvalboshdan. ga o'rnatilgan bo'lsa True, get_fields()boshqa maydonning funksiyalarini qo'llab-quvvatlash uchun ishlatiladigan maydonlarni o'z ichiga oladi. Bunga “+” bilan boshlanadigan related_name(masalan ManyToManyField, yoki ) ega boʻlgan maydonlar ham kiradi .ForeignKey
>>> from django.contrib.auth.models import User
>>> User._meta.get_fields()
(,
,
,
,
,
,
,
,
,
,
,
,
,
)
# Also include hidden fields.
>>> User._meta.get_fields(include_hidden=True)
(,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
)