我正在为我刚开始的新GeoDjango项目编写测试。通常我使用Factory Boy和Faker来创建用于测试的模型实例。但是,我不清楚如何模拟GeoDjango PointField字段。查看Spacialite中的记录时,它显示为二进制blob。
我对GIS的东西很陌生,对于如何在Django中为PointFields创建工厂有点困惑。
# models.py
from django.contrib.gis.db import models
class Place(models.Model):
name = models.CharField(max_length=255)
location = models.PointField(blank=True, null=True)
objects = models.GeoManager()
def __str__(self):
return "%s" % self.name
# factories.py
import factory
from faker import Factory as FakerFactory
from . import models
faker = FakerFactory.create()
class PlaceFactory(factory.django.DjangoModelFactory):
class Meta:
model = models.Place
name = factory.LazyAttribute(lambda x: faker.name())
#location = What do I do?
答案 0 :(得分:9)
我认为您需要为点实例创建自定义模糊属性。你能试试吗?现在我没有设置来运行它。
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
答案 1 :(得分:7)
正如deprecated所说的那样,挑剔即将成为Factory Boy documentation。
现在FactoryBoy包含了factory.Faker类,因此大多数内置的模糊器均已弃用,以支持其Faker等效项。
正如@Steven B所说,您必须创建自己的提供程序。为了使提供程序尽可能通用,我对他的代码做了一些更改。
class DjangoGeoPointProvider(BaseProvider):
def geo_point(self, **kwargs):
kwargs['coords_only'] = True
faker = factory.Faker('local_latlng', **kwargs)
coords = faker.generate()
return Point(x=float(coords[1]), y=float(coords[0]), srid=4326)
注意:coords_only
必须始终为true,因为我们只需要lat
和long
值,而无需任何额外的元数据。
最后,就像使用local_latlng
provider或任何内置提供程序一样。这是一个完整的示例:
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')
注意:“美国”是默认的国家/地区代码,在此示例中可以省略,但是您可以在Faker文档中使用任何其他指定的国家/地区代码。
答案 2 :(得分:1)
Faker已经具有一些不错的地理功能。您可以创建自己的提供程序以使其适用于Django,例如:
import factory
from faker.providers import BaseProvider
from django.contrib.gis.geos import Point
class DjangoGeoLocationProvider(BaseProvider):
countries = ['NL', 'DE', 'FR', 'BE']
# uses faker.providers.geo
def geolocation(self, country=None):
country_code = country or factory.Faker('random_element', elements=self.countries).generate()
faker = factory.Faker('local_latlng', country_code=country_code, coords_only=True)
coords = faker.generate()
return Point(x=float(coords[1]), y=float(coords[0]), srid=4326)
这将为给定的国家/地区生成Django兼容点。
注册后:
factory.Faker.add_provider(DjangoGeoLocationProvider)
您可以像任何内置提供程序一样在DjangoModelFactory中使用它:
from factory.django import DjangoModelFactory as Factory
class PlaceFactory(Factory):
class Meta:
model = Place
location = factory.Faker('geolocation')
# or
another_location = factory.Faker('geolocation', country='NL')
答案 3 :(得分:0)
您也可以直接设置值。
import json
from factory import LazyAttribute
from factory.django import DjangoModelFactory
class PlaceFactory(DjangoModelFactory):
static_location = "{'type': 'Point', 'coordinates': [1,1]}"
random_location = LazyAttribute(lambda x: json.dumps({
'type': 'Point',
'coordinates': [random.uniform(-180.0, 180.0), random.uniform(-180.0, 180.0)]}
))