使用Factory Boy和GeoDjango PointFields

Tom*_*Tom 5 python gis django geodjango factory-boy

我正在为我刚开始的新GeoDjango项目编写测试.通常我使用Factory BoyFaker来创建用于测试的模型实例.但是我不清楚如何模拟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
Run Code Online (Sandbox Code Playgroud)
# 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?
Run Code Online (Sandbox Code Playgroud)

dja*_*aut 11

我相信你需要为点实例创建一个自定义模糊属性.你能试试吗?现在我没有设置来运行它.

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
Run Code Online (Sandbox Code Playgroud)


mat*_*ean 10

正如Factory Boy 文档所说,Fussy 即将被弃用

现在 FactoryBoy 包含 factory.Faker 类,这些内置模糊器中的大多数都已弃用,取而代之的是 Faker 等价物。

正如@Steven B所说,您必须创建自己的提供程序。我对他的代码进行了一些更改,以使提供程序尽可能通用。

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)
Run Code Online (Sandbox Code Playgroud)

注意coords_only必须始终为真,因为我们只需要latlong值,没有任何额外的元数据。

注 2generate()已弃用,请参阅相关答案

最后,就像使用local_latlng 提供程序或任何内置提供程序一样。这是一个完整的例子:

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)
Run Code Online (Sandbox Code Playgroud)

注意:'US' 是默认的国家代码,在本例中可以省略,但您可以使用 Faker 文档中任何其他指定的国家代码。