diff --git a/netbox/dcim/api/serializers.py b/netbox/dcim/api/serializers.py index fa0f6dc14..f92c1f64e 100644 --- a/netbox/dcim/api/serializers.py +++ b/netbox/dcim/api/serializers.py @@ -221,7 +221,7 @@ class WritableRackReservationSerializer(ValidatedModelSerializer): class Meta: model = RackReservation - fields = ['id', 'rack', 'units', 'description'] + fields = ['id', 'rack', 'units', 'user', 'description'] # diff --git a/netbox/dcim/forms.py b/netbox/dcim/forms.py index c3a545f7c..c4ec531f3 100644 --- a/netbox/dcim/forms.py +++ b/netbox/dcim/forms.py @@ -4,6 +4,7 @@ from mptt.forms import TreeNodeChoiceField import re from django import forms +from django.contrib.auth.models import User from django.contrib.postgres.forms.array import SimpleArrayField from django.db.models import Count, Q @@ -376,10 +377,11 @@ class RackFilterForm(BootstrapMixin, CustomFieldFilterForm): class RackReservationForm(BootstrapMixin, forms.ModelForm): units = SimpleArrayField(forms.IntegerField(), widget=ArrayFieldSelectMultiple(attrs={'size': 10})) + user = forms.ModelChoiceField(queryset=User.objects.order_by('username')) class Meta: model = RackReservation - fields = ['units', 'description'] + fields = ['units', 'user', 'description'] def __init__(self, *args, **kwargs): @@ -411,6 +413,15 @@ class RackReservationFilterForm(BootstrapMixin, forms.Form): ) +class RackReservationBulkEditForm(BootstrapMixin, BulkEditForm): + pk = forms.ModelMultipleChoiceField(queryset=RackReservation.objects.all(), widget=forms.MultipleHiddenInput) + user = forms.ModelChoiceField(queryset=User.objects.order_by('username'), required=False) + description = forms.CharField(max_length=100, required=False) + + class Meta: + nullable_fields = [] + + # # Manufacturers # diff --git a/netbox/dcim/migrations/0049_rackreservation_change_user.py b/netbox/dcim/migrations/0049_rackreservation_change_user.py new file mode 100644 index 000000000..ae9f95246 --- /dev/null +++ b/netbox/dcim/migrations/0049_rackreservation_change_user.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.6 on 2017-10-31 17:32 +from __future__ import unicode_literals + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('dcim', '0048_rack_serial'), + ] + + operations = [ + migrations.AlterField( + model_name='rackreservation', + name='user', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL), + ), + ] diff --git a/netbox/dcim/models.py b/netbox/dcim/models.py index 5d2acb09b..daa4c80cd 100644 --- a/netbox/dcim/models.py +++ b/netbox/dcim/models.py @@ -418,7 +418,7 @@ class RackReservation(models.Model): rack = models.ForeignKey('Rack', related_name='reservations', on_delete=models.CASCADE) units = ArrayField(models.PositiveSmallIntegerField()) created = models.DateTimeField(auto_now_add=True) - user = models.ForeignKey(User, editable=False, on_delete=models.PROTECT) + user = models.ForeignKey(User, on_delete=models.PROTECT) description = models.CharField(max_length=100) class Meta: diff --git a/netbox/dcim/urls.py b/netbox/dcim/urls.py index 633cf9a8b..2d00f096d 100644 --- a/netbox/dcim/urls.py +++ b/netbox/dcim/urls.py @@ -45,6 +45,7 @@ urlpatterns = [ # Rack reservations url(r'^rack-reservations/$', views.RackReservationListView.as_view(), name='rackreservation_list'), + url(r'^rack-reservations/edit/$', views.RackReservationBulkEditView.as_view(), name='rackreservation_bulk_edit'), url(r'^rack-reservations/delete/$', views.RackReservationBulkDeleteView.as_view(), name='rackreservation_bulk_delete'), url(r'^rack-reservations/(?P\d+)/edit/$', views.RackReservationEditView.as_view(), name='rackreservation_edit'), url(r'^rack-reservations/(?P\d+)/delete/$', views.RackReservationDeleteView.as_view(), name='rackreservation_delete'), diff --git a/netbox/dcim/views.py b/netbox/dcim/views.py index e0ab7f1f2..3120197d2 100644 --- a/netbox/dcim/views.py +++ b/netbox/dcim/views.py @@ -426,6 +426,16 @@ class RackReservationDeleteView(PermissionRequiredMixin, ObjectDeleteView): return obj.rack.get_absolute_url() +class RackReservationBulkEditView(PermissionRequiredMixin, BulkEditView): + permission_required = 'dcim.change_rackreservation' + cls = RackReservation + queryset = RackReservation.objects.select_related('rack', 'user') + filter = filters.RackReservationFilter + table = tables.RackReservationTable + form = forms.RackReservationBulkEditForm + default_return_url = 'dcim:rackreservation_list' + + class RackReservationBulkDeleteView(PermissionRequiredMixin, BulkDeleteView): permission_required = 'dcim.delete_rackreservation' cls = RackReservation diff --git a/netbox/templates/dcim/rackreservation_list.html b/netbox/templates/dcim/rackreservation_list.html index b93dc0bf1..f1524d328 100644 --- a/netbox/templates/dcim/rackreservation_list.html +++ b/netbox/templates/dcim/rackreservation_list.html @@ -5,7 +5,7 @@

{% block title %}Rack Reservations{% endblock %}

- {% include 'utilities/obj_table.html' with bulk_delete_url='dcim:rackreservation_bulk_delete' %} + {% include 'utilities/obj_table.html' with bulk_edit_url='dcim:rackreservation_bulk_edit' bulk_delete_url='dcim:rackreservation_bulk_delete' %}
{% include 'inc/search_panel.html' %}