Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(form): allow Answers with empty value #791

Merged
merged 1 commit into from Nov 18, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
19 changes: 15 additions & 4 deletions caluma/form/filters.py
Expand Up @@ -108,6 +108,7 @@ class AnswerLookupMode(Enum):
CONTAINS = "contains"
ICONTAINS = "icontains"
INTERSECTS = "intersects"
ISNULL = "isnull"

GTE = "gte"
GT = "gt"
Expand All @@ -121,10 +122,14 @@ class AnswerHierarchyMode(Enum):


class HasAnswerFilterType(InputObjectType):
"""Lookup type to search document structures."""
"""
Lookup type to search document structures.

When using lookup `ISNULL`, the provided `value` will be ignored.
"""

question = graphene.ID(required=True)
value = graphene.types.generic.GenericScalar(required=True)
value = graphene.types.generic.GenericScalar(required=False)
lookup = AnswerLookupMode()
hierarchy = AnswerHierarchyMode()

Expand All @@ -146,18 +151,21 @@ def __init__(self, *args, **kwargs):
AnswerLookupMode.STARTSWITH,
AnswerLookupMode.CONTAINS,
AnswerLookupMode.ICONTAINS,
AnswerLookupMode.ISNULL,
],
"integer": [
AnswerLookupMode.EXACT,
AnswerLookupMode.LT,
AnswerLookupMode.LTE,
AnswerLookupMode.GT,
AnswerLookupMode.GTE,
AnswerLookupMode.ISNULL,
],
"multiple_choice": [
AnswerLookupMode.EXACT,
AnswerLookupMode.CONTAINS,
AnswerLookupMode.INTERSECTS,
AnswerLookupMode.ISNULL,
],
}
VALID_LOOKUPS["date"] = VALID_LOOKUPS["integer"]
Expand All @@ -177,10 +185,13 @@ def filter(self, qs, value):
return qs

def apply_expr(self, qs, expr):
lookup = expr.get("lookup", self.lookup_expr)

question_slug = expr["question"]
match_value = expr["value"]
match_value = expr.get("value")
if lookup == AnswerLookupMode.ISNULL:
match_value = True

lookup = expr.get("lookup", self.lookup_expr)
hierarchy = expr.get("hierarchy", AnswerHierarchyMode.FAMILY)

question = models.Question.objects.get(slug=question_slug)
Expand Down
4 changes: 2 additions & 2 deletions caluma/form/historical_schema.py
Expand Up @@ -125,7 +125,7 @@ class Meta:
class HistoricalFileAnswer(FileAnswer):
value = graphene.Field(
HistoricalFile,
required=True,
required=False,
as_of=graphene.types.datetime.DateTime(required=True),
)

Expand Down Expand Up @@ -175,7 +175,7 @@ class Meta:
class HistoricalTableAnswer(TableAnswer):
value = graphene.List(
HistoricalDocument,
required=True,
required=False,
as_of=graphene.types.datetime.DateTime(required=True),
)

Expand Down
12 changes: 6 additions & 6 deletions caluma/form/schema.py
Expand Up @@ -657,7 +657,7 @@ def get_queryset(cls, queryset, info):


class IntegerAnswer(AnswerQuerysetMixin, FormDjangoObjectType):
value = graphene.Int(required=True)
value = graphene.Int()

class Meta:
model = models.Answer
Expand All @@ -667,7 +667,7 @@ class Meta:


class FloatAnswer(AnswerQuerysetMixin, FormDjangoObjectType):
value = graphene.Float(required=True)
value = graphene.Float()

class Meta:
model = models.Answer
Expand All @@ -677,7 +677,7 @@ class Meta:


class DateAnswer(AnswerQuerysetMixin, FormDjangoObjectType):
value = graphene.types.datetime.Date(required=True)
value = graphene.types.datetime.Date()

def resolve_value(self, info, **args):
return self.date
Expand All @@ -690,7 +690,7 @@ class Meta:


class StringAnswer(AnswerQuerysetMixin, FormDjangoObjectType):
value = graphene.String(required=True)
value = graphene.String()

class Meta:
model = models.Answer
Expand All @@ -700,7 +700,7 @@ class Meta:


class ListAnswer(AnswerQuerysetMixin, FormDjangoObjectType):
value = graphene.List(graphene.String, required=True)
value = graphene.List(graphene.String)

class Meta:
model = models.Answer
Expand Down Expand Up @@ -731,7 +731,7 @@ class Meta:


class TableAnswer(AnswerQuerysetMixin, FormDjangoObjectType):
value = graphene.List(Document, required=True)
value = graphene.List(Document)

def resolve_value(self, info, **args):
return self.documents.order_by("-answerdocument__sort")
Expand Down
18 changes: 10 additions & 8 deletions caluma/form/serializers.py
Expand Up @@ -464,6 +464,8 @@ class Meta:

class SaveAnswerSerializer(serializers.ModelSerializer):
def validate(self, data):
if "value" not in data:
data["value"] = None
validators.AnswerValidator().validate(**data, info=self.context["info"])
return super().validate(data)

Expand All @@ -473,35 +475,35 @@ class Meta:


class SaveDocumentStringAnswerSerializer(SaveAnswerSerializer):
value = CharField(trim_whitespace=False, allow_blank=True)
value = CharField(trim_whitespace=False, allow_blank=True, required=False)

class Meta(SaveAnswerSerializer.Meta):
pass


class SaveDocumentListAnswerSerializer(SaveAnswerSerializer):
value = ListField(child=CharField())
value = ListField(child=CharField(), required=False)

class Meta(SaveAnswerSerializer.Meta):
pass


class SaveDocumentIntegerAnswerSerializer(SaveAnswerSerializer):
value = IntegerField()
value = IntegerField(required=False)

class Meta(SaveAnswerSerializer.Meta):
pass


class SaveDocumentFloatAnswerSerializer(SaveAnswerSerializer):
value = FloatField()
value = FloatField(required=False)

class Meta(SaveAnswerSerializer.Meta):
pass


class SaveDocumentDateAnswerSerializer(SaveAnswerSerializer):
value = DateField(source="date")
value = DateField(source="date", required=False)

class Meta(SaveAnswerSerializer.Meta):
pass
Expand All @@ -512,7 +514,7 @@ class SaveDocumentTableAnswerSerializer(SaveAnswerSerializer):
source="documents",
queryset=models.Document.objects,
many=True,
required=True,
required=False,
help_text="List of document IDs representing the rows in the table.",
)

Expand Down Expand Up @@ -598,8 +600,8 @@ class Meta(SaveAnswerSerializer.Meta):


class SaveDocumentFileAnswerSerializer(SaveAnswerSerializer):
value = CharField(write_only=True, source="file")
value_id = PrimaryKeyRelatedField(read_only=True, source="file")
value = CharField(write_only=True, source="file", required=False)
value_id = PrimaryKeyRelatedField(read_only=True, source="file", required=False)

def set_file(self, validated_data):
file_name = validated_data.get("file")
Expand Down