ob-dj-store 0.0.12__py3-none-any.whl → 0.0.12.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ob_dj_store/apis/stores/rest/serializers/serializers.py +88 -46
- ob_dj_store/core/stores/models/_favorite.py +6 -7
- ob_dj_store/core/stores/settings_validation.py +44 -1
- {ob_dj_store-0.0.12.dist-info → ob_dj_store-0.0.12.2.dist-info}/METADATA +1 -1
- {ob_dj_store-0.0.12.dist-info → ob_dj_store-0.0.12.2.dist-info}/RECORD +7 -7
- {ob_dj_store-0.0.12.dist-info → ob_dj_store-0.0.12.2.dist-info}/WHEEL +0 -0
- {ob_dj_store-0.0.12.dist-info → ob_dj_store-0.0.12.2.dist-info}/top_level.txt +0 -0
@@ -1,5 +1,4 @@
|
|
1
1
|
import calendar
|
2
|
-
import sys
|
3
2
|
import typing
|
4
3
|
from datetime import time, timedelta
|
5
4
|
|
@@ -7,7 +6,9 @@ from django.conf import settings
|
|
7
6
|
from django.contrib.contenttypes.models import ContentType
|
8
7
|
from django.contrib.gis.geos import Point
|
9
8
|
from django.core.exceptions import ObjectDoesNotExist, ValidationError
|
9
|
+
from django.db import models
|
10
10
|
from django.shortcuts import get_object_or_404
|
11
|
+
from django.utils.module_loading import import_string
|
11
12
|
from django.utils.timezone import now
|
12
13
|
from django.utils.translation import gettext_lazy as _
|
13
14
|
from rest_framework import serializers
|
@@ -963,18 +964,25 @@ class GenericSerializer(serializers.Serializer):
|
|
963
964
|
return serializer_class(context=context).to_representation(value)
|
964
965
|
|
965
966
|
def get_serializer_for_instance(self, instance):
|
966
|
-
serializer_class = instance.__class__.__name__
|
967
|
-
|
968
|
-
|
969
|
-
|
970
|
-
|
967
|
+
serializer_class = instance.__class__.__name__
|
968
|
+
return import_string(
|
969
|
+
store_settings.FAVORITES_SERIALIZERS_PATHS[serializer_class]
|
970
|
+
)
|
971
|
+
|
972
|
+
|
973
|
+
def get_favorite_extras_models():
|
974
|
+
extras_list = []
|
975
|
+
for key, value in settings.FAVORITE_TYPES.items():
|
976
|
+
if "extras" in value:
|
977
|
+
extras_list.extend(value["extras"].keys())
|
978
|
+
return extras_list
|
971
979
|
|
972
980
|
|
973
981
|
class FavoriteExtraSerializer(serializers.ModelSerializer):
|
974
982
|
content_object = GenericSerializer(read_only=True)
|
975
983
|
object_id = serializers.IntegerField(min_value=1, write_only=True)
|
976
984
|
object_type = serializers.ChoiceField(
|
977
|
-
write_only=True, choices=
|
985
|
+
write_only=True, choices=get_favorite_extras_models()
|
978
986
|
)
|
979
987
|
|
980
988
|
class Meta:
|
@@ -986,13 +994,23 @@ class FavoriteExtraSerializer(serializers.ModelSerializer):
|
|
986
994
|
"object_type",
|
987
995
|
)
|
988
996
|
|
997
|
+
def to_representation(self, instance):
|
998
|
+
data = super().to_representation(instance)
|
999
|
+
extras = get_favorite_extras_models()
|
1000
|
+
model_name = instance.content_type.model
|
1001
|
+
for extra in extras:
|
1002
|
+
if model_name == extra.lower():
|
1003
|
+
data["object_type"] = extra
|
1004
|
+
break
|
1005
|
+
return data
|
1006
|
+
|
989
1007
|
|
990
1008
|
class FavoriteSerializer(serializers.ModelSerializer):
|
991
1009
|
content_object = GenericSerializer(read_only=True)
|
992
1010
|
extras = FavoriteExtraSerializer(many=True)
|
993
1011
|
object_id = serializers.IntegerField(min_value=1, write_only=True)
|
994
1012
|
object_type = serializers.ChoiceField(
|
995
|
-
write_only=True, choices=store_settings.FAVORITE_TYPES
|
1013
|
+
write_only=True, choices=list(store_settings.FAVORITE_TYPES.keys())
|
996
1014
|
)
|
997
1015
|
|
998
1016
|
class Meta:
|
@@ -1009,63 +1027,87 @@ class FavoriteSerializer(serializers.ModelSerializer):
|
|
1009
1027
|
"name": {"required": True},
|
1010
1028
|
}
|
1011
1029
|
|
1030
|
+
def to_representation(self, instance):
|
1031
|
+
data = super().to_representation(instance)
|
1032
|
+
model_name = instance.content_type.model
|
1033
|
+
for favorite in store_settings.FAVORITE_TYPES.keys():
|
1034
|
+
if model_name == favorite.lower():
|
1035
|
+
data["object_type"] = favorite
|
1036
|
+
break
|
1037
|
+
return data
|
1038
|
+
|
1012
1039
|
def _lookup_validation(self, data):
|
1013
|
-
content_type = ContentType.objects.get_for_model(
|
1014
|
-
extras_lookup_content_type = {}
|
1015
|
-
for extra in data["extras"]:
|
1016
|
-
content_type_extra = extra.model
|
1017
|
-
extras_lookup_content_type[content_type_extra] = extra
|
1040
|
+
content_type = ContentType.objects.get_for_model(data["content_object"])
|
1018
1041
|
queryset = Favorite.objects.filter(
|
1019
1042
|
content_type=content_type,
|
1020
1043
|
object_id=data["content_object"].id,
|
1021
1044
|
user=self.context["request"].user,
|
1022
|
-
)
|
1023
|
-
|
1024
|
-
|
1025
|
-
|
1026
|
-
|
1027
|
-
|
1028
|
-
|
1029
|
-
|
1030
|
-
|
1045
|
+
).prefetch_related("extras")
|
1046
|
+
|
1047
|
+
if not queryset.exists():
|
1048
|
+
return
|
1049
|
+
|
1050
|
+
for favorite in queryset:
|
1051
|
+
content_objects = [
|
1052
|
+
instance.content_object for instance in favorite.extras.all()
|
1053
|
+
]
|
1054
|
+
if data["extras"] == content_objects:
|
1055
|
+
raise serializers.ValidationError(
|
1056
|
+
_(f"You cannot favorite the same item twice")
|
1057
|
+
)
|
1058
|
+
|
1059
|
+
def get_object(self, model: models.Model, id: int):
|
1060
|
+
try:
|
1061
|
+
object = model.objects.get(pk=id)
|
1062
|
+
return object
|
1063
|
+
except model.DoesNotExist:
|
1031
1064
|
raise serializers.ValidationError(
|
1032
|
-
_(f"
|
1065
|
+
_(f"{model.__name__} with the id of {id} does not exist")
|
1033
1066
|
)
|
1034
1067
|
|
1035
1068
|
def validate(self, attrs):
|
1036
1069
|
validated_data = super().validate(attrs)
|
1070
|
+
extras_data = {}
|
1037
1071
|
name = validated_data["name"]
|
1038
1072
|
object_type = validated_data["object_type"]
|
1039
|
-
|
1040
|
-
|
1041
|
-
)
|
1042
|
-
raise serializers.ValidationError(
|
1043
|
-
_(f"Cannot resolve keyword '{object_type}' into an object type")
|
1044
|
-
)
|
1045
|
-
object_type_model = getattr(sys.modules[__name__], object_type)
|
1073
|
+
object_type_model = import_string(
|
1074
|
+
store_settings.FAVORITE_TYPES[object_type]["path"]
|
1075
|
+
)
|
1046
1076
|
object_instance = get_object_or_404(
|
1047
1077
|
object_type_model, pk=validated_data["object_id"]
|
1048
1078
|
)
|
1049
|
-
extras_data = {}
|
1050
|
-
extras = []
|
1051
1079
|
for extra in validated_data["extras"]:
|
1052
|
-
|
1053
|
-
|
1080
|
+
if (
|
1081
|
+
extra["object_type"]
|
1082
|
+
not in store_settings.FAVORITE_TYPES[object_type]["extras"]
|
1083
|
+
):
|
1054
1084
|
raise serializers.ValidationError(
|
1055
|
-
_(
|
1056
|
-
f"Cannot resolve keyword '{extra_object_type}' into an object type"
|
1057
|
-
)
|
1085
|
+
_(f"{extra['object_type']} Cannot be extra of {object_type}")
|
1058
1086
|
)
|
1059
|
-
|
1060
|
-
extras_data
|
1061
|
-
|
1062
|
-
|
1063
|
-
|
1064
|
-
|
1065
|
-
|
1066
|
-
|
1067
|
-
|
1087
|
+
extra_object_type = extra["object_type"]
|
1088
|
+
extras_data.setdefault(
|
1089
|
+
extra_object_type,
|
1090
|
+
{
|
1091
|
+
"model": import_string(
|
1092
|
+
store_settings.FAVORITE_TYPES[object_type]["extras"][
|
1093
|
+
extra_object_type
|
1094
|
+
]["path"]
|
1095
|
+
),
|
1096
|
+
"ids": [],
|
1097
|
+
},
|
1098
|
+
)
|
1099
|
+
extras_data[extra_object_type]["ids"].append(extra["object_id"])
|
1068
1100
|
|
1101
|
+
extras = []
|
1102
|
+
for key, value in extras_data.items():
|
1103
|
+
type = store_settings.FAVORITE_TYPES[object_type]["extras"][key]["type"]
|
1104
|
+
if len(value["ids"]) > 1 and type == store_settings.SIGNLE_FAVORITE_EXTRA:
|
1105
|
+
raise serializers.ValidationError(_(f"Cannot set multiple {key}s"))
|
1106
|
+
for id in value["ids"]:
|
1107
|
+
extras.append(
|
1108
|
+
self.get_object(value["model"], id)
|
1109
|
+
) # get objects of extras instead of ids
|
1110
|
+
extras = list(set(extras)) # remove duplicated extras
|
1069
1111
|
validated_data = {
|
1070
1112
|
"content_object": object_instance,
|
1071
1113
|
"extras": extras,
|
@@ -44,13 +44,12 @@ class Favorite(DjangoModelCleanMixin, models.Model):
|
|
44
44
|
)
|
45
45
|
favorite.save()
|
46
46
|
for extra in extras:
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
)
|
47
|
+
extra_content_type = ContentType.objects.get_for_model(type(extra))
|
48
|
+
favorite.extras.create(
|
49
|
+
content_type=extra_content_type,
|
50
|
+
object_id=extra.id,
|
51
|
+
content_object=extra,
|
52
|
+
)
|
54
53
|
return favorite
|
55
54
|
|
56
55
|
|
@@ -40,6 +40,49 @@ def store_validation_settings(app_configs, **kwargs):
|
|
40
40
|
)
|
41
41
|
)
|
42
42
|
|
43
|
-
if
|
43
|
+
if hasattr(settings, "GIFT_PAYMENT_METHOD_PATH"):
|
44
44
|
_path_validation(settings.GIFT_PAYMENT_METHOD_PATH)
|
45
|
+
|
46
|
+
# Favorite validation settings
|
47
|
+
if hasattr(settings, "FAVORITE_TYPES"):
|
48
|
+
for key, favorite in settings.FAVORITE_TYPES.items():
|
49
|
+
if not favorite.get("path"):
|
50
|
+
errors.append(
|
51
|
+
Error(
|
52
|
+
f"Model path should be set for {key}",
|
53
|
+
id="store_validation_settings_error",
|
54
|
+
)
|
55
|
+
)
|
56
|
+
else:
|
57
|
+
_path_validation(favorite["path"])
|
58
|
+
if favorite.get("extras", None):
|
59
|
+
for key_extra, extra in favorite["extras"].items():
|
60
|
+
if not extra.get("path", None):
|
61
|
+
errors.append(
|
62
|
+
Error(
|
63
|
+
f"Model path should be set for {key}",
|
64
|
+
id="store_validation_settings_error",
|
65
|
+
)
|
66
|
+
)
|
67
|
+
else:
|
68
|
+
_path_validation(extra["path"])
|
69
|
+
if extra.get("type", None) == None:
|
70
|
+
errors.append(
|
71
|
+
Error(
|
72
|
+
f"type must be set for {key_extra}",
|
73
|
+
id="store_validation_settings_error",
|
74
|
+
)
|
75
|
+
)
|
76
|
+
else:
|
77
|
+
if not (
|
78
|
+
hasattr(settings, "SIGNLE_FAVORITE_EXTRA")
|
79
|
+
and hasattr(settings, "MULTIPLE_FAVORITE_EXTRA")
|
80
|
+
):
|
81
|
+
errors.append(
|
82
|
+
Error(
|
83
|
+
f"SIGNLE_FAVORITE_EXTRA and MULTIPLE_FAVORITE_EXTRA must be set",
|
84
|
+
id="store_validation_settings_error",
|
85
|
+
)
|
86
|
+
)
|
87
|
+
|
45
88
|
return errors
|
@@ -3,7 +3,7 @@ ob_dj_store/apis/stores/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG
|
|
3
3
|
ob_dj_store/apis/stores/filters.py,sha256=18Sb8Id1mgCC0zAzTOQRfBaS7bkyD_sgM8_jAbf1ulE,6349
|
4
4
|
ob_dj_store/apis/stores/urls.py,sha256=cPForgFpOgOGCUVAk6DZcZ7qOooMf1zpDIr1BA0L_8A,1593
|
5
5
|
ob_dj_store/apis/stores/views.py,sha256=0MTOaEHAFR4nKKjOc_bdpo93sYHkp2JvkX7hRlK3GNs,31701
|
6
|
-
ob_dj_store/apis/stores/rest/serializers/serializers.py,sha256
|
6
|
+
ob_dj_store/apis/stores/rest/serializers/serializers.py,sha256=b3Gka1WflitjxN6Gp-8BD1gKlCouQDZtrZOt2crFd38,38966
|
7
7
|
ob_dj_store/apis/tap/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
8
8
|
ob_dj_store/apis/tap/serializers.py,sha256=KPrBK4h2-fWvEVf6vOj2ww5-USV9WqpyYicIqoHIiXI,1065
|
9
9
|
ob_dj_store/apis/tap/urls.py,sha256=bnOTv6an11kxpo_FdqlhsizlGPLVpNxBjCyKcf3_C9M,367
|
@@ -15,7 +15,7 @@ ob_dj_store/core/stores/admin_inlines.py,sha256=SLj8mMa-Sc3oP693R0W9c3Ocyk7eb34I
|
|
15
15
|
ob_dj_store/core/stores/apps.py,sha256=ZadmEER_dNcQTH617b3fAsYZJSyRw0g46Kjp4eOAsOU,498
|
16
16
|
ob_dj_store/core/stores/managers.py,sha256=6fCyTGgRnZshTri9UdEFlAPv3lKjyMllK0BG-OqUwOs,6804
|
17
17
|
ob_dj_store/core/stores/receivers.py,sha256=PCe40N6S31fTiGGty94LC-CIUQsBoxRlZiTxxCaYlHU,3611
|
18
|
-
ob_dj_store/core/stores/settings_validation.py,sha256=
|
18
|
+
ob_dj_store/core/stores/settings_validation.py,sha256=T_gQ2WbQlG7lqu3XgqiCZ9mqfSN4tlijdRG7efcDmkA,3123
|
19
19
|
ob_dj_store/core/stores/utils.py,sha256=_FwZEIwKdfj3CuYHCz3wKqq5TBb8xak7UiiCB1oggKc,1850
|
20
20
|
ob_dj_store/core/stores/gateway/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
21
21
|
ob_dj_store/core/stores/gateway/tap/__init__.py,sha256=5Z6azpb6tmr1nRvKwQWzlYw9ruvw-9ZMBWRqEngDKTM,40
|
@@ -101,7 +101,7 @@ ob_dj_store/core/stores/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQe
|
|
101
101
|
ob_dj_store/core/stores/models/__init__.py,sha256=fNB_sn6HM6EmTp_Z-Q7KXD8HDWVjG3qlayrWqvygvbw,1617
|
102
102
|
ob_dj_store/core/stores/models/_address.py,sha256=qS5TQ9Z12zx_4CrrHvG8PoYVkdiOq_MtbKR14WKh3Hw,1661
|
103
103
|
ob_dj_store/core/stores/models/_cart.py,sha256=qgjg5MXTMRIZRJJDx5BQ1pa9__ylfrnYMMRGbB2R53c,4555
|
104
|
-
ob_dj_store/core/stores/models/_favorite.py,sha256=
|
104
|
+
ob_dj_store/core/stores/models/_favorite.py,sha256=IA3p4u_-U0KcpofFMSkcuNWaI7C1hFkFdgMwQYYZGzw,2513
|
105
105
|
ob_dj_store/core/stores/models/_feedback.py,sha256=eCUVgprNK5hSRKOS4M_pdR7QH2-rqhoYevlpykhCOLg,1472
|
106
106
|
ob_dj_store/core/stores/models/_inventory.py,sha256=vAXSpCyUdYDIWgUEUUObQfhAcCcQO6j6zATrHf5dPuQ,3928
|
107
107
|
ob_dj_store/core/stores/models/_order.py,sha256=lizkG-HEsxsC7Xasi5nnAtUnBL4riXezR48LblX-Zsk,8246
|
@@ -113,7 +113,7 @@ ob_dj_store/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU
|
|
113
113
|
ob_dj_store/utils/helpers.py,sha256=FtXXJOD2PILqZTyuf80bmf0KuWW64hxbJG6naJdxI5w,1607
|
114
114
|
ob_dj_store/utils/model.py,sha256=DV7hOhTaZL3gh9sptts2jTUFlTArKG3i7oPioq9HLFE,303
|
115
115
|
ob_dj_store/utils/utils.py,sha256=8UVAFB56qUSjJJ5f9vnermtw638gdFy4CFRCuMbns_M,1342
|
116
|
-
ob_dj_store-0.0.12.dist-info/METADATA,sha256=
|
117
|
-
ob_dj_store-0.0.12.dist-info/WHEEL,sha256=2wepM1nk4DS4eFpYrW1TTqPcoGNfHhhO_i5m4cOimbo,92
|
118
|
-
ob_dj_store-0.0.12.dist-info/top_level.txt,sha256=CZG3G0ptTkzGnc0dFYN-ZD7YKdJBmm47bsmGwofD_lk,12
|
119
|
-
ob_dj_store-0.0.12.dist-info/RECORD,,
|
116
|
+
ob_dj_store-0.0.12.2.dist-info/METADATA,sha256=ReVvSLpSZepJmFvkEIOo0tV9ZjtH9JoKpFvx3MDLg-Q,2827
|
117
|
+
ob_dj_store-0.0.12.2.dist-info/WHEEL,sha256=2wepM1nk4DS4eFpYrW1TTqPcoGNfHhhO_i5m4cOimbo,92
|
118
|
+
ob_dj_store-0.0.12.2.dist-info/top_level.txt,sha256=CZG3G0ptTkzGnc0dFYN-ZD7YKdJBmm47bsmGwofD_lk,12
|
119
|
+
ob_dj_store-0.0.12.2.dist-info/RECORD,,
|
File without changes
|
File without changes
|