mirror of
https://github.com/netbox-community/netbox.git
synced 2026-01-23 12:08:43 -06:00
Introduce the Owner model
This commit is contained in:
1057
contrib/openapi.json
1057
contrib/openapi.json
File diff suppressed because it is too large
Load Diff
@@ -36,6 +36,12 @@ ORGANIZATION_MENU = Menu(
|
||||
get_model_item('tenancy', 'contactassignment', _('Contact Assignments'), actions=['bulk_import']),
|
||||
),
|
||||
),
|
||||
MenuGroup(
|
||||
label=_('Ownership'),
|
||||
items=(
|
||||
get_model_item('users', 'owner', _('Owners')),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
46
netbox/templates/users/owner.html
Normal file
46
netbox/templates/users/owner.html
Normal file
@@ -0,0 +1,46 @@
|
||||
{% extends 'generic/object.html' %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block subtitle %}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="card">
|
||||
<h2 class="card-header">{% trans "Owner" %}</h2>
|
||||
<table class="table table-hover attr-table">
|
||||
<tr>
|
||||
<th scope="row">{% trans "Name" %}</th>
|
||||
<td>{{ object.name }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">{% trans "Description" %}</th>
|
||||
<td>{{ object.description|placeholder }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="card">
|
||||
<h2 class="card-header">{% trans "Groups" %}</h2>
|
||||
<div class="list-group list-group-flush">
|
||||
{% for group in object.groups.all %}
|
||||
<a href="{% url 'users:group' pk=group.pk %}" class="list-group-item list-group-item-action">{{ group }}</a>
|
||||
{% empty %}
|
||||
<div class="list-group-item text-muted">{% trans "None" %}</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<h2 class="card-header">{% trans "Users" %}</h2>
|
||||
<div class="list-group list-group-flush">
|
||||
{% for user in object.users.all %}
|
||||
<a href="{% url 'users:user' pk=user.pk %}" class="list-group-item list-group-item-action">{{ user }}</a>
|
||||
{% empty %}
|
||||
<div class="list-group-item text-muted">{% trans "None" %}</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -1,3 +1,4 @@
|
||||
from .serializers_.users import *
|
||||
from .serializers_.permissions import *
|
||||
from .serializers_.tokens import *
|
||||
from .serializers_.owners import *
|
||||
|
||||
30
netbox/users/api/serializers_/owners.py
Normal file
30
netbox/users/api/serializers_/owners.py
Normal file
@@ -0,0 +1,30 @@
|
||||
from netbox.api.fields import SerializedPKRelatedField
|
||||
from netbox.api.serializers import ValidatedModelSerializer
|
||||
from users.models import Group, Owner, User
|
||||
from .users import GroupSerializer, UserSerializer
|
||||
|
||||
__all__ = (
|
||||
'OwnerSerializer',
|
||||
)
|
||||
|
||||
|
||||
class OwnerSerializer(ValidatedModelSerializer):
|
||||
groups = SerializedPKRelatedField(
|
||||
queryset=Group.objects.all(),
|
||||
serializer=GroupSerializer,
|
||||
nested=True,
|
||||
required=False,
|
||||
many=True
|
||||
)
|
||||
users = SerializedPKRelatedField(
|
||||
queryset=User.objects.all(),
|
||||
serializer=UserSerializer,
|
||||
nested=True,
|
||||
required=False,
|
||||
many=True
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = Owner
|
||||
fields = ('id', 'url', 'display_url', 'display', 'name', 'description', 'groups', 'users')
|
||||
brief_fields = ('id', 'url', 'display', 'name', 'description')
|
||||
@@ -7,17 +7,11 @@ from . import views
|
||||
router = NetBoxRouter()
|
||||
router.APIRootView = views.UsersRootView
|
||||
|
||||
# Users and groups
|
||||
router.register('users', views.UserViewSet)
|
||||
router.register('groups', views.GroupViewSet)
|
||||
|
||||
# Tokens
|
||||
router.register('tokens', views.TokenViewSet)
|
||||
|
||||
# Permissions
|
||||
router.register('permissions', views.ObjectPermissionViewSet)
|
||||
|
||||
# User preferences
|
||||
router.register('owners', views.OwnerViewSet)
|
||||
router.register('config', views.UserConfigViewSet, basename='userconfig')
|
||||
|
||||
app_name = 'users-api'
|
||||
|
||||
@@ -12,7 +12,7 @@ from rest_framework.viewsets import ViewSet
|
||||
|
||||
from netbox.api.viewsets import NetBoxModelViewSet
|
||||
from users import filtersets
|
||||
from users.models import Group, ObjectPermission, Token, User, UserConfig
|
||||
from users.models import Group, ObjectPermission, Owner, Token, User, UserConfig
|
||||
from utilities.data import deepmerge
|
||||
from utilities.querysets import RestrictedQuerySet
|
||||
from . import serializers
|
||||
@@ -88,6 +88,16 @@ class ObjectPermissionViewSet(NetBoxModelViewSet):
|
||||
filterset_class = filtersets.ObjectPermissionFilterSet
|
||||
|
||||
|
||||
#
|
||||
# Owners
|
||||
#
|
||||
|
||||
class OwnerViewSet(NetBoxModelViewSet):
|
||||
queryset = Owner.objects.all()
|
||||
serializer_class = serializers.OwnerSerializer
|
||||
filterset_class = filtersets.OwnerFilterSet
|
||||
|
||||
|
||||
#
|
||||
# User preferences
|
||||
#
|
||||
|
||||
@@ -6,12 +6,13 @@ from django.utils.translation import gettext as _
|
||||
from core.models import ObjectType
|
||||
from extras.models import NotificationGroup
|
||||
from netbox.filtersets import BaseFilterSet
|
||||
from users.models import Group, ObjectPermission, Token, User
|
||||
from users.models import Group, ObjectPermission, Owner, Token, User
|
||||
from utilities.filters import ContentTypeFilter
|
||||
|
||||
__all__ = (
|
||||
'GroupFilterSet',
|
||||
'ObjectPermissionFilterSet',
|
||||
'OwnerFilterSet',
|
||||
'TokenFilterSet',
|
||||
'UserFilterSet',
|
||||
)
|
||||
@@ -221,3 +222,44 @@ class ObjectPermissionFilterSet(BaseFilterSet):
|
||||
return queryset.filter(actions__contains=[action])
|
||||
else:
|
||||
return queryset.exclude(actions__contains=[action])
|
||||
|
||||
|
||||
class OwnerFilterSet(BaseFilterSet):
|
||||
q = django_filters.CharFilter(
|
||||
method='search',
|
||||
label=_('Search'),
|
||||
)
|
||||
group_id = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='groups',
|
||||
queryset=Group.objects.all(),
|
||||
label=_('Group (ID)'),
|
||||
)
|
||||
group = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='groups__name',
|
||||
queryset=Group.objects.all(),
|
||||
to_field_name='name',
|
||||
label=_('Group (name)'),
|
||||
)
|
||||
user_id = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='users',
|
||||
queryset=User.objects.all(),
|
||||
label=_('User (ID)'),
|
||||
)
|
||||
user = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='users__username',
|
||||
queryset=User.objects.all(),
|
||||
to_field_name='username',
|
||||
label=_('User (username)'),
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = Owner
|
||||
fields = ('id', 'name', 'description')
|
||||
|
||||
def search(self, queryset, name, value):
|
||||
if not value.strip():
|
||||
return queryset
|
||||
return queryset.filter(
|
||||
Q(name__icontains=value) |
|
||||
Q(description__icontains=value)
|
||||
)
|
||||
|
||||
@@ -12,6 +12,7 @@ from utilities.forms.widgets import BulkEditNullBooleanSelect, DateTimePicker
|
||||
__all__ = (
|
||||
'GroupBulkEditForm',
|
||||
'ObjectPermissionBulkEditForm',
|
||||
'OwnerBulkEditForm',
|
||||
'UserBulkEditForm',
|
||||
'TokenBulkEditForm',
|
||||
)
|
||||
@@ -124,3 +125,21 @@ class TokenBulkEditForm(BulkEditForm):
|
||||
nullable_fields = (
|
||||
'expires', 'description', 'allowed_ips',
|
||||
)
|
||||
|
||||
|
||||
class OwnerBulkEditForm(BulkEditForm):
|
||||
pk = forms.ModelMultipleChoiceField(
|
||||
queryset=Owner.objects.all(),
|
||||
widget=forms.MultipleHiddenInput
|
||||
)
|
||||
description = forms.CharField(
|
||||
label=_('Description'),
|
||||
max_length=200,
|
||||
required=False
|
||||
)
|
||||
|
||||
model = Owner
|
||||
fieldsets = (
|
||||
FieldSet('description',),
|
||||
)
|
||||
nullable_fields = ('description',)
|
||||
|
||||
@@ -3,10 +3,12 @@ from django.utils.translation import gettext as _
|
||||
from users.models import *
|
||||
from users.choices import TokenVersionChoices
|
||||
from utilities.forms import CSVModelForm
|
||||
from utilities.forms.fields import CSVModelMultipleChoiceField
|
||||
|
||||
|
||||
__all__ = (
|
||||
'GroupImportForm',
|
||||
'OwnerImportForm',
|
||||
'UserImportForm',
|
||||
'TokenImportForm',
|
||||
)
|
||||
@@ -50,3 +52,22 @@ class TokenImportForm(CSVModelForm):
|
||||
class Meta:
|
||||
model = Token
|
||||
fields = ('user', 'version', 'token', 'write_enabled', 'expires', 'description',)
|
||||
|
||||
|
||||
class OwnerImportForm(CSVModelForm):
|
||||
groups = CSVModelMultipleChoiceField(
|
||||
queryset=Group.objects.all(),
|
||||
required=False,
|
||||
to_field_name='name',
|
||||
)
|
||||
users = CSVModelMultipleChoiceField(
|
||||
queryset=User.objects.all(),
|
||||
required=False,
|
||||
to_field_name='username',
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = Owner
|
||||
fields = (
|
||||
'name', 'description', 'groups', 'users',
|
||||
)
|
||||
|
||||
@@ -4,7 +4,7 @@ from django.utils.translation import gettext_lazy as _
|
||||
from netbox.forms import NetBoxModelFilterSetForm
|
||||
from netbox.forms.mixins import SavedFiltersMixin
|
||||
from users.choices import TokenVersionChoices
|
||||
from users.models import Group, ObjectPermission, Token, User
|
||||
from users.models import Group, ObjectPermission, Owner, Token, User
|
||||
from utilities.forms import BOOLEAN_WITH_BLANK_CHOICES, FilterForm
|
||||
from utilities.forms.fields import DynamicModelMultipleChoiceField
|
||||
from utilities.forms.rendering import FieldSet
|
||||
@@ -14,6 +14,7 @@ from utilities.forms.widgets import DateTimePicker
|
||||
__all__ = (
|
||||
'GroupFilterForm',
|
||||
'ObjectPermissionFilterForm',
|
||||
'OwnerFilterForm',
|
||||
'TokenFilterForm',
|
||||
'UserFilterForm',
|
||||
)
|
||||
@@ -140,3 +141,21 @@ class TokenFilterForm(SavedFiltersMixin, FilterForm):
|
||||
label=_('Last Used'),
|
||||
widget=DateTimePicker()
|
||||
)
|
||||
|
||||
|
||||
class OwnerFilterForm(NetBoxModelFilterSetForm):
|
||||
model = Owner
|
||||
fieldsets = (
|
||||
FieldSet('q', 'filter_id',),
|
||||
FieldSet('group_id', 'user_id', name=_('Members')),
|
||||
)
|
||||
group_id = DynamicModelMultipleChoiceField(
|
||||
queryset=Group.objects.all(),
|
||||
required=False,
|
||||
label=_('Group')
|
||||
)
|
||||
user_id = DynamicModelMultipleChoiceField(
|
||||
queryset=User.objects.all(),
|
||||
required=False,
|
||||
label=_('User')
|
||||
)
|
||||
|
||||
@@ -23,11 +23,11 @@ from utilities.permissions import qs_filter_from_constraints
|
||||
__all__ = (
|
||||
'GroupForm',
|
||||
'ObjectPermissionForm',
|
||||
'OwnerForm',
|
||||
'TokenForm',
|
||||
'UserConfigForm',
|
||||
'UserForm',
|
||||
'UserTokenForm',
|
||||
'TokenForm',
|
||||
)
|
||||
|
||||
|
||||
@@ -431,3 +431,18 @@ class ObjectPermissionForm(forms.ModelForm):
|
||||
instance.groups.set(self.cleaned_data['groups'])
|
||||
|
||||
return instance
|
||||
|
||||
|
||||
class OwnerForm(forms.ModelForm):
|
||||
|
||||
fieldsets = (
|
||||
FieldSet('name', 'description', name=_('Owner')),
|
||||
FieldSet('groups', name=_('Groups')),
|
||||
FieldSet('users', name=_('Users')),
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = Owner
|
||||
fields = [
|
||||
'name', 'description', 'groups', 'users',
|
||||
]
|
||||
|
||||
@@ -10,6 +10,7 @@ from users import models
|
||||
|
||||
__all__ = (
|
||||
'GroupFilter',
|
||||
'OwnerFilter',
|
||||
'UserFilter',
|
||||
)
|
||||
|
||||
@@ -31,3 +32,11 @@ class UserFilter(BaseObjectTypeFilterMixin):
|
||||
date_joined: DatetimeFilterLookup[datetime] | None = strawberry_django.filter_field()
|
||||
last_login: DatetimeFilterLookup[datetime] | None = strawberry_django.filter_field()
|
||||
groups: Annotated['GroupFilter', strawberry.lazy('users.graphql.filters')] | None = strawberry_django.filter_field()
|
||||
|
||||
|
||||
@strawberry_django.filter_type(models.Owner, lookups=True)
|
||||
class OwnerFilter(BaseObjectTypeFilterMixin):
|
||||
name: FilterLookup[str] | None = strawberry_django.filter_field()
|
||||
description: FilterLookup[str] | None = strawberry_django.filter_field()
|
||||
groups: Annotated['GroupFilter', strawberry.lazy('users.graphql.filters')] | None = strawberry_django.filter_field()
|
||||
users: Annotated['UserFilter', strawberry.lazy('users.graphql.filters')] | None = strawberry_django.filter_field()
|
||||
|
||||
@@ -13,3 +13,6 @@ class UsersQuery:
|
||||
|
||||
user: UserType = strawberry_django.field()
|
||||
user_list: List[UserType] = strawberry_django.field()
|
||||
|
||||
owner: OwnerType = strawberry_django.field()
|
||||
owner_list: List[OwnerType] = strawberry_django.field()
|
||||
|
||||
@@ -3,11 +3,12 @@ from typing import List
|
||||
import strawberry_django
|
||||
|
||||
from netbox.graphql.types import BaseObjectType
|
||||
from users.models import Group, User
|
||||
from users.models import Group, Owner, User
|
||||
from .filters import *
|
||||
|
||||
__all__ = (
|
||||
'GroupType',
|
||||
'OwnerType',
|
||||
'UserType',
|
||||
)
|
||||
|
||||
@@ -32,3 +33,13 @@ class GroupType(BaseObjectType):
|
||||
)
|
||||
class UserType(BaseObjectType):
|
||||
groups: List[GroupType]
|
||||
|
||||
|
||||
@strawberry_django.type(
|
||||
Owner,
|
||||
fields=['id', 'name', 'description', 'groups', 'users'],
|
||||
filters=OwnerFilter,
|
||||
pagination=True
|
||||
)
|
||||
class OwnerType(BaseObjectType):
|
||||
pass
|
||||
|
||||
43
netbox/users/migrations/0015_owner.py
Normal file
43
netbox/users/migrations/0015_owner.py
Normal file
@@ -0,0 +1,43 @@
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('users', '0014_users_token_v2'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Owner',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False)),
|
||||
('name', models.CharField(max_length=150, unique=True)),
|
||||
('description', models.CharField(blank=True, max_length=200)),
|
||||
(
|
||||
'groups',
|
||||
models.ManyToManyField(
|
||||
blank=True,
|
||||
related_name='owners',
|
||||
related_query_name='owner',
|
||||
to='users.group',
|
||||
)
|
||||
),
|
||||
(
|
||||
'users',
|
||||
models.ManyToManyField(
|
||||
blank=True,
|
||||
related_name='owners',
|
||||
related_query_name='owner',
|
||||
to=settings.AUTH_USER_MODEL,
|
||||
)
|
||||
),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'owner',
|
||||
'verbose_name_plural': 'owners',
|
||||
'ordering': ('name',),
|
||||
},
|
||||
),
|
||||
]
|
||||
@@ -2,3 +2,4 @@ from .users import *
|
||||
from .preferences import *
|
||||
from .tokens import *
|
||||
from .permissions import *
|
||||
from .owners import *
|
||||
|
||||
49
netbox/users/models/owners.py
Normal file
49
netbox/users/models/owners.py
Normal file
@@ -0,0 +1,49 @@
|
||||
from django.db import models
|
||||
from django.urls import reverse
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from utilities.querysets import RestrictedQuerySet
|
||||
|
||||
__all__ = (
|
||||
'Owner',
|
||||
)
|
||||
|
||||
|
||||
class Owner(models.Model):
|
||||
name = models.CharField(
|
||||
verbose_name=_('name'),
|
||||
max_length=150,
|
||||
unique=True,
|
||||
)
|
||||
description = models.CharField(
|
||||
verbose_name=_('description'),
|
||||
max_length=200,
|
||||
blank=True
|
||||
)
|
||||
groups = models.ManyToManyField(
|
||||
to='users.Group',
|
||||
verbose_name=_('groups'),
|
||||
blank=True,
|
||||
related_name='owners',
|
||||
related_query_name='owner',
|
||||
)
|
||||
users = models.ManyToManyField(
|
||||
to='users.User',
|
||||
verbose_name=_('users'),
|
||||
blank=True,
|
||||
related_name='owners',
|
||||
related_query_name='owner',
|
||||
)
|
||||
|
||||
objects = RestrictedQuerySet.as_manager()
|
||||
|
||||
class Meta:
|
||||
ordering = ('name',)
|
||||
verbose_name = _('owner')
|
||||
verbose_name_plural = _('owners')
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
def get_absolute_url(self):
|
||||
return reverse('users:owner', args=[self.pk])
|
||||
@@ -2,11 +2,12 @@ import django_tables2 as tables
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from netbox.tables import NetBoxTable, columns
|
||||
from users.models import Group, ObjectPermission, Token, User
|
||||
from users.models import Group, ObjectPermission, Owner, Token, User
|
||||
|
||||
__all__ = (
|
||||
'GroupTable',
|
||||
'ObjectPermissionTable',
|
||||
'OwnerTable',
|
||||
'TokenTable',
|
||||
'UserTable',
|
||||
)
|
||||
@@ -143,3 +144,27 @@ class ObjectPermissionTable(NetBoxTable):
|
||||
default_columns = (
|
||||
'pk', 'name', 'enabled', 'object_types', 'can_view', 'can_add', 'can_change', 'can_delete', 'description',
|
||||
)
|
||||
|
||||
|
||||
class OwnerTable(NetBoxTable):
|
||||
name = tables.Column(
|
||||
verbose_name=_('Name'),
|
||||
linkify=True
|
||||
)
|
||||
groups = columns.ManyToManyColumn(
|
||||
verbose_name=_('Groups'),
|
||||
linkify_item=('users:group', {'pk': tables.A('pk')})
|
||||
)
|
||||
users = columns.ManyToManyColumn(
|
||||
verbose_name=_('Groups'),
|
||||
linkify_item=('users:group', {'pk': tables.A('pk')})
|
||||
)
|
||||
actions = columns.ActionsColumn(
|
||||
actions=('edit', 'delete'),
|
||||
)
|
||||
|
||||
class Meta(NetBoxTable.Meta):
|
||||
model = Owner
|
||||
fields = (
|
||||
'pk', 'id', 'name', 'description', 'groups', 'users',
|
||||
)
|
||||
|
||||
@@ -18,4 +18,7 @@ urlpatterns = [
|
||||
path('permissions/', include(get_model_urls('users', 'objectpermission', detail=False))),
|
||||
path('permissions/<int:pk>/', include(get_model_urls('users', 'objectpermission'))),
|
||||
|
||||
path('owners/', include(get_model_urls('users', 'owner', detail=False))),
|
||||
path('owners/<int:pk>/', include(get_model_urls('users', 'owner'))),
|
||||
|
||||
]
|
||||
|
||||
@@ -6,7 +6,7 @@ from netbox.object_actions import AddObject, BulkDelete, BulkEdit, BulkExport, B
|
||||
from netbox.views import generic
|
||||
from utilities.views import register_model_view
|
||||
from . import filtersets, forms, tables
|
||||
from .models import Group, User, ObjectPermission, Token
|
||||
from .models import Group, User, ObjectPermission, Owner, Token
|
||||
|
||||
|
||||
#
|
||||
@@ -231,3 +231,60 @@ class ObjectPermissionBulkDeleteView(generic.BulkDeleteView):
|
||||
queryset = ObjectPermission.objects.all()
|
||||
filterset = filtersets.ObjectPermissionFilterSet
|
||||
table = tables.ObjectPermissionTable
|
||||
|
||||
|
||||
#
|
||||
# Owners
|
||||
#
|
||||
|
||||
@register_model_view(Owner, 'list', path='', detail=False)
|
||||
class OwnerListView(generic.ObjectListView):
|
||||
queryset = Owner.objects.all()
|
||||
filterset = filtersets.OwnerFilterSet
|
||||
filterset_form = forms.OwnerFilterForm
|
||||
table = tables.OwnerTable
|
||||
|
||||
|
||||
@register_model_view(Owner)
|
||||
class OwnerView(generic.ObjectView):
|
||||
queryset = Owner.objects.all()
|
||||
template_name = 'users/owner.html'
|
||||
|
||||
|
||||
@register_model_view(Owner, 'add', detail=False)
|
||||
@register_model_view(Owner, 'edit')
|
||||
class OwnerEditView(generic.ObjectEditView):
|
||||
queryset = Owner.objects.all()
|
||||
form = forms.OwnerForm
|
||||
|
||||
|
||||
@register_model_view(Owner, 'delete')
|
||||
class OwnerDeleteView(generic.ObjectDeleteView):
|
||||
queryset = Owner.objects.all()
|
||||
|
||||
|
||||
@register_model_view(Owner, 'bulk_import', path='import', detail=False)
|
||||
class OwnerBulkImportView(generic.BulkImportView):
|
||||
queryset = Owner.objects.all()
|
||||
model_form = forms.OwnerImportForm
|
||||
|
||||
|
||||
@register_model_view(Owner, 'bulk_edit', path='edit', detail=False)
|
||||
class OwnerBulkEditView(generic.BulkEditView):
|
||||
queryset = Owner.objects.all()
|
||||
filterset = filtersets.OwnerFilterSet
|
||||
table = tables.OwnerTable
|
||||
form = forms.OwnerBulkEditForm
|
||||
|
||||
|
||||
@register_model_view(Owner, 'bulk_rename', path='rename', detail=False)
|
||||
class OwnerBulkRenameView(generic.BulkRenameView):
|
||||
queryset = Owner.objects.all()
|
||||
field_name = 'ownername'
|
||||
|
||||
|
||||
@register_model_view(Owner, 'bulk_delete', path='delete', detail=False)
|
||||
class OwnerBulkDeleteView(generic.BulkDeleteView):
|
||||
queryset = Owner.objects.all()
|
||||
filterset = filtersets.OwnerFilterSet
|
||||
table = tables.OwnerTable
|
||||
|
||||
Reference in New Issue
Block a user