Как я могу подделать мультиполигонное поле? - PullRequest
0 голосов
/ 02 октября 2018

Я создаю фабрику Django для модели, которая содержит MultiPolygonField.Выдает ошибку, когда я запускаю тест.Подробности ниже.

Я создал специального провайдера для подделки этого поля.Код взят из документации Django:

from django.contrib.gis.geos import (
    Polygon,
    MultiPolygon,
)
import factory
from faker import Faker
from faker.providers import BaseProvider

fake = Faker()


class Provider(BaseProvider):
    def mpoly(self):
        p1 = Polygon( ((0, 0), (0, 1), (1, 1), (0, 0)) )
        p2 = Polygon( ((1, 1), (1, 2), (2, 2), (1, 1)) )
        mpoly = MultiPolygon(p1, p2)
        return mpoly

fake.add_provider(Provider)


class GeographyFactory(factory.DjangoModelFactory):
    """
    A Factory to generate mock GeographyFactory objects to be used
    in tests.
    """

    class Meta:
        model = 'location.Geography'

    name = factory.Faker('name')
    mpoly = fake.mpoly

Ошибка, которую я получаю при запуске тестов, однако, поставила меня в тупик.

TypeError: Cannot set Geography SpatialProxy (MULTIPOLYGON) with value of type: <class 'method'>

Похоже, яне возвращает правильный тип, но я не могу понять, что он хочет вместо объекта MultiPolygon, который я возвращаю.Почему он думает, что я возвращаюсь <class 'method'>?

Любые предложения приветствуются!

1 Ответ

0 голосов
/ 01 декабря 2018

Я бы предложил определить пользовательский нечеткий атрибут, который допускал бы некоторую случайность в ваших тестах.

import factory
import factory.fuzzy
from factory import random


class FuzzyPolygon(factory.fuzzy.BaseFuzzyAttribute):
    """Yields random polygon"""
    def __init__(self, length=None, **kwargs):
        if length is None:
            length = random.randgen.randrange(3, 20, 1)
        if length < 3:
            raise Exception("Polygon needs to be 3 or greater in length.")
        self.length = length
        super().__init__(**kwargs)

    def get_random_coords(self):
        return (
            factory.Faker("latitude").generate({}),
            factory.Faker("longitude").generate({}),
        )

    def fuzz(self):
        prefix = suffix = self.get_random_coords()
        coords = [self.get_random_coords() for __ in range(self.length - 1)]
        return Polygon([prefix] + coords + [suffix])


class FuzzyMultiPolygon(factory.fuzzy.BaseFuzzyAttribute):
    """Yields random multipolygon"""
    def __init__(self, length=None, **kwargs):
        if length is None:
            length = random.randgen.randrange(2, 20, 1)
        if length < 2:
            raise Exception("MultiPolygon needs to be 2 or greater in length.")
        self.length = length
        super().__init__(**kwargs)

    def fuzz(self):
        polygons = [FuzzyPolygon().fuzz() for __ in range(self.length)]
        return MultiPolygon(*polygons)

Затем вы можете использовать их в своих DjangoModelfactory;

class GeographyFactory(factory.DjangoModelFactory):
    """
    A Factory to generate mock GeographyFactory objects to be used
    in tests.
    """

    class Meta:
        model = 'location.Geography'

    name = factory.Faker('name')
    mpoly = FuzzyMultiPolygon()
...