Using Factory Boy with GeoDjango PointFields
I believe you need to create a custom fuzzy attribute for point instances. Can you try this? Right now I don't have the setup to run it all through.
import random
from django.contrib.gis.geos import Point
from factory.fuzzy import BaseFuzzyAttribute
class FuzzyPoint(BaseFuzzyAttribute):
def fuzz(self):
return Point(random.uniform(-180.0, 180.0),
random.uniform(-90.0, 90.0))
class PlaceFactory(FakerFactory):
name = factory.LazyAttribute(lambda x: faker.name())
location = FuzzyPoint()
class Meta:
model = models.Place
Fussy is about to be deprecated as Factory Boy documentation says.
Now that FactoryBoy includes the factory.Faker class, most of these built-in fuzzers are deprecated in favor of their Faker equivalents.
As @Steven B said, you must create your own provider. I did some changes to his code in order to make the provider as generic as possible.
class DjangoGeoPointProvider(BaseProvider):
def geo_point(self, **kwargs):
kwargs['coords_only'] = True
# # generate() is not working in later Faker versions
# faker = factory.Faker('local_latlng', **kwargs)
# coords = faker.generate()
faker = factory.faker.faker.Faker()
coords = faker.local_latlng(**kwargs)
return Point(x=float(coords[1]), y=float(coords[0]), srid=4326)
Note: coords_only
must be always true because we just need lat
and long
values, without any extra metadata.
Note 2: generate()
is deprecated, see related answer.
Finally, it is like using the local_latlng
provider or any of the built-in providers. Here is a full example:
class TargetFactory(factory.django.DjangoModelFactory):
factory.Faker.add_provider(DjangoGeoPointProvider)
class Meta:
model = Target
radius = factory.Faker('random_int', min=4500, max=90000)
location = factory.Faker('geo_point', country_code='US')
Note: 'US' is the default country code, it could be omitted in this example, but you could use any of the other specified countries code in Faker doc.