Skip to content

Commit

Permalink
Fix(backend): Search fields generation when field has custom source a…
Browse files Browse the repository at this point in the history
…nd field's source matches model's field name and serializer has no field with name matching source.
  • Loading branch information
flwd3m authored and onegreyonewhite committed Nov 12, 2024
1 parent 6d4b3e7 commit 4f41514
Show file tree
Hide file tree
Showing 7 changed files with 45 additions and 21 deletions.
3 changes: 3 additions & 0 deletions frontend_src/vstutils/fields/boolean/BooleanField.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ export class BooleanField extends BaseField {
return false;
}

/**
* @returns {import('vue').Component}
*/
getComponent() {
return BooleanFieldMixin;
}
Expand Down
8 changes: 3 additions & 5 deletions frontend_src/vstutils/webpush.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
/* eslint-disable */

import { type IApp } from '#vstutils/app';
import { BooleanField, BooleanFieldMixin } from '#vstutils/fields/boolean';
import { type Model } from '#vstutils/models';
import { guiPopUp } from '#vstutils/popUp';
import { onFilterOperations, onSchemaViewsCreated, signals, useSignalSubscription } from '#vstutils/signals';
import { HttpMethods, formatPath, getApp, joinPaths } from '#vstutils/utils';
import { type PageEditView } from '#vstutils/views';
import { defineComponent, ref } from 'vue';
import { type Component, defineComponent, ref } from 'vue';
import { type DefaultXOptions, type FieldOptions } from './fields/base';

const notificationsSupported =
Expand Down Expand Up @@ -55,8 +53,8 @@ const NotificationStatusFieldMixin = defineComponent({
class NotificationsStatusField extends BooleanField {
static format = 'notifications-status';

static get mixins() {
return [NotificationStatusFieldMixin as any];
override getComponent(): Component {
return NotificationStatusFieldMixin;
}
}

Expand Down
3 changes: 3 additions & 0 deletions test_src/test_proj/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,9 @@
API[VST_API_VERSION][r'dynamic_fields'] = dict(
model='test_proj.models.dynamic_fields.DynamicFields'
)
API[VST_API_VERSION][r'test_search_fields_generation'] = dict(
view='test_proj.views.TestSearchFieldGenerationViewSet',
)
API[VST_API_VERSION][r'oauth2_tests'] = dict(
view='test_proj.views.TestOauth2ViewSet',
)
Expand Down
5 changes: 5 additions & 0 deletions test_src/test_proj/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@
Product
)
from .webpushes import TestNotification, TestWebPush, StaffOnlyNotification
from .views import TestSearchFieldGenerationViewSet
from rest_framework.exceptions import ValidationError
from base64 import b64encode
from PIL import Image
Expand Down Expand Up @@ -2396,6 +2397,10 @@ def test_search_fields(self):
self.get_model_class('test_proj.Author').generated_view.search_fields,
('name', 'phone', 'masked')
)
self.assertEqual(
TestSearchFieldGenerationViewSet.search_fields,
('value',),
)

def test_etag(self):
client = self.client
Expand Down
19 changes: 17 additions & 2 deletions test_src/test_proj/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import pydantic
from django.utils.functional import SimpleLazyObject
from rest_framework.fields import IntegerField
from rest_framework.fields import IntegerField, CharField
from rest_framework.permissions import AllowAny

from vstutils.api import responses, filter_backends, fields
Expand All @@ -18,7 +18,7 @@
from vstutils.utils import create_view
from vstutils.gui.context import gui_version

from .models import Host, HostList, HostGroup, ModelWithBinaryFiles, ModelWithFK, CachableProxyModel
from .models import Host, HostList, HostGroup, ModelWithBinaryFiles, ModelWithFK, CachableProxyModel, Variable


class TestFilterBackend(filter_backends.VSTFilterBackend):
Expand Down Expand Up @@ -309,3 +309,18 @@ def counter(self, request):
# Some tests run with session middleware disabled so it needs to be saved manually
request.session.save()
return responses.Response200({'value': value})


TestSearchFieldGenerationViewSet = Variable.get_view_class(
ignore_meta=True,
serializer_class_name='TestSearchFieldGenerationSerializer',
list_fields=['value_alias'],
override_list_fields={
# Check that when
# field has custom source
# and field's source matches model's field name
# and serializer has no field with name matching source
# search fields generation will not fail
'value_alias': CharField(source='value'),
},
)
2 changes: 1 addition & 1 deletion vstutils/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
# pylint: disable=django-not-available
__version__: str = '5.11.10'
__version__: str = '5.11.11'
26 changes: 13 additions & 13 deletions vstutils/models/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -560,20 +560,20 @@ def _get_search_fields(cls, serializer, fields=None):
else:
model_fields = cls.get_model_fields_mapping() # pylint: disable=no-value-for-parameter
serializer_fields = serializer().fields
avail_fields = filter(
tuple(model_fields.keys()).__contains__,
tuple(
k if v.source is None or v.source == '*' else v.source
for k, v in serializer_fields.items()
if not isinstance(v, EXCLUDED_FIELDS)
for field_name, field in serializer_fields.items():
if isinstance(field, EXCLUDED_FIELDS):
continue
filter_prop = (
field_name
if field.source is None or field.source == '*'
else field.source
)
)
for field in avail_fields:
serializer_field = serializer_fields[field]
if isinstance(serializer_field, FkField):
yield f'{field}__{serializer_field.autocomplete_represent}'
elif isinstance(serializer_field, drfCharField):
yield field
if filter_prop not in model_fields:
continue
if isinstance(field, FkField):
yield f'{filter_prop}__{field.autocomplete_represent}'
elif isinstance(field, drfCharField):
yield filter_prop

def _get_view_class(cls, view_base_class):
"""
Expand Down

0 comments on commit 4f41514

Please sign in to comment.