Arthur de Jong

Open Source / Free Software developer

summaryrefslogtreecommitdiffstats
path: root/tests/generic_relations/models.py
blob: 7522f5b4cd89905d277cffffe3b19be76cd7f8cf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
"""
Generic relations

Generic relations let an object have a foreign key to any object through a
content-type/object-id field. A ``GenericForeignKey`` field can point to any
object, be it animal, vegetable, or mineral.

The canonical example is tags (although this example implementation is *far*
from complete).
"""

from __future__ import unicode_literals

from django.contrib.contenttypes.fields import (
    GenericForeignKey, GenericRelation,
)
from django.contrib.contenttypes.models import ContentType
from django.db import models
from django.utils.encoding import python_2_unicode_compatible


@python_2_unicode_compatible
class TaggedItem(models.Model):
    """A tag on an item."""
    tag = models.SlugField()
    content_type = models.ForeignKey(ContentType, models.CASCADE)
    object_id = models.PositiveIntegerField()

    content_object = GenericForeignKey()

    class Meta:
        ordering = ["tag", "content_type__model"]

    def __str__(self):
        return self.tag


class ValuableTaggedItem(TaggedItem):
    value = models.PositiveIntegerField()


class AbstractComparison(models.Model):
    comparative = models.CharField(max_length=50)

    content_type1 = models.ForeignKey(ContentType, models.CASCADE, related_name="comparative1_set")
    object_id1 = models.PositiveIntegerField()

    first_obj = GenericForeignKey(ct_field="content_type1", fk_field="object_id1")


@python_2_unicode_compatible
class Comparison(AbstractComparison):
    """
    A model that tests having multiple GenericForeignKeys. One is defined
    through an inherited abstract model and one defined directly on this class.
    """
    content_type2 = models.ForeignKey(ContentType, models.CASCADE, related_name="comparative2_set")
    object_id2 = models.PositiveIntegerField()

    other_obj = GenericForeignKey(ct_field="content_type2", fk_field="object_id2")

    def __str__(self):
        return "%s is %s than %s" % (self.first_obj, self.comparative, self.other_obj)


@python_2_unicode_compatible
class Animal(models.Model):
    common_name = models.CharField(max_length=150)
    latin_name = models.CharField(max_length=150)

    tags = GenericRelation(TaggedItem, related_query_name='animal')
    comparisons = GenericRelation(Comparison,
                                  object_id_field="object_id1",
                                  content_type_field="content_type1")

    def __str__(self):
        return self.common_name


@python_2_unicode_compatible
class Vegetable(models.Model):
    name = models.CharField(max_length=150)
    is_yucky = models.BooleanField(default=True)

    tags = GenericRelation(TaggedItem)

    def __str__(self):
        return self.name


class Carrot(Vegetable):
    pass


@python_2_unicode_compatible
class Mineral(models.Model):
    name = models.CharField(max_length=150)
    hardness = models.PositiveSmallIntegerField()

    # note the lack of an explicit GenericRelation here...

    def __str__(self):
        return self.name


class GeckoManager(models.Manager):
    def get_queryset(self):
        return super(GeckoManager, self).get_queryset().filter(has_tail=True)


class Gecko(models.Model):
    has_tail = models.BooleanField(default=False)
    objects = GeckoManager()


# To test fix for #11263
class Rock(Mineral):
    tags = GenericRelation(TaggedItem)


class ValuableRock(Mineral):
    tags = GenericRelation(ValuableTaggedItem)


class ManualPK(models.Model):
    id = models.IntegerField(primary_key=True)
    tags = GenericRelation(TaggedItem, related_query_name='manualpk')


class ForProxyModelModel(models.Model):
    content_type = models.ForeignKey(ContentType, models.CASCADE)
    object_id = models.PositiveIntegerField()
    obj = GenericForeignKey(for_concrete_model=False)
    title = models.CharField(max_length=255, null=True)


class ForConcreteModelModel(models.Model):
    content_type = models.ForeignKey(ContentType, models.CASCADE)
    object_id = models.PositiveIntegerField()
    obj = GenericForeignKey()


class ConcreteRelatedModel(models.Model):
    bases = GenericRelation(ForProxyModelModel, for_concrete_model=False)


class ProxyRelatedModel(ConcreteRelatedModel):
    class Meta:
        proxy = True


# To test fix for #7551
class AllowsNullGFK(models.Model):
    content_type = models.ForeignKey(ContentType, models.SET_NULL, null=True)
    object_id = models.PositiveIntegerField(null=True)
    content_object = GenericForeignKey()