Coverage for dcim/models/base.py: 71%

19 statements  

« prev     ^ index     » next       coverage.py v7.15.2, created at 2026-10-10 18:35 +0000

1from django.core.exceptions import ValidationError 

2from django.core.validators import MaxValueValidator, MinValueValidator 

3from django.db import models 

4from django.utils.translation import gettext_lazy as _ 

5 

6from dcim.constants import PORT_POSITION_MAX, PORT_POSITION_MIN 

7 

8__all__ = ( 

9 'PortMappingBase', 

10) 

11 

12 

13class PortMappingBase(models.Model): 

14 """ 

15 Base class for PortMapping and PortTemplateMapping 

16 """ 

17 front_port_position = models.PositiveSmallIntegerField( 

18 default=1, 

19 validators=( 

20 MinValueValidator(PORT_POSITION_MIN), 

21 MaxValueValidator(PORT_POSITION_MAX), 

22 ), 

23 ) 

24 rear_port_position = models.PositiveSmallIntegerField( 

25 default=1, 

26 validators=( 

27 MinValueValidator(PORT_POSITION_MIN), 

28 MaxValueValidator(PORT_POSITION_MAX), 

29 ), 

30 ) 

31 

32 # Change-logged but private: no public API/URL, and the delete-time UPDATE cascade onto the 

33 # parent ports stays suppressed (see #21390, #22270). 

34 _netbox_private = True 

35 

36 class Meta: 

37 abstract = True 

38 constraints = ( 

39 models.UniqueConstraint( 

40 fields=('front_port', 'front_port_position'), 

41 name='%(app_label)s_%(class)s_unique_front_port_position' 

42 ), 

43 models.UniqueConstraint( 

44 fields=('rear_port', 'rear_port_position'), 

45 name='%(app_label)s_%(class)s_unique_rear_port_position' 

46 ), 

47 ) 

48 

49 def __str__(self): 

50 return f'{self.front_port}:{self.front_port_position} to {self.rear_port}:{self.rear_port_position}' 

51 

52 def clean(self): 

53 super().clean() 

54 

55 # Validate rear port position 

56 if self.rear_port_position > self.rear_port.positions: 

57 raise ValidationError({ 

58 "rear_port_position": _( 

59 "Invalid rear port position ({rear_port_position}): Rear port {name} has only {positions} " 

60 "positions." 

61 ).format( 

62 rear_port_position=self.rear_port_position, 

63 name=self.rear_port.name, 

64 positions=self.rear_port.positions 

65 ) 

66 })