Example #1
0
def model_to_dict(m, field_names=None):
    """
    Convert Django Model instance to dict based on given field names.
    Attribute names can be re-written if the given field_names is a dict.
    """
    if field_names == None:
        if hasattr(m, 'get_json_fieldnames'):
            field_names = m.get_json_fieldnames()
        else:
            field_names = get_model_field_names(m)

    obj = {}

    # encode fields
    for attr in field_names:
        try:
            v = get_model_attr(m, attr)

            if isinstance(field_names, list):
                obj[attr] = v
            elif isinstance(field_names, dict):
                obj[field_names[attr]] = v
        except:
            pass

    return obj
Example #2
0
    def get_model_fields(self, model):
        """
        Return a list of all fields for the given model. Certain fields are
        excluded for now, for example ManyToMany fields, because we do not
        support them yet.
        """
        for fieldname in get_model_field_names(model):
            try:
                field = model._meta.get_field(fieldname)
            except FieldDoesNotExist:
                continue

            # we do not attempt to sync arbitary relations yet, the only
            # field that we do support is ForeignKey
            if isinstance(field, RelatedField) and not \
               isinstance(field, models.ForeignKey):
                continue

            yield field
Example #3
0
    def get_changes(self, a, b=None):
        """
        Return a structure in JSON that describes the changes that occurred for
        the given model a (before the change) and b (after the change).
        """
        # nothing to work with
        if a is None and b is None:
            return None

        # identify model class and get list of known models
        _class = a.__class__
        models = get_models()

        # identify all database columns from model
        fieldnames = get_model_field_names(_class)

        # generate index over b (if available)
        index = {}
        if b is not None:
            for entry in b:
                index[entry.get('n')] = entry.get('a')

        def _array_equal(ass, bss):
            if len(ass) != len(bss):
                return False

            for i, a in enumerate(ass):
                if a != bss[i]:
                    return False

            return True

        # generate changes
        result = []
        for fieldname in fieldnames:
            # get field is model
            field = _class._meta.get_field(fieldname)

            # ignore file fields
            if isinstance(field, DjangoFileField):
                continue

            # get previous value (b)
            if b is not None:
                vb = index.get(field.attname)
            else:
                vb = None

            # get current and previous values
            if field.many_to_many:
                # ignore ManyToMany with through model. It will be picked up
                # by collecting related objects
                has_through_model = False
                for m in models:
                    if issubclass(field.rel.through, m):
                        has_through_model = True
                        break
                if has_through_model:
                    continue

                # get list of pk's for many-to-many related objects
                if a.pk:
                    va = getattr(a, field.name)
                    if va is not None: va = [x.pk for x in va.all()]
                else:
                    va = []
            else:
                va = getattr(a, field.attname)

            # value changed?
            changed = False
            if b is not None:
                if isinstance(va, list) and isinstance(vb, list):
                    changed = not _array_equal(va, vb)
                else:
                    changed = va != vb

            if b is None or changed:
                result.append({'n': field.attname, 'a': va, 'b': vb})
        return result
Example #4
0
 def test_get_model_field_names_should_call_get_json_fieldnames_to_determine_json_properties(self):
     self.assertEqual(
         ['id', 'title'],
         get_model_field_names(TestModelWithJsonFields(), json=True)
     )
Example #5
0
 def _get_fields_for_empty_model_json():
     get_model_field_names('', json=True)
Example #6
0
 def _get_fields_for_empty_model():
     get_model_field_names('')
Example #7
0
 def test_get_model_field_names_should_return_correct_number_of_fields(self):
     number_of_fields = len(get_model_field_names(TestModel))
     number_of_fields_json = len(get_model_field_names(TestModel, json=True))
     self.assertEqual(number_of_fields, 11)
     self.assertEqual(number_of_fields_json, 11)
Example #8
0
 def test_get_model_field_names_should_return_list(self):
     self.assertIsInstance(get_model_field_names(TestModel), list, 'must be list')
     self.assertIsInstance(get_model_field_names(TestModel, json=True), list, 'must be list')