mirror of
https://github.com/netbox-community/netbox.git
synced 2026-02-05 06:46:25 -06:00
Merge branch 'main' into feature
This commit is contained in:
@@ -2,6 +2,7 @@ from typing import TYPE_CHECKING, Annotated, List
|
||||
|
||||
import strawberry
|
||||
import strawberry_django
|
||||
from strawberry.types import Info
|
||||
|
||||
__all__ = (
|
||||
'ConfigContextMixin',
|
||||
@@ -37,7 +38,7 @@ class CustomFieldsMixin:
|
||||
class ImageAttachmentsMixin:
|
||||
|
||||
@strawberry_django.field
|
||||
def image_attachments(self, info) -> List[Annotated["ImageAttachmentType", strawberry.lazy('.types')]]:
|
||||
def image_attachments(self, info: Info) -> List[Annotated['ImageAttachmentType', strawberry.lazy('.types')]]:
|
||||
return self.images.restrict(info.context.request.user, 'view')
|
||||
|
||||
|
||||
@@ -45,17 +46,17 @@ class ImageAttachmentsMixin:
|
||||
class JournalEntriesMixin:
|
||||
|
||||
@strawberry_django.field
|
||||
def journal_entries(self, info) -> List[Annotated["JournalEntryType", strawberry.lazy('.types')]]:
|
||||
def journal_entries(self, info: Info) -> List[Annotated['JournalEntryType', strawberry.lazy('.types')]]:
|
||||
return self.journal_entries.all()
|
||||
|
||||
|
||||
@strawberry.type
|
||||
class TagsMixin:
|
||||
|
||||
tags: List[Annotated["TagType", strawberry.lazy('.types')]]
|
||||
tags: List[Annotated['TagType', strawberry.lazy('.types')]]
|
||||
|
||||
|
||||
@strawberry.type
|
||||
class ContactsMixin:
|
||||
|
||||
contacts: List[Annotated["ContactAssignmentType", strawberry.lazy('tenancy.graphql.types')]]
|
||||
contacts: List[Annotated['ContactAssignmentType', strawberry.lazy('tenancy.graphql.types')]]
|
||||
|
||||
@@ -1,9 +1,39 @@
|
||||
from django.contrib.postgres.fields import ArrayField
|
||||
from django.contrib.postgres.fields.ranges import RangeField
|
||||
from django.db.models import CharField, JSONField, Lookup
|
||||
from django.db.models.fields.json import KeyTextTransform
|
||||
|
||||
from .fields import CachedValueField
|
||||
|
||||
|
||||
class RangeContains(Lookup):
|
||||
"""
|
||||
Filter ArrayField(RangeField) columns where ANY element-range contains the scalar RHS.
|
||||
|
||||
Usage (ORM):
|
||||
Model.objects.filter(<range_array_field>__range_contains=<scalar>)
|
||||
|
||||
Works with int4range[], int8range[], daterange[], tstzrange[], etc.
|
||||
"""
|
||||
|
||||
lookup_name = 'range_contains'
|
||||
|
||||
def as_sql(self, compiler, connection):
|
||||
# Compile LHS (the array-of-ranges column/expression) and RHS (scalar)
|
||||
lhs, lhs_params = self.process_lhs(compiler, connection)
|
||||
rhs, rhs_params = self.process_rhs(compiler, connection)
|
||||
|
||||
# Guard: only allow ArrayField whose base_field is a PostgreSQL RangeField
|
||||
field = getattr(self.lhs, 'output_field', None)
|
||||
if not (isinstance(field, ArrayField) and isinstance(field.base_field, RangeField)):
|
||||
raise TypeError('range_contains is only valid for ArrayField(RangeField) columns')
|
||||
|
||||
# Range-contains-element using EXISTS + UNNEST keeps the range on the LHS: r @> value
|
||||
sql = f"EXISTS (SELECT 1 FROM unnest({lhs}) AS r WHERE r @> {rhs})"
|
||||
params = lhs_params + rhs_params
|
||||
return sql, params
|
||||
|
||||
|
||||
class Empty(Lookup):
|
||||
"""
|
||||
Filter on whether a string is empty.
|
||||
@@ -25,7 +55,7 @@ class JSONEmpty(Lookup):
|
||||
|
||||
A key is considered empty if it is "", null, or does not exist.
|
||||
"""
|
||||
lookup_name = "empty"
|
||||
lookup_name = 'empty'
|
||||
|
||||
def as_sql(self, compiler, connection):
|
||||
# self.lhs.lhs is the parent expression (could be a JSONField or another KeyTransform)
|
||||
@@ -69,6 +99,7 @@ class NetContainsOrEquals(Lookup):
|
||||
return 'CAST(%s AS INET) >>= %s' % (lhs, rhs), params
|
||||
|
||||
|
||||
ArrayField.register_lookup(RangeContains)
|
||||
CharField.register_lookup(Empty)
|
||||
JSONField.register_lookup(JSONEmpty)
|
||||
CachedValueField.register_lookup(NetHost)
|
||||
|
||||
@@ -90,7 +90,7 @@ class ConfigContextModelQuerySet(RestrictedQuerySet):
|
||||
ConfigContext.objects.filter(
|
||||
self._get_config_context_filters()
|
||||
).annotate(
|
||||
_data=EmptyGroupByJSONBAgg('data', ordering=['weight', 'name'])
|
||||
_data=EmptyGroupByJSONBAgg('data', order_by=['weight', 'name'])
|
||||
).values("_data").order_by()
|
||||
)
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user