from django.db import models
class Person(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
CREATE TABLE myapp_person (
"id" serial NOT NULL PRIMARY KEY,
"first_name" varchar(30) NOT NULL,
"last_name" varchar(30) NOT NULL
);
INSTALLED_APPS = (
#...
'mysite.myapp',
#...
)
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)
name = models.CharField(max_length=100)
release_date = models.DateField()
num_stars = models.IntegerField()
Если True, поле не обязательно и может быть пустым. По-умолчанию - False.
Это не то же что и null. null относится к базе данных, blank - к проверке данных. Если поле содержит blank=True, интерфейс администратора позволит добавлять пустое значение. При blank=False - поле обязательно.
An iterable (e.g., a list or tuple) of 2-tuples to use as choices for this field. При определении, интерфейс администратора использует select вместо стандартного текстового поля и ограничит значение поля указанными значениями.
Список значений выглядит:
YEAR_IN_SCHOOL_CHOICES = (
(u'FR', u'Freshman'),
(u'SO', u'Sophomore'),
(u'JR', u'Junior'),
(u'SR', u'Senior'),
(u'GR', u'Graduate'),
)
Первый элемент в кортеже - значение хранимое в базе данных, второй элемент - отображается на странице, или в ModelChoiceField. Для получения отображаемого значения используется метод get_FOO_display экземпляра модели. Например:
from django.db import models
class Person(models.Model):
GENDER_CHOICES = (
(u'M', u'Male'),
(u'F', u'Female'),
)
name = models.CharField(max_length=60)
gender = models.CharField(max_length=2, choices=GENDER_CHOICES)
>>> p = Person(name="Fred Flintstone", gender="M")
>>> p.save()
>>> p.gender
u'M'
>>> p.get_gender_display()
u'Male'
При ``True``поле будет первичным ключом.
Если primary_key=True не указан ни для одного поля, Django самостоятельно добавит поле типа IntegerField для хранения первичного ключа, по-этому вам не обязательно указывать primary_key=True для каждой модели. Подробнее Первичный ключ по-умолчанию.
id = models.AutoField(primary_key=True)
first_name = models.CharField("person's first name", max_length=30)
first_name = models.CharField(max_length=30)
poll = models.ForeignKey(Poll, verbose_name="the related poll")
sites = models.ManyToManyField(Site, verbose_name="list of sites")
place = models.OneToOneField(Place, verbose_name="related place")
class Manufacturer(models.Model):
# ...
class Car(models.Model):
manufacturer = models.ForeignKey(Manufacturer)
# ...
class Car(models.Model):
company_that_makes_it = models.ForeignKey(Manufacturer)
# ...
См.также
ForeignKey принимает дополнительные аргументы, смотрите справку по полям модели. Эти аргументы определяют как работает связь, все они не обязательны.
Пример работы с обратно-связанными объектами смотрите в в соответствующем разделе.
class Topping(models.Model):
# ...
class Pizza(models.Model):
# ...
toppings = models.ManyToManyField(Topping)
См.также
class Person(models.Model):
name = models.CharField(max_length=128)
def __unicode__(self):
return self.name
class Group(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField(Person, through='Membership')
def __unicode__(self):
return self.name
class Membership(models.Model):
person = models.ForeignKey(Person)
group = models.ForeignKey(Group)
date_joined = models.DateField()
invite_reason = models.CharField(max_length=64)
>>> 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()
[<Person: Ringo Starr>]
>>> ringo.group_set.all()
[<Group: The Beatles>]
>>> m2 = Membership.objects.create(person=paul, group=beatles,
... date_joined=date(1960, 8, 1),
... invite_reason= "Wanted to form a band.")
>>> beatles.members.all()
[<Person: Ringo Starr>, <Person: Paul McCartney>]
# THIS WILL NOT WORK
>>> beatles.members.add(john)
# NEITHER WILL THIS
>>> beatles.members.create(name="George Harrison")
# AND NEITHER WILL THIS
>>> beatles.members = [john, paul, ringo, george]
# Beatles have broken up
>>> beatles.members.clear()
# Find all the groups with a member whose name starts with 'Paul'
>>> Group.objects.filter(members__name__startswith='Paul')
[<Group: The Beatles>]
# 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))
[<Person: Ringo Starr]
>>> ringos_membership = Membership.objects.get(group=beatles, person=ringo)
>>> ringos_membership.date_joined
datetime.date(1962, 8, 16)
>>> ringos_membership.invite_reason
u'Needed a new drummer.'
>>> ringos_membership = ringo.membership_set.get(group=beatles)
>>> ringos_membership.date_joined
datetime.date(1962, 8, 16)
>>> ringos_membership.invite_reason
u'Needed a new drummer.'
См.также
from geography.models import ZipCode
class Restaurant(models.Model):
# ...
zip_code = models.ForeignKey(ZipCode)
Название поля не может быть слово зарезервированное Python, т.к. это приведет к синтаксической ошибке. Например:
class Example(models.Model):
pass = models.IntegerField() # 'pass' is a reserved word!
Название поля не может содержать несколько нижних подчеркиваний(_) подряд, т.к. такой подход Django использует для формирования запросов. Например:
class Example(models.Model):
foo__bar = models.IntegerField() # 'foo__bar' has two underscores!
class Ox(models.Model):
horn_length = models.IntegerField()
class Meta:
ordering = ["horn_length"]
verbose_name_plural = "oxen"
from django.contrib.localflavor.us.models import USStateField
class Person(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
birth_date = models.DateField()
address = models.CharField(max_length=100)
city = models.CharField(max_length=50)
state = USStateField() # Yes, this is America-centric...
def baby_boomer_status(self):
"Returns the person's baby-boomer status."
import datetime
if datetime.date(1945, 8, 1) <= self.birth_date <= datetime.date(1964, 12, 31):
return "Baby boomer"
if self.birth_date < datetime.date(1945, 8, 1):
return "Pre-boomer"
return "Post-boomer"
def is_midwestern(self):
"Returns True if this person is from the Midwest."
return self.state in ('IL', 'WI', 'MI', 'IN', 'OH', 'IA', 'MO')
def _get_full_name(self):
"Returns the person's full name."
return '%s %s' % (self.first_name, self.last_name)
full_name = property(_get_full_name)
“Волшебный метод” Python, который возвращает unicode “представление” объекта. Это то, что Python и Django используют для отображения объекта как строки, обычно в консоли, интерфейсе администратора или шаблоне.
Желательно определить этот метод, т.к. значение по-умолчанию не слишком привлекательно.
Этот метод указывает Django какой URL использовать для объекта. Django использует его в интерфейсе администратора и каждый раз, когда необходимо получить URL для объекта.
Каждый объект, который имеет уникальный URL должен иметь метод метод.
class Blog(models.Model):
name = models.CharField(max_length=100)
tagline = models.TextField()
def save(self, *args, **kwargs):
do_something()
super(Blog, self).save(*args, **kwargs) # Call the "real" save() method.
do_something_else()
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(Blog, self).save(*args, **kwargs) # Call the "real" save() method.
Overriding Delete
Учтите что метод delete() не вызывается при удалении объектов через QuerySet. Для гарантированного выполнения действий после удаления объекта используйте сигналы pre_delete и/или post_delete.
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)
class CommonInfo(models.Model):
...
class Meta:
abstract = True
ordering = ['name']
class Student(CommonInfo):
...
class Meta(CommonInfo.Meta):
db_table = 'student_info'
class Place(models.Model):
name = models.CharField(max_length=50)
address = models.CharField(max_length=80)
class Restaurant(Place):
serves_hot_dogs = models.BooleanField()
serves_pizza = models.BooleanField()
>>> Place.objects.filter(name="Bob's Cafe")
>>> Restaurant.objects.filter(name="Bob's Cafe")
>>> p = Place.objects.get(id=12)
# If p is a Restaurant object, this will give the child class:
>>> p.restaurant
<Restaurant: ...>
class ChildModel(ParentModel):
...
class Meta:
# Remove parent's ordering effect
ordering = []
class Supplier(Place):
# Must specify related_name on all relations.
customers = models.ManyToManyField(Restaurant, related_name='provider')
from django.contrib.auth.models import User
class MyUser(User):
class Meta:
proxy = True
def do_something(self):
...
>>> u = User.objects.create(username="foobar")
>>> MyUser.objects.get(username="foobar")
<MyUser: foobar>
class OrderedUser(User):
class Meta:
ordering = ["username"]
proxy = True
class NewManager(models.Manager):
...
class MyUser(User):
objects = NewManager()
class Meta:
proxy = True
# Create an abstract class for the new manager.
class ExtraManagers(models.Model):
secondary = NewManager()
class Meta:
abstract = True
class MyUser(User, ExtraManagers):
class Meta:
proxy = True
Aug 21, 2013