-
-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathmanagers.py
More file actions
150 lines (109 loc) · 4.43 KB
/
managers.py
File metadata and controls
150 lines (109 loc) · 4.43 KB
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
from django.apps import apps
from django.contrib.contenttypes.models import ContentType
from django.db import models
def _get_content_type_and_obj(obj, model=None):
if isinstance(model, str):
model = apps.get_model(*model.split("."))
if isinstance(obj, int):
obj = model.objects.get(pk=obj)
return ContentType.objects.get_for_model(type(obj)), obj
class FavoriteManager(models.Manager):
"""
A Manager for Favorite objects
"""
from django import VERSION
if VERSION > (1, 8):
def get_query_set(self):
return self.get_queryset()
def for_user(self, user, model=None):
"""
Returns a Favorite objects queryset for a given user.
If a model params is provided, it returns only the
favorited objects of that model class
Usage:
Favorite.objects.for_user(user)
Favorite.objects.for_user(user, model=Song)
Favorite.objects.for_user(user, model="music.song")
"""
qs = self.get_query_set().filter(user=user)
if model:
if isinstance(model, str):
model = apps.get_model(*model.split("."))
content_type = ContentType.objects.get_for_model(model)
qs = qs.filter(target_content_type=content_type)
return qs.order_by("-timestamp")
def for_model(self, model):
"""
Returns a Favorite objects queryset for a given model.
`model` may be a django model class or an string representing
a model in module-notation, ie: "auth.User"
Usage:
Favorite.objects.for_model(Song)
Favorite.objects.for_model("music.Song")
"""
# if model is an app_label.model string make it a Model class
if isinstance(model, str):
model = apps.get_model(*model.split("."))
content_type = ContentType.objects.get_for_model(model)
qs = self.get_query_set().filter(target_content_type=content_type)
return qs.order_by("-timestamp")
def for_object(self, obj, model=None):
"""
Returns a Favorite objects queryset for a given object
Usage:
Favorite.objects.for_object(1, "music.Song")
Favorite.objects.for_object(1, Song)
or given a music app with a Song model:
song = Song.objects.get(pk=1)
Favorite.objects.for_object(song)
"""
content_type, obj = _get_content_type_and_obj(obj, model)
qs = self.get_query_set().filter(target_content_type=content_type, target_object_id=obj.pk)
return qs.order_by("-timestamp")
def get_favorite(self, user, obj, model=None):
"""
Returns a Favorite instance if the `user` has favorited
the given object `obj`. Otherwise returns None
Usage:
Favorite.objects.get_favorite(user, 1, "music.Song")
Favorite.objects.get_favorite(user, 1, Song)
or given a music app with a Song model:
song = Song.objects.get(pk=1)
Favorite.objects.get_favorite(user, song)
"""
try:
content_type, obj = _get_content_type_and_obj(obj, model)
except AttributeError:
return None
try:
return self.get_query_set().get(
user=user, target_content_type=content_type, target_object_id=obj.id
)
except self.model.DoesNotExist:
return None
def create(self, user, obj, model=None):
"""
Creates and returns a new Favorite obj for the given user and obj
"""
content_type, content_object = _get_content_type_and_obj(obj, model)
fav = super().create(
user=user,
target_content_type=content_type,
target_object_id=content_object.pk,
target=content_object,
)
return fav
def get_or_create(self, user, obj, model=None):
"""
Gets or creates a Favorite for the given user and obj.
Returns tuple (favorite, created) where created is a boolean.
This method is atomic and safe from race conditions.
"""
content_type, content_object = _get_content_type_and_obj(obj, model)
fav, created = super().get_or_create(
user=user,
target_content_type=content_type,
target_object_id=content_object.pk,
defaults={"target": content_object},
)
return fav, created