Skip to content

Commit

Permalink
Merge pull request #126 from paulocheque/bugfix-lookup
Browse files Browse the repository at this point in the history
Bugfix for the Issue #122. Lookup field convert dict values without b…
  • Loading branch information
paulocheque committed Mar 2, 2020
2 parents 19e25a7 + da302e4 commit 2d88386
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 4 deletions.
10 changes: 8 additions & 2 deletions django_dynamic_fixture/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,23 +35,29 @@ def look_up_alias(ddf_as_f=True, **kwargs):
a__b__c=1 => {a: {b: {c: 1}}}
"""
field_dict = {}
params_to_be_skipped = []
for alias, value in kwargs.items():
parts = alias.split(LOOKUP_SEP)
if len(parts) == 1:
params_to_be_skipped.append(alias)
level_dict = field_dict
for part in parts[:-1]:
level_dict = level_dict.setdefault(part, {})
level_dict[parts[-1]] = value
if ddf_as_f:
for root, value in field_dict.items():
field_dict[root] = dict_to_f(value)
if root in params_to_be_skipped:
field_dict[root] = value
else:
field_dict[root] = dict_to_f(value)
return field_dict


def dict_to_f(value):
"""
Example:
1 => 1
{b: 1 => F(b=1)
{b: 1} => F(b=1)
{b: {c: 1}} => F(b=F(c=1))
"""
if not isinstance(value, dict):
Expand Down
2 changes: 1 addition & 1 deletion django_dynamic_fixture/ddf.py
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ def __str__(self):
return 'F(%s)' % (', '.join(six.text_type('%s=%s') % (key, value) for key, value in self.kwargs.items()))

def __eq__(self, that):
return self.kwargs == that.kwargs
return isinstance(that, self.__class__) and self.kwargs == that.kwargs

def _get_data_from_custom_dynamic_fixture(self, field, fixture, persist_dependencies):
'''return data of a Dynamic Fixture: field=F(...)'''
Expand Down
60 changes: 60 additions & 0 deletions django_dynamic_fixture/fields.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import json

from django.conf import settings
from django.contrib.postgres.fields import (
JSONField as DjangoJSONField,
ArrayField as DjangoArrayField,
)
from django.db.models import Field


class JSONField(DjangoJSONField):
pass


class ArrayField(DjangoArrayField):
pass


if 'sqlite' in settings.DATABASES['default']['ENGINE']:
class JSONField(Field):
def db_type(self, connection):
return 'text'

def from_db_value(self, value, expression, connection):
if value is not None:
return self.to_python(value)
return value

def to_python(self, value):
if value is not None:
try:
return json.loads(value)
except (TypeError, ValueError):
return value
return value

def get_prep_value(self, value):
if value is not None:
return str(json.dumps(value))
return value

def value_to_string(self, obj):
return self.value_from_object(obj)


class ArrayField(JSONField):
def __init__(self, base_field, size=None, **kwargs):
"""Care for DjanroArrayField's kwargs."""
self.base_field = base_field
self.size = size
return super().__init__(**kwargs)

def deconstruct(self):
"""Need to create migrations properly."""
name, path, args, kwargs = super().deconstruct()
kwargs.update({
'base_field': self.base_field.clone(),
'size': self.size,
})
return name, path, args, kwargs
2 changes: 2 additions & 0 deletions django_dynamic_fixture/models_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -493,6 +493,8 @@ class Book(models.Model):
main_author = models.ForeignKey(Author, related_name='books', on_delete=models.DO_NOTHING)
authors = models.ManyToManyField('Author', related_name='m2m')
categories = models.ManyToManyField('Category', related_name='m2m')
from .fields import JSONField
metadata = JSONField(null=True)

class BookPublisher(models.Model):
book_edition = models.ForeignKey('BookEdition', on_delete=models.DO_NOTHING)
Expand Down
2 changes: 2 additions & 0 deletions django_dynamic_fixture/tests/test_sample_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ def test_book(self):
o = G('django_dynamic_fixture.Book', authors=2, categories=5)
assert o.authors.all().count() == 2
assert o.categories.all().count() == 5
o = G('django_dynamic_fixture.Book', metadata={'a': 1})
assert o.metadata == {'a': 1}

def test_book_edition(self):
o = G('django_dynamic_fixture.BookEdition')
Expand Down
7 changes: 6 additions & 1 deletion django_dynamic_fixture/tests/test_wrappers.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-

from django.test import TestCase
from django.test import TransactionTestCase as TestCase

from django_dynamic_fixture.models_test import EmptyModel, ModelWithRelationships, ModelForLibrary
from django_dynamic_fixture import N, G, F, C, P, teach, look_up_alias, PRE_SAVE, POST_SAVE
Expand Down Expand Up @@ -203,6 +203,11 @@ def test_look_up_alias_with_many_parameters(self):
assert {'a': 1, 'b': F(c=2)} == look_up_alias(a=1, b__c=2)
assert {'a': F(b=1), 'c': F(d=2)} == look_up_alias(a__b=1, c__d=2)

def test_dont_format_default_dict_values(self):
kwargs = dict(metadata=dict(a=1))
assert {'metadata': {'a': 1}} == look_up_alias(**kwargs)
assert {'metadata': {'a': 1}} == look_up_alias(metadata={'a': 1})


class PreAndPostSaveTest(TestCase):
def tearDown(self):
Expand Down

0 comments on commit 2d88386

Please sign in to comment.