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