Skip to content

Commit

Permalink
Release 5.11.11
Browse files Browse the repository at this point in the history
### Changelog:
- Fix(backend): Search fields generation when field has custom source and field's source matches model's field name and serializer has no field with name matching source.
- Fix(frontend): Search fields generation and push notifications status field.

See merge request vst/vst-utils!676
  • Loading branch information
onegreyonewhite committed Nov 12, 2024
2 parents 6d4b3e7 + 4f41514 commit ae991f9
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 ae991f9

Please sign in to comment.