1# -*- coding: UTF-8 -*- 2 3from django.db import models 4from django.contrib.auth.models import User as UserAlias 5 6from south.modelsinspector import add_introspection_rules 7 8on_delete_is_available = hasattr(models, "PROTECT") # models here is django.db.models 9 10def default_func(): 11 return "yays" 12 13# An empty case. 14class Other1(models.Model): pass 15 16# Another one 17class Other3(models.Model): pass 18def get_sentinel_object(): 19 """ 20 A function to return the object to be used in place of any deleted object, 21 when using the SET option for on_delete. 22 """ 23 # Create a new one, so we always have an instance to test with. Can't work! 24 return Other3() 25 26# Nastiness. 27class HorribleModel(models.Model): 28 "A model to test the edge cases of model parsing" 29 30 ZERO, ONE = 0, 1 31 32 # First, some nice fields 33 name = models.CharField(max_length=255) 34 short_name = models.CharField(max_length=50) 35 slug = models.SlugField(unique=True) 36 37 # A ForeignKey, to a model above, and then below 38 o1 = models.ForeignKey(Other1) 39 o2 = models.ForeignKey('Other2') 40 41 if on_delete_is_available: 42 o_set_null_on_delete = models.ForeignKey('Other3', null=True, on_delete=models.SET_NULL) 43 o_cascade_delete = models.ForeignKey('Other3', null=True, on_delete=models.CASCADE, related_name="cascademe") 44 o_protect = models.ForeignKey('Other3', null=True, on_delete=models.PROTECT, related_name="dontcascademe") 45 o_default_on_delete = models.ForeignKey('Other3', null=True, default=1, on_delete=models.SET_DEFAULT, related_name="setmedefault") 46 o_set_on_delete_function = models.ForeignKey('Other3', null=True, default=1, on_delete=models.SET(get_sentinel_object), related_name="setsentinel") 47 o_set_on_delete_value = models.ForeignKey('Other3', null=True, default=1, on_delete=models.SET(get_sentinel_object()), related_name="setsentinelwithactualvalue") # dubious case 48 o_no_action_on_delete = models.ForeignKey('Other3', null=True, default=1, on_delete=models.DO_NOTHING, related_name="deletemeatyourperil") 49 50 51 # Now to something outside 52 user = models.ForeignKey(UserAlias, related_name="horribles") 53 54 # Unicode! 55 code = models.CharField(max_length=25, default="↑↑↓↓←→←→BA") 56 57 # Odd defaults! 58 class_attr = models.IntegerField(default=ZERO) 59 func = models.CharField(max_length=25, default=default_func) 60 61 # Time to get nasty. Define a non-field choices, and use it 62 choices = [('hello', '1'), ('world', '2')] 63 choiced = models.CharField(max_length=20, choices=choices) 64 65 class Meta: 66 db_table = "my_fave" 67 verbose_name = "Dr. Strangelove," + \ 68 """or how I learned to stop worrying 69and love the bomb""" 70 71 # Now spread over multiple lines 72 multiline = \ 73 models.TextField( 74 ) 75 76# Special case. 77class Other2(models.Model): 78 # Try loading a field without a newline after it (inspect hates this) 79 close_but_no_cigar = models.PositiveIntegerField(primary_key=True) 80 81class CustomField(models.IntegerField): 82 def __init__(self, an_other_model, **kwargs): 83 super(CustomField, self).__init__(**kwargs) 84 self.an_other_model = an_other_model 85 86add_introspection_rules([ 87 ( 88 [CustomField], 89 [], 90 {'an_other_model': ('an_other_model', {})}, 91 ), 92], ['^south\.tests\.fakeapp\.models\.CustomField']) 93 94class BaseModel(models.Model): 95 pass 96 97class SubModel(BaseModel): 98 others = models.ManyToManyField(Other1) 99 custom = CustomField(Other2) 100 101class CircularA(models.Model): 102 c = models.ForeignKey('CircularC') 103 104class CircularB(models.Model): 105 a = models.ForeignKey(CircularA) 106 107class CircularC(models.Model): 108 b = models.ForeignKey(CircularB) 109 110class Recursive(models.Model): 111 self = models.ForeignKey('self') 112