Parcourir la source

Converted to a single column for value storage

Jeremy Stretch il y a 8 ans
Parent
commit
a33e89fed7

+ 1 - 1
netbox/extras/forms.py

@@ -44,7 +44,7 @@ def get_custom_fields_for_model(content_type, bulk_editing=False):
 
         # Text
         else:
-            field = forms.CharField(max_length=100, required=cf.required, initial=cf.default)
+            field = forms.CharField(max_length=255, required=cf.required, initial=cf.default)
 
         field.model = cf
         field.label = cf.label if cf.label else cf.name.capitalize()

+ 2 - 4
netbox/extras/migrations/0002_custom_fields.py

@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-# Generated by Django 1.10 on 2016-08-15 19:18
+# Generated by Django 1.10 on 2016-08-17 18:42
 from __future__ import unicode_literals
 
 from django.db import migrations, models
@@ -47,9 +47,7 @@ class Migration(migrations.Migration):
             fields=[
                 ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                 ('obj_id', models.PositiveIntegerField()),
-                ('val_int', models.BigIntegerField(blank=True, null=True)),
-                ('val_char', models.CharField(blank=True, max_length=100)),
-                ('val_date', models.DateField(blank=True, null=True)),
+                ('serialized_value', models.CharField(max_length=255)),
                 ('field', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='values', to='extras.CustomField')),
                 ('obj_type', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='contenttypes.ContentType')),
             ],

+ 37 - 23
netbox/extras/models.py

@@ -1,3 +1,5 @@
+from datetime import date
+
 from django.contrib.auth.models import User
 from django.contrib.contenttypes.fields import GenericForeignKey
 from django.contrib.contenttypes.models import ContentType
@@ -97,15 +99,45 @@ class CustomField(models.Model):
     def __unicode__(self):
         return self.label or self.name.capitalize()
 
+    def serialize_value(self, value):
+        """
+        Serialize the given value to a string suitable for storage as a CustomFieldValue
+        """
+        if value is None:
+            return ''
+        if self.type == CF_TYPE_BOOLEAN:
+            return str(int(bool(value)))
+        if self.type == CF_TYPE_DATE:
+            return value.strftime('%Y-%m-%d')
+        if self.type == CF_TYPE_SELECT:
+            # Could be ModelChoiceField or TypedChoiceField
+            return str(value.id) if hasattr(value, 'id') else str(value)
+        return str(value)
+
+    def deserialize_value(self, serialized_value):
+        """
+        Convert a string into the object it represents depending on the type of field
+        """
+        if serialized_value is '':
+            return None
+        if self.type == CF_TYPE_INTEGER:
+            return int(serialized_value)
+        if self.type == CF_TYPE_BOOLEAN:
+            return bool(int(serialized_value))
+        if self.type == CF_TYPE_DATE:
+            # Read date as YYYY-MM-DD
+            return date(*[int(n) for n in serialized_value.split('-')])
+        if self.type == CF_TYPE_SELECT:
+            return CustomFieldChoice.objects.get(pk=int(serialized_value))
+        return serialized_value
+
 
 class CustomFieldValue(models.Model):
     field = models.ForeignKey('CustomField', related_name='values')
     obj_type = models.ForeignKey(ContentType, related_name='+', on_delete=models.PROTECT)
     obj_id = models.PositiveIntegerField()
     obj = GenericForeignKey('obj_type', 'obj_id')
-    val_int = models.BigIntegerField(blank=True, null=True)
-    val_char = models.CharField(max_length=100, blank=True)
-    val_date = models.DateField(blank=True, null=True)
+    serialized_value = models.CharField(max_length=255)
 
     class Meta:
         ordering = ['obj_type', 'obj_id']
@@ -116,29 +148,11 @@ class CustomFieldValue(models.Model):
 
     @property
     def value(self):
-        if self.field.type == CF_TYPE_INTEGER:
-            return self.val_int
-        if self.field.type == CF_TYPE_BOOLEAN:
-            return bool(self.val_int) if self.val_int is not None else None
-        if self.field.type == CF_TYPE_DATE:
-            return self.val_date
-        if self.field.type == CF_TYPE_SELECT:
-            return CustomFieldChoice.objects.get(pk=self.val_int) if self.val_int else None
-        return self.val_char
+        return self.field.deserialize_value(self.serialized_value)
 
     @value.setter
     def value(self, value):
-        if self.field.type == CF_TYPE_INTEGER:
-            self.val_int = value
-        elif self.field.type == CF_TYPE_BOOLEAN:
-            self.val_int = int(bool(value)) if value is not None else None
-        elif self.field.type == CF_TYPE_DATE:
-            self.val_date = value
-        elif self.field.type == CF_TYPE_SELECT:
-            # Could be ModelChoiceField or TypedChoiceField
-            self.val_int = value.id if hasattr(value, 'id') else value
-        else:
-            self.val_char = value
+        self.serialized_value = self.field.serialize_value(value)
 
     def save(self, *args, **kwargs):
         if (self.field.type == CF_TYPE_TEXT and self.value == '') or self.value is None: