mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-29 11:56:25 -06:00
Added views for rack reservations
This commit is contained in:
parent
6b53570039
commit
ac2bf91a87
@ -488,7 +488,7 @@ class RackReservation(models.Model):
|
|||||||
created = models.DateTimeField(auto_now_add=True)
|
created = models.DateTimeField(auto_now_add=True)
|
||||||
user = models.ForeignKey(User, editable=False, on_delete=models.PROTECT)
|
user = models.ForeignKey(User, editable=False, on_delete=models.PROTECT)
|
||||||
rack = models.ForeignKey('Rack', related_name='reservations', editable=False, on_delete=models.CASCADE)
|
rack = models.ForeignKey('Rack', related_name='reservations', editable=False, on_delete=models.CASCADE)
|
||||||
units = ArrayField(models.PositiveSmallIntegerField(validators=[MinValueValidator(1)]))
|
units = ArrayField(models.PositiveSmallIntegerField())
|
||||||
description = models.CharField(max_length=100)
|
description = models.CharField(max_length=100)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
@ -497,6 +497,32 @@ class RackReservation(models.Model):
|
|||||||
def __str__(self):
|
def __str__(self):
|
||||||
return u"Reservation for rack {}".format(self.rack)
|
return u"Reservation for rack {}".format(self.rack)
|
||||||
|
|
||||||
|
def clean(self):
|
||||||
|
|
||||||
|
if self.units:
|
||||||
|
|
||||||
|
# Validate that all specified units exist in the Rack.
|
||||||
|
invalid_units = [u for u in self.units if u not in self.rack.units]
|
||||||
|
if invalid_units:
|
||||||
|
raise ValidationError({
|
||||||
|
'units': u"Invalid unit(s) for {}U rack: {}".format(
|
||||||
|
self.rack.u_height,
|
||||||
|
', '.join([str(u) for u in invalid_units]),
|
||||||
|
),
|
||||||
|
})
|
||||||
|
|
||||||
|
# Check that none of the units has already been reserved for this Rack.
|
||||||
|
reserved_units = []
|
||||||
|
for resv in self.rack.reservations.exclude(pk=self.pk):
|
||||||
|
reserved_units += resv.units
|
||||||
|
conflicting_units = [u for u in self.units if u in reserved_units]
|
||||||
|
if conflicting_units:
|
||||||
|
raise ValidationError({
|
||||||
|
'units': 'The following units have already been reserved: {}'.format(
|
||||||
|
', '.join([str(u) for u in conflicting_units]),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Device Types
|
# Device Types
|
||||||
|
@ -31,6 +31,7 @@ urlpatterns = [
|
|||||||
|
|
||||||
# Rack reservations
|
# Rack reservations
|
||||||
url(r'^rack-reservations/(?P<pk>\d+)/edit/$', views.RackReservationEditView.as_view(), name='rackreservation_edit'),
|
url(r'^rack-reservations/(?P<pk>\d+)/edit/$', views.RackReservationEditView.as_view(), name='rackreservation_edit'),
|
||||||
|
url(r'^rack-reservations/(?P<pk>\d+)/delete/$', views.RackReservationDeleteView.as_view(), name='rackreservation_delete'),
|
||||||
|
|
||||||
# Racks
|
# Racks
|
||||||
url(r'^racks/$', views.RackListView.as_view(), name='rack_list'),
|
url(r'^racks/$', views.RackListView.as_view(), name='rack_list'),
|
||||||
|
@ -334,15 +334,24 @@ class RackReservationEditView(PermissionRequiredMixin, ObjectEditView):
|
|||||||
model = RackReservation
|
model = RackReservation
|
||||||
form_class = forms.RackReservationForm
|
form_class = forms.RackReservationForm
|
||||||
|
|
||||||
def alter_obj(self, obj, args, kwargs):
|
def alter_obj(self, obj, request, args, kwargs):
|
||||||
if 'rack' in kwargs:
|
if not obj.pk:
|
||||||
obj.rack = get_object_or_404(Rack, pk=kwargs['rack'])
|
obj.rack = get_object_or_404(Rack, pk=kwargs['rack'])
|
||||||
|
obj.user = request.user
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
def get_return_url(self, obj):
|
def get_return_url(self, obj):
|
||||||
return obj.rack.get_absolute_url()
|
return obj.rack.get_absolute_url()
|
||||||
|
|
||||||
|
|
||||||
|
class RackReservationDeleteView(PermissionRequiredMixin, ObjectDeleteView):
|
||||||
|
permission_required = 'dcim.delete_rackreservation'
|
||||||
|
model = RackReservation
|
||||||
|
|
||||||
|
def get_return_url(self, obj):
|
||||||
|
return obj.rack.get_absolute_url()
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Manufacturers
|
# Manufacturers
|
||||||
#
|
#
|
||||||
|
@ -198,22 +198,32 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<th>Units</th>
|
<th>Units</th>
|
||||||
<th>Description</th>
|
<th>Description</th>
|
||||||
<th>User</th>
|
|
||||||
<th>Created</th>
|
|
||||||
<th></th>
|
<th></th>
|
||||||
</tr>
|
</tr>
|
||||||
{% for resv in reservations %}
|
{% for resv in reservations %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ resv.units }}</td>
|
<td>{{ resv.units|join:', ' }}</td>
|
||||||
<td>{{ resv.description }}</td>
|
<td>
|
||||||
<td>{{ resv.user }}</td>
|
{{ resv.description }}<br />
|
||||||
<td>{{ resv.created }}</td>
|
<small>{{ resv.user }} · {{ resv.created }}</small>
|
||||||
<td>{% if perms.change_rackreservation %}<a href="{% url 'dcim:rackreservation_edit' pk=resv.pk %}">edit</a>{% endif %}</td>
|
</td>
|
||||||
|
<td class="text-right">
|
||||||
|
{% if perms.change_rackreservation %}
|
||||||
|
<a href="{% url 'dcim:rackreservation_edit' pk=resv.pk %}" class="btn btn-warning btn-xs" title="Edit reservation">
|
||||||
|
<i class="glyphicon glyphicon-pencil" aria-hidden="true"></i>
|
||||||
|
</a>
|
||||||
|
{% endif %}
|
||||||
|
{% if perms.delete_rackreservation %}
|
||||||
|
<a href="{% url 'dcim:rackreservation_delete' pk=resv.pk %}" class="btn btn-danger btn-xs" title="Delete reservation">
|
||||||
|
<i class="glyphicon glyphicon-trash" aria-hidden="true"></i>
|
||||||
|
</a>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</table>
|
</table>
|
||||||
{% else %}
|
{% else %}
|
||||||
<span class="text-muted">None</span>
|
<div class="panel-body text-muted">None</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if perms.dcim.add_rackreservation %}
|
{% if perms.dcim.add_rackreservation %}
|
||||||
<div class="panel-footer text-right">
|
<div class="panel-footer text-right">
|
||||||
|
Loading…
Reference in New Issue
Block a user