Models are the only authoritative source of information for your data. It contains the necessary fields and behaviors for the data you store. Generally, each model corresponds to a unique table in the database.
Every model is
django.db.models.ModelA python subclass of.
Each attribute of the model represents a field in the database.
Django provides a set of automatically generated API for database access; See_ Execute query_。
A short example
This example defines a
PersonModel, it has
last_nameThere are two attributes
from django.db import models class Person(models.Model): first_name = models.CharField(max_length=30) last_name = models.CharField(max_length=30)
last_nameIt’s two parts of the modelfield. Each field is designated as a class property, and each property is mapped to a database column.
PersonThe model creates such a table in the database:
CREATE TABLE myapp_person ( "id" serial NOT NULL PRIMARY KEY, "first_name" varchar(30) NOT NULL, "last_name" varchar(30) NOT NULL );
Some technical considerations:
The name of this table
myapp_person, is automatically generated according to the metadata in the model, and can also be overridden as other names. See_Table names_。
idFields are added automatically, but this behavior can be overridden. See_ Auto increment primary key field_。
In this case
CREATE TABLESQL statements use PostgreSQL syntax format, it should be noted that Django will_ Setup file_To use the corresponding SQL statement.
After defining the model, you need to tell Django_ Use_ These models. All you have to do is modify the
INSTALLED_APPS Settings, adding
models.pyThe name of the app.
INSTALLED_APPS = ( #... 'myapp', #... )
When you are
INSTALLED_APPSWhen you add a new application name to, make sure you run the command
manage.py migrate, which can be used first
manage.py makemigrationsTo generate migration scripts for them.
The most important and indispensable part of the model is the field set, which is a list of database fields. Field is specified as a class property. Note that the selected field name should not be the same as the field name_ Model API_Conflicts, such as
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) name = models.CharField(max_length=100) release_date = models.DateField() num_stars = models.IntegerField()
Each field in the model is
FieldAn instance of a subclass. Django determines the following information based on the type of field class:
Column types in the database (for example,
The default HTML to use when rendering forms_ Components_(for example,
Minimal validation requirements, which are used in Django administration sites and automatically generated forms.
Django has dozens of built-in field types; A complete list of field types can be found in the_ Model field reference_Found in. If the built-in type still can’t meet your requirements, you can freely write the field type that meets your requirements; See_ Write custom model fields_。
There are also some common parameters for all fields. These parameters are in the_ Reference_Here we will briefly introduce some of the most commonly used:
True, Django will use
NULLTo store null values in the database. The default value is
True, this field is not allowed to be filled in. Default to
Note that this is related to
nullIt’s purely database, not database
blankIt’s in the field of data validation. If the
blank=TrueThe validation of the form will allow the field to be null. If the
blank=False, which is required.
An iteratable object (for example, a list or a tuple) consisting of two tuples used to provide options for a field. If options is set, the default form will be a selection box instead of a standard text box, and the options in this selection box are the options in options.
This is an example of the choices list:
YEAR_IN_SCHOOL_CHOICES = ( ('FR', 'Freshman'), ('SO', 'Sophomore'), ('JR', 'Junior'), ('SR', 'Senior'), ('GR', 'Graduate'), )
The first element in each tuple is the value stored in the database; The second element is the content used for display in the management interface or modelchoicefield. In a given model class instance, if you want to get the display value of a choices field, call
get_FOO_displayMethod (here foo is the name of the choices field). For example:
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'
The default value of the field. It can be a value or a callable object. If it is callable, it will be called every time a new object is created.
Additional help content displayed by the form part. Even if the field is not used in the form, it is useful for generating documents.
TrueThen this field is the primary key of the model.
If you don’t specify any of the fields
primary_key=TrueDjango will automatically add one
IntegerFieldFields are used as primary keys, so you don’t need to set any of the fields unless you want to override the default primary key behavior
primary_key=True. See_ Auto increment primary key field_。
The primary key field is read-only. If you change the value of the primary key on an existing object and save it, a new object will be created outside the original object. For example:
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) ['Apple', 'Pear']
If the value is set to
TrueThe value of this data field must be unique in the whole table
Again, these are just a brief introduction to common fields. For details, please refer to the general model field options reference（_common model field option reference_).
Auto increment primary key field
By default, Django adds the following field to each model:
id = models.AutoField(primary_key=True)
This is a self incrementing primary key field.
If you want to specify a custom primary key field, just specify it on a field
primary_key=TrueThat’s it. If Django sees that you explicitly set the
Field.primary_key, will not be added automatically
Only one field can be specified per model
primary_key=True(whether explicitly declared or automatically added).
The readme name of the field
OneToOneFieldIn addition, each field type accepts an optional positional parameter — the field’s readme name. If no readme is given, Django automatically creates a readme based on the field’s property name — replacing the underline of the property name with a space.
In this case, the readme is
"person's first name"：
first_name = models.CharField("person's first name", max_length=30)
In this case, the readme is
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")
verbose_nameDon’t capitalize the first letter of. Django capitalizes automatically when necessary.
Obviously, the power of relational database lies in the correlation between tables. Django provides three most common database relationships: many to one, many to many, and one to one.
Many to one relationship
ForeignKeyA positional parameter is required: the class associated with the model.
For example, a car
CarThere is one
ManufacturerMake a lot of cars, every car
CarThere can only be one
Manufacturer——Use the following definition:
from django.db import models class Manufacturer(models.Model): # ... pass class Car(models.Model): manufacturer = models.ForeignKey(Manufacturer) # ...
It is recommended that you use the lowercase name of the associated model as the
ForeignKeyThe name of the field (for example, above)
manufacturer）。 Of course, you can have another name. For example:
class Car(models.Model): company_that_makes_it = models.ForeignKey(Manufacturer) # ...
ForeignKeyField also takes many other parameters, which are_ Model field reference_There is a detailed introduction. These options help define how relationships should work; They are all optional parameters.
For details of accessing reverse association objects, see_Following relationships backward example_。
For example code, see_ Example of many to one relationship model_)。
Many to many relationship
ManyToManyFieldA positional parameter is required: the class associated with the model.
For example, a
PizzaThere can be many
ToppingIt can be on multiple pizzas, and each
PizzaThere are many kinds of topping as follows:
from django.db import models class Topping(models.Model): # ... pass class Pizza(models.Model): # ... toppings = models.ManyToManyField(Topping)
ForeignKeyYou can also create_ The relation of recursion_(objects and their many to many associations) and_ Association with a model that has not yet defined a relationship_； See_ Model field reference_。
It is recommended that you use the plural form of the name of the associated model as an example
ManyToManyFieldThe name of the
In which model
ManyToManyFieldIt doesn’t matter, just choose one of the two models – don’t set both.
ManyToManyFieldThe instance should be in a form that can be edited. In the example above,
PizzaIn (not in)
ToppingIt’s set inside
ManyToManyFieldField), because it’s more natural to assume that a pizza has multiple toppings than a topping on multiple pizza. In the way above, in the
PizzaUsers will be allowed to select different toppings in the form of.
For a complete example, see_ Example of many to many relationship model_。
Other fields in many to many relationships
When dealing with simple many to many relationships such as pairing with pizza and topping, standard
ManyToManyField That’s it. However, sometimes you may need to relate the data to the relationship between the two models.
For example, there is an app that records the music group to which the musician belongs. We can use one
ManyToManyFieldRepresents the many to many relationship between a group and its members. However, sometimes you may want to know more about the details of the membership, such as when the members joined the group.
In these cases, Django allows you to specify a model to define many to many relationships. You can put other fields in the mediation model. Source model
ManyToManyFieldField will use
throughThe parameters point to the mediation model. For the above Music Group example, the code is as follows:
from django.db import models class Person(models.Model): name = models.CharField(max_length=128) def __str__(self): # __unicode__ on Python 2 return self.name class Group(models.Model): name = models.CharField(max_length=128) members = models.ManyToManyField(Person, through='Membership') def __str__(self): # __unicode__ on Python 2 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)
When setting the mediation model, explicitly specify the foreign key and associate it with the model involved in many to many relationships. This explicit declaration defines how the two models relate.
The mediation model has some limitations:
The mediation model must_ There is and only one_ Foreign key to the source model (in the example above)
Group）, or you have to use
ManyToManyField.through_fieldsExplicitly specify the foreign key that Django should use. If there are more than one foreign key in your model, and
through_fieldsIf not specified, an invalid error will be triggered. There are the same restrictions on the foreign keys of the target model (in the example above)
Two foreign keys to the same model are allowed to exist in the model of many to many association with itself through mediation model, but they will be regarded as two (different) aspects of many to many association. If so_ Over_ Two foreign keys. You must specify them as above
through_fieldsOtherwise, a validation error will be raised.
Changed in Django 1.7:
In Django 1.6 and earlier, the mediation model prohibited more than one foreign key.
Now that you’ve set it up
ManyToManyFieldTo use the mediation model (in this case, the
Membership）Next, you start creating many to many relationships. All you have to do is create an instance of the mediation model:
>>> 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>]
Unlike normal many to many fields, you can_ No_ use
createAnd assignment statements (for example,
beatles.members = [...]）To create a relationship:
# 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]
Why not? That’s because you can’t just create
GroupYou also need to specify the relationship between them
MembershipAll the information needed in the model; And simple
createAnd assignment statements can’t do that. So they cannot be used in many to many relationships that use the mediation model. At this point, the only way is to create an instance of the mediation model.
>>> # Beatles have broken up >>> beatles.members.clear() >>> # Note that this deletes the intermediate model instances >>> Membership.objects.all() 
After you create a many to many relationship by creating an instance of the mediation model, you can execute the query. Like many to many fields, you can directly use the attributes of the associated model to query
# Find all the groups with a member whose name starts with 'Paul' >>> Group.objects.filter(members__name__startswith='Paul') [<Group: The Beatles>]
If you use the mediation model, you can also use the properties of the mediation model to query
# 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]
If you need to access a member’s information, you can get it directly
>>> 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.'
Another way to get the same information is in the
PersonQuery on object_ Many to many inverse relation_：
>>> 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.'
One to one relationship
OneToOneFieldUsed to define a one-to-one relationship. Usage and others
fieldTypes are the same: they are included as class attributes in the model.
When an object wants to extend from another object, the most common way is to add a one-to-one relationship to the primary key of the object.
OneToOneFieldYou want a positional parameter: the class associated with the model.
For example, you want to build a “places” database with some common fields, such as address, phone number, etc. Next, if you want to build a restaurant database based on the place database, you don’t want to copy the existing fields to the place database
RestaurantModel, then you can
OneToOneFieldField, which points to
Place(because restaurant itself is a place; In fact, when dealing with this problem, you should use a typical_ Succession_It implies a one-to-one relationship.
ForeignKeyAgain, you can define_ The relation of recursion_and_ Reference a model that has no defined relationship_. See_ Model field reference_。
stay_ An example of one to one relationship model_There is a complete set of examples in.
In previous versions,
OneToOneFieldThe field automatically becomes the primary key of the model. But now it’s not (but you can still pass it if you want to)
primary_keyParameter to create the primary key field. So there can be more than one in a model
Cross file model
It’s very easy to access the models of other applications. At the top of the file where you define the model, import the relevant model to implement it. Then, you can refer to it wherever you need it. For example:
from django.db import models from geography.models import ZipCode class Restaurant(models.Model): # ... zip_code = models.ForeignKey(ZipCode)
Restrictions on field naming
Django has only two restrictions on field naming:
The name of the field cannot be a python reserved keyword because this will result in a python syntax error. For example:
class Example(models.Model): pass = models.IntegerField() # 'pass' is a reserved word!
Because of the way the Django query syntax works, there cannot be more than one consecutive underline in a field name. For example:
class Example(models.Model): foo__bar = models.IntegerField() # 'foo__bar' has two underscores!
These restrictions are flexible because there is no requirement that the field name must match the column name of the database. ginseng
Reserved words of SQL
select, which can be used as the field name of the model, because Django will escape the database table name and column name in the underlying SQL query statement. It uses different reference syntax based on your database engine.
Custom field type
If the existing model fields are not suitable, or you want to use the advantages of some rare database column types, you can create your own field types. Create your own fields in_ Write custom model fields_There is a complete story in.
class MetaDefine the metadata of the model, for example:
from django.db import models class Ox(models.Model): horn_length = models.IntegerField() class Meta: ordering = ["horn_length"] verbose_name_plural = "oxen"
Model metadata is “any data that is not a field,” such as sorting options（
ordering）, data table name（
db_table）Or human readable singular and plural names（
verbose_name_plural）。 Add to model
class MetaIt is completely optional, and all options are not required.
elementA complete list of options can be found in_ Model options reference_Find it.
Properties of the model
The most important attribute of a model is the
Manager. It’s the interface through which
database query operations are provided to Django models and is used to
_retrieve the instances_ from the database. If no
Manager is defined, the default name is
objects. Managers are only accessible via
model classes, not the model instances.
Methods of modeling
You can define custom methods on the model to add custom “bottom” functions to your objects.
ManagerMethods are used for “table scope” transactions, and model methods should focus on specific model instances.
It’s a very valuable technology to put the business logic in the same place – the model.
For example, the following model has some custom methods:
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" 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)
The last method in this example is a_property_。
_ Model example reference_With a complete_ The method of automatic generation for model_List. You can cover them – see belowMethod of covering model predefined——But there are ways you’ll always want to redefine:
__str__() (Python 3)
Python 3 equivalent of
__unicode__() (Python 2)
A python “magic method” that returns the Unicode “Representation” of an object. Python and Django use this method when model instances need to be cast and displayed as normal strings. The most obvious is when an object is displayed in an interactive console or management site.
Will always want to define this method; The default method makes little sense.
It tells Django how to calculate the URL of an object. Django uses this method in its administration site, as well as in any other case where you need to calculate the URL of an object.
Any object that has a URL that uniquely identifies itself should define this method.
Method of covering predefined models
You are free to override these methods (and any other modeling methods) to change their behavior.
A typical use scenario for overriding the built-in method is that you want to do something else when you save an object. For example (see
save()For the parameters it accepts in the
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(Blog, self).save(*args, **kwargs) # Call the "real" save() method. do_something_else()
You can also prevent saving:
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(Blog, self).save(*args, **kwargs) # Call the "real" save() method.
You have to remember to call the superclass method——
super(Blog, self).save(*args, **kwargs)——To ensure that the object is saved to the database. If you forget to call this method of the superclass, the default behavior will not happen and the database will not change.
Also remember to pass parameters to the model method – that is, the
*args, **kwargs. Django will always extend the function of built-in model method and add new parameters in the future. If used in your method definition
*args, **kwargsWill ensure that your code automatically supports these new parameters.
Overridden model methods are not called on bulk operations
Attention, when_ When using query set to batch delete objects_, will not be called for each object
delete()method. To ensure that the custom delete logic is executed, you can use the
pre_deleteAnd / or
Execute custom SQL
Another common requirement is to write custom SQL statements in model method and module level method. For more details on using the original SQL statement, see_ Use original SQL_Document for.
Model inheritance in Django is almost the same as ordinary class inheritance in Python, but the basic requirements of the model listed in the head of this page should be followed. This means that the custom model class should inherit
The only decision you need to make is whether you want the parent model to have its own database tables, or whether you want the parent model to hold only some common information that can only be seen in the child model.
There are three styles of inheritance in Django.
Usually, you just want to use the parent class to hold some information. You don’t want to type it in every submodel. This class will never be used alone, so you can use it_ Abstract base class_。
If you inherit an existing model and want each model to have its own database table, you should use_ Multi table inheritance_。
Finally, if you just want to change the python level behavior of the module without modifying the fields of the model, you can use the_ Proxy model_。
Abstract base class
Abstract classes are very useful when you want to store some common information in many models. After you write the base class, in the_Meta_Class
abstract=True, the class cannot create any tables. Instead, when it is used as a base class for other models, it will be added to that subclass. If the abstraction base class and its subclass have the same items, then error will appear (and Django will return an exception).
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)
StudentThe model will have three items:
CommonInfoThe model cannot be used like the general Django model because it is an abstract base class. It cannot generate data forms or managers, and cannot be instantiated or stored.
For many users, this type of model inheritance is what you want. It provides a way to extract common information at the python language level, but at the database level, each subclass still creates only one database.
When an abstract class is created, Django will automatically define the_Meta_As an attribute of a subclass. If the subclass does not declare its own_Meta_Class, which will inherit the_Meta_. if the subclass wants to extend the parent Can inherit from the parent class _Meta_ Yes, for example
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'
When inheriting, Django changes the base class_Meta_Class to make an adjustment: in the installation_Meta_Django sets the
abstract=False. This means that subclasses of the abstract base class do not automatically become abstract classes. Of course, you can have an abstract class inherit another abstract base class, but explicitly set it every time
For an abstract base class, some properties are placed in the _Meta_ There is no meaning in embedded classes. For example, include
db_tableWill mean all subclasses (those that do not specify themselves)_Meta_Class) use the same data table. Generally speaking, this is not what we want.
Use with care
If you are
related_nameProperty, you must always specify one for the field_ Only_ The reverse name of the. But doing so on an abstract base class raises a serious problem. Because Django will add base class fields to each subclass, and the field attribute values of each subclass are exactly the same (including
When you use in (and only in) abstract base classes
related_nameIf you want to bypass this problem, you need to include
'%(class)s'Will be replaced with the lowercase underlined name of the subclass, and the field will be used in the subclass.
'%(app_label)s'Will be replaced with the lowercase underlined name of the application, which contains subclasses. The name of each installed application should be unique, and the name of each model class in the application should also be unique, so the generated names should be different from each other.
For example, suppose you have an app called
from django.db import models class Base(models.Model): m2m = models.ManyToManyField(OtherModel, related_name="%(app_label)s_%(class)s_related") class Meta: abstract = True class ChildA(Base): pass class ChildB(Base): pass
And another application
from common.models import Base class ChildB(Base): pass
The reverse name of the childa.m2m field is childa_ The reverse name of the childb.m2m field is childb_ related。 It depends on how you use it
'%(app_label)sTo construct your reverse name. If you don’t, Django will be verifying the model (or running it)
migrate）An error is thrown when the.
If you don’t define an associated field in the abstract base class
related_name Property, then the default reverse name is the subclass name plus
'_set'Whether it works depends on whether you define a field with the same name in a subclass. For example, in the above code, if you remove
ChildAIn the middle,
m2mThe reverse name of the field is
ChildBThe reverse name of the M2M field of is
Multi table inheritance
This is the second inheritance supported by Django. When using this inheritance method, each sub model in the same level is a complete model in the true sense. Each submodel has its own data table, which can be queried and created. Inheritance adds a link (through an automatically created
OneToOneFieldTo achieve). For example:
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)
PlaceAll the fields in it are in the
RestaurantIs also valid, but the data is saved in another data table. So the following two statements can be run:
>>> Place.objects.filter(name="Bob's Cafe") >>> Restaurant.objects.filter(name="Bob's Cafe")
If you have one
Place ， So it’s also a
RestaurantThen you can use the lowercase form of submodel from pl
>>> p = Place.objects.get(id=12) # If p is a Restaurant object, this will give the child class: >>> p.restaurant <Restaurant: ...>
However, if the
Restaurant ( For example, it’s just
PlaceObject, or it is the parent of another class)
p.restaurantIt will be thrown out
On multi table inheritance
In multi table inheritance, the subclass inherits the_Meta_Classes are meaningless. be-all_Meta_ Option is already working on the parent class, and it’s only counterproductive to use it again（ This is the opposite of using an abstract base class, because the abstract base class does not have its own content.)
So a child model does not have access to the_Meta_ Class. However, in some limited cases, a subclass can inherit some meta from its parent class: if the subclass does not specify
get_latest_byProperties, it inherits them from the parent class.
If the parent class has sort settings and you don’t want the child class to have any sort settings, you can explicitly disable sort
class ChildModel(ParentModel): # ... class Meta: # Remove parent's ordering effect ordering = 
Inheritance and reverse association
Because multi table inheritance uses an implicit
OneToOneFieldTo link a subclass to a parent, so as in the example above, you can use a parent to refer to a subclass. But this one to one field field is the default
ManyToManyField The default reverse name is the same. If you do a many to one or many to many relationship with other subclasses of model, you canmustForce assignments on each many to one and many to many fields
related_name. If you don’t, Django will run validation on you An exception is thrown when.
class Supplier(Place): customers = models.ManyToManyField(Place)
This results in an error:
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'.
Like the following, to
related_nameYou can fix this error:
Specifies the field of the linked parent class
As we mentioned earlier, Django will automatically create one
OneToOneFieldField links the subclass to a non Abstract parent model. If you want to specify the property name of the link parent class, you can create your own
OneToOneFieldField and set
parent_link=TrueTo use this field to link the parent class.
use _ Multi table inheritance_Each subclass of the model creates a new data table, which is usually exactly what we want to do. This is because subclasses need a space to store field data that is not included in the base class. But sometimes, you may just want to change the behavior of the model in the python layer. For example, change the default manager or add a new method.
And that’s what the proxy model inheritance method does: create one for the original model_ Agency_ 。 You can create, delete, and update instances of the proxy model, and all data can be saved as if you were using the original model. The difference is that you can change the default sort settings and the default manager in the proxy model without affecting the original model.
Declaring a proxy model is no different from declaring a normal model. set up
proxy The value of is
TrueTo complete the declaration of the proxy model.
For example, suppose you want to give Django its own standard
PersonModel adds a method. You can do this:
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
MyPersonClass and its parent class
Person Operate on the same data table. In particular,
Person Any instance of the
MyPersonVisit, and vice versa:
>>> p = Person.objects.create(first_name="foobar") >>> MyPerson.objects.get(first_name="foobar") <MyPerson: foobar>
You can also use the proxy model to define different default sorting settings for the model. You may not want to give it every time
PersonModels are sorted, but agents are always used according to the
last_nameProperty sorting. It’s very easy:
class OrderedPerson(Person): class Meta: ordering = ["last_name"] proxy = True
PersonThe query is unordered, and
OrderedPersonThe inquiry will be made according to the
The query set always returns the requested model
That is to say, there is no way for Django to query
PersonObject’s query set returns objects of the same type. The point of proxy objects is that they rely on native objects
PersonObject’s code still uses it, and you can use the extension object you added (it doesn’t rely on any other code). It’s not going to be
PersonModels (or other) are replaced everywhere with other models that you create yourself.
Restrictions on base classes
The proxy model must inherit from a non abstract base class. You cannot inherit from multiple non abstract base classes because a proxy model cannot connect to different tables. A proxy model can also inherit any number of abstract base classes, but only if they do_ No_ Define any model field.
Manager of agent model
If you do not define any managers in the proxy model, the proxy model inherits the managers from the parent class 。 If you define a manager in the agent model, it becomes the default manager ， However, the manager defined in the parent class is still valid.
Continue with the above example when you query
PersonWhen modeling, you can change the default manager, for example:
from django.db import models class NewManager(models.Manager): # ... pass class MyPerson(Person): objects = NewManager() class Meta: proxy = True
If you want to add a new manager to the agent instead of replacing the existing default manager, you can use the_ Custom manager_Create a base class with a new manager and inherit it after the main base class
# 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
You may not need to do this often, but it works.
Differences between proxy model and unmanaged model
Inheritance and use of proxy model
managed The unmanaged model of the property is very similar. But the two are not the same, you should consider which option.
One difference is that you can
Meta.managed=FalseIn fact, it must be specified unless you really want to get an empty model. Be careful when creating unmanaged models
Meta.db_tableThis is because the unmanaged model created maps to an existing model and has its own method. Therefore, if you want to keep the two models synchronized and make changes to the program, it will become cumbersome and fragile.
Another difference is that they handle the manager differently. The behavior of the proxy model should be similar to that of the model it represents, so the proxy model should inherit the managers of the parent model, including its default manager. However, in common multi table inheritance, the subclass cannot inherit the manager of the parent class, because the manager of the parent class may not be applicable when dealing with non base class fields. In the latter case_ Manager document_There is a detailed introduction.
After we implemented these two features, we tried to combine them. The results show that the combination of macro inheritance and micro manager not only makes API complex and difficult to use, but also difficult to understand. As these two options may be needed in any situation, they are still used independently at present.
Therefore, the general rule is:
If you want to learn from an existing model or data table, and do not want to involve all the columns of the original data table, then let
Meta.managed=False. This option is usually used when creating models or tables for database views that do not need to be controlled by Django.
If you want to make Python level changes to the model and keep the fields unchanged, you can
Meta.proxy=True. Therefore, when the data is saved, the proxy model is equivalent to completely copying the storage structure of the original model.
Like Python subclasses, Django’s model can be inherited from multiple parent models. Remember that the general Python name resolution rules also apply. The first base class with a specific name (such as_Meta_）It’s the one used. For example, this means that if multiple parent classes contain _Meta_Class, only the first one will be used, and the rest will be ignored.
In general, you don’t need to inherit multiple parent classes. Multiple inheritance is mainly useful for “mix in” classes: add a specific, extra field or method to each class that inherits mix in. You should try to keep your inheritance relationship as concise and direct as possible, so that you don’t have to work hard to figure out where a particular piece of information comes from.
Changed in Django 1.7\.
Before Django 1.7, inheriting multiple
idThe model of primary key field will not throw an exception, but it will cause data loss. For example, consider these models (due to
idFields, they are no longer valid:
class Article(models.Model): headline = models.CharField(max_length=50) body = models.TextField() class Book(models.Model): title = models.CharField(max_length=50) class BookReview(Book, Article): pass
This code shows how to create an object of a subclass and override the value in the parent object that was created earlier.
>>> article = Article.objects.create(headline='Some piece of news.') >>> review = BookReview.objects.create( ... headline='Review of Little Red Riding Hood.', ... title='Little Red Riding Hood') >>> >>> assert Article.objects.get(pk=article.pk).headline == article.headline Traceback (most recent call last): File "<console>", line 1, in <module> AssertionError >>> # the "Some piece of news." headline has been overwritten. >>> Article.objects.get(pk=article.pk).headline 'Review of Little Red Riding Hood.'
You can use explicit
AutoFieldTo use multiple inheritance properly:
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
Or use a common ancestor to hold
class Piece(models.Model): pass class Article(Piece): ... class Book(Piece): ... class BookReview(Book, Article): pass
Field name “hiding” is not permitted
Ordinary Python class inheritance allows subclasses to override any property of the parent class. But in Django, rewriting
FieldInstances are not allowed (at least not yet). If there is one in the base class
authorField, you can’t create any subclass named
Rewriting the fields of the parent class will cause a lot of trouble, such as initializing the instance (specified in the
Model.__init__And serialization. Ordinary Python class inheritance mechanism can’t handle these features well. So Django’s inheritance mechanism is designed to be different from python, which is not arbitrary.
These restrictions are only for those used as attributes
FieldInstance, not for Python properties, which can still be overridden. In Python’s view, the above restriction is only for the name of the field instance: if you manually specify the column name of the database, then in multiple inheritance, you can use the same column name in a subclass and an ancestor class（ Because they use fields from two different data tables).
If you override a model field in any ancestor class, Django will throw it
Covers all the model related APIs including model fields, related
This paper is based onCC BY-NC-SA 3.0Please keep the author’s signature and the source of the article.
Django document collaborative translation teamWe are short of staff. Interested friends can join us. It is totally public welfare. Communication group: 467338606.