mirror of
				https://github.com/django/django.git
				synced 2025-10-26 23:26:08 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			178 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			178 lines
		
	
	
		
			4.0 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 Supplier(Place):
 | |
|     customers = models.ManyToManyField(Restaurant, related_name='provider')
 | |
| 
 | |
| 
 | |
| 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
 |