Skip to content

Commit 0e16f77

Browse files
committed
Add the option to define the filtered field and exclude other field choices to easier ensure unique values
1 parent fcb1cee commit 0e16f77

File tree

1 file changed

+31
-7
lines changed

1 file changed

+31
-7
lines changed

django_features/custom_fields/fields.py

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,48 @@
33
from django.core.exceptions import ObjectDoesNotExist
44
from rest_framework import serializers
55
from rest_framework.exceptions import ValidationError
6+
from rest_framework.utils.model_meta import get_field_info
67

8+
from django_features.custom_fields.models import CustomField
79
from django_features.custom_fields.models import CustomValue
10+
from django_features.custom_fields.models.value import CustomValueQuerySet
811

912

1013
class ChoiceIdField(serializers.Field):
11-
def to_internal_value(self, data: Any) -> CustomValue:
12-
if isinstance(data, int):
14+
def __init__(
15+
self, field: CustomField, unique_field: str | None = None, **kwargs: Any
16+
) -> None:
17+
super().__init__(**kwargs)
18+
self.field = field
19+
self.unique_field = unique_field or "id"
20+
21+
valid_fields = get_field_info(CustomValue).fields_and_pk
22+
if self.unique_field not in valid_fields:
23+
raise ValueError(
24+
f"The unique_field must be a valid field of {valid_fields}: invalid field {self.unique_field}"
25+
)
26+
27+
def get_queryset(self) -> CustomValueQuerySet:
28+
return CustomValue.objects.filter(field_id=self.field.id)
29+
30+
def to_internal_value(self, data: Any) -> CustomValue | CustomValueQuerySet:
31+
qs = self.get_queryset()
32+
if isinstance(data, int) or isinstance(data, str):
1333
try:
14-
return CustomValue.objects.get(id=data)
34+
return qs.get(**{self.unique_field: data})
1535
except ObjectDoesNotExist:
1636
raise ValidationError(
17-
f"Custom value with the id {data} does not exist."
37+
f"Custom value with the {self.unique_field} {data} does not exist."
1838
)
1939
elif isinstance(data, list):
20-
values = CustomValue.objects.filter(id__in=data)
40+
values = qs.filter(**{f"{self.unique_field}__in": data})
2141
if values.count() != len(data):
22-
missing = set(data) - set(values.values_list("id", flat=True))
23-
raise ValidationError(f"Some of the given ids do not match: {missing}")
42+
missing = set(data) - set(
43+
values.values_list(self.unique_field, flat=True)
44+
)
45+
raise ValidationError(
46+
f"Some of the given {self.unique_field}s do not match: {missing}"
47+
)
2448
return values
2549
raise ValidationError(
2650
f"The given value {data} has not a valid type. Expected a list or int."

0 commit comments

Comments
 (0)