mirror of
				https://github.com/django/django.git
				synced 2025-10-25 06:36:07 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			215 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			215 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| """
 | |
| XX. Model inheritance
 | |
| 
 | |
| Model inheritance exists in two varieties:
 | |
|     - abstract base classes which are a way of specifying common
 | |
|       information inherited by the subclasses. They don't exist as a separate
 | |
|       model.
 | |
|     - non-abstract base classes (the default), which are models in their own
 | |
|       right with their own database tables and everything. Their subclasses
 | |
|       have references back to them, created automatically.
 | |
| 
 | |
| Both styles are demonstrated here.
 | |
| """
 | |
| from django.db import models
 | |
| 
 | |
| #
 | |
| # Abstract base classes
 | |
| #
 | |
| 
 | |
| 
 | |
| class CommonInfo(models.Model):
 | |
|     name = models.CharField(max_length=50)
 | |
|     age = models.PositiveIntegerField()
 | |
| 
 | |
|     class Meta:
 | |
|         abstract = True
 | |
|         ordering = ["name"]
 | |
| 
 | |
|     def __str__(self):
 | |
|         return "%s %s" % (self.__class__.__name__, self.name)
 | |
| 
 | |
| 
 | |
| class Worker(CommonInfo):
 | |
|     job = models.CharField(max_length=50)
 | |
| 
 | |
| 
 | |
| class Student(CommonInfo):
 | |
|     school_class = models.CharField(max_length=10)
 | |
| 
 | |
|     class Meta:
 | |
|         pass
 | |
| 
 | |
| 
 | |
| #
 | |
| # Abstract base classes with related models
 | |
| #
 | |
| 
 | |
| 
 | |
| class Post(models.Model):
 | |
|     title = models.CharField(max_length=50)
 | |
| 
 | |
| 
 | |
| class Attachment(models.Model):
 | |
|     post = models.ForeignKey(
 | |
|         Post,
 | |
|         models.CASCADE,
 | |
|         related_name="attached_%(class)s_set",
 | |
|         related_query_name="attached_%(app_label)s_%(class)ss",
 | |
|     )
 | |
|     content = models.TextField()
 | |
| 
 | |
|     class Meta:
 | |
|         abstract = True
 | |
| 
 | |
| 
 | |
| class Comment(Attachment):
 | |
|     is_spam = models.BooleanField(default=False)
 | |
| 
 | |
| 
 | |
| class Link(Attachment):
 | |
|     url = models.URLField()
 | |
| 
 | |
| 
 | |
| #
 | |
| # Multi-table inheritance
 | |
| #
 | |
| 
 | |
| 
 | |
| class Chef(models.Model):
 | |
|     name = models.CharField(max_length=50)
 | |
| 
 | |
| 
 | |
| class Place(models.Model):
 | |
|     name = models.CharField(max_length=50)
 | |
|     address = models.CharField(max_length=80)
 | |
| 
 | |
| 
 | |
| class Rating(models.Model):
 | |
|     rating = models.IntegerField(null=True, blank=True)
 | |
| 
 | |
|     class Meta:
 | |
|         abstract = True
 | |
|         ordering = ["-rating"]
 | |
| 
 | |
| 
 | |
| class Restaurant(Place, Rating):
 | |
|     serves_hot_dogs = models.BooleanField(default=False)
 | |
|     serves_pizza = models.BooleanField(default=False)
 | |
|     chef = models.ForeignKey(Chef, models.SET_NULL, null=True, blank=True)
 | |
| 
 | |
|     class Meta(Rating.Meta):
 | |
|         db_table = "my_restaurant"
 | |
| 
 | |
| 
 | |
| class ItalianRestaurant(Restaurant):
 | |
|     serves_gnocchi = models.BooleanField(default=False)
 | |
| 
 | |
| 
 | |
| class ItalianRestaurantCommonParent(ItalianRestaurant, Place):
 | |
|     place_ptr_two = models.OneToOneField(
 | |
|         Place, on_delete=models.CASCADE, parent_link=True
 | |
|     )
 | |
| 
 | |
| 
 | |
| class Supplier(Place):
 | |
|     customers = models.ManyToManyField(Restaurant, related_name="provider")
 | |
| 
 | |
| 
 | |
| class CustomSupplier(Supplier):
 | |
|     pass
 | |
| 
 | |
| 
 | |
| class ParkingLot(Place):
 | |
|     # An explicit link to the parent (we can control the attribute name).
 | |
|     parent = models.OneToOneField(
 | |
|         Place, models.CASCADE, primary_key=True, parent_link=True
 | |
|     )
 | |
|     main_site = models.ForeignKey(Place, models.CASCADE, related_name="lot")
 | |
| 
 | |
| 
 | |
| #
 | |
| # Abstract base classes with related models where the sub-class has the
 | |
| # same name in a different app and inherits from the same abstract base
 | |
| # class.
 | |
| # NOTE: The actual API tests for the following classes are in
 | |
| #       model_inheritance_same_model_name/models.py - They are defined
 | |
| #       here in order to have the name conflict between apps
 | |
| #
 | |
| 
 | |
| 
 | |
| class Title(models.Model):
 | |
|     title = models.CharField(max_length=50)
 | |
| 
 | |
| 
 | |
| class NamedURL(models.Model):
 | |
|     title = models.ForeignKey(
 | |
|         Title, models.CASCADE, related_name="attached_%(app_label)s_%(class)s_set"
 | |
|     )
 | |
|     url = models.URLField()
 | |
| 
 | |
|     class Meta:
 | |
|         abstract = True
 | |
| 
 | |
| 
 | |
| class Mixin:
 | |
|     def __init__(self):
 | |
|         self.other_attr = 1
 | |
|         super().__init__()
 | |
| 
 | |
| 
 | |
| class MixinModel(models.Model, Mixin):
 | |
|     pass
 | |
| 
 | |
| 
 | |
| class Base(models.Model):
 | |
|     titles = models.ManyToManyField(Title)
 | |
| 
 | |
| 
 | |
| class SubBase(Base):
 | |
|     sub_id = models.IntegerField(primary_key=True)
 | |
| 
 | |
| 
 | |
| class GrandParent(models.Model):
 | |
|     first_name = models.CharField(max_length=80)
 | |
|     last_name = models.CharField(max_length=80)
 | |
|     email = models.EmailField(unique=True)
 | |
|     place = models.ForeignKey(Place, models.CASCADE, null=True, related_name="+")
 | |
| 
 | |
|     class Meta:
 | |
|         # Ordering used by test_inherited_ordering_pk_desc.
 | |
|         ordering = ["-pk"]
 | |
|         unique_together = ("first_name", "last_name")
 | |
| 
 | |
| 
 | |
| class Parent(GrandParent):
 | |
|     pass
 | |
| 
 | |
| 
 | |
| class Child(Parent):
 | |
|     pass
 | |
| 
 | |
| 
 | |
| class GrandChild(Child):
 | |
|     pass
 | |
| 
 | |
| 
 | |
| class CommonAncestor(models.Model):
 | |
|     id = models.IntegerField(primary_key=True, default=1)
 | |
| 
 | |
| 
 | |
| class FirstParent(CommonAncestor):
 | |
|     first_ancestor = models.OneToOneField(
 | |
|         CommonAncestor, models.CASCADE, primary_key=True, parent_link=True
 | |
|     )
 | |
| 
 | |
| 
 | |
| class SecondParent(CommonAncestor):
 | |
|     second_ancestor = models.OneToOneField(
 | |
|         CommonAncestor, models.CASCADE, primary_key=True, parent_link=True
 | |
|     )
 | |
| 
 | |
| 
 | |
| class CommonChild(FirstParent, SecondParent):
 | |
|     pass
 |