강의

멘토링

커뮤니티

Cộng đồng Hỏi & Đáp của Inflearn

Hình ảnh hồ sơ của jahy53522475
jahy53522475

câu hỏi đã được viết

Làm cách nào để ứng dụng giao hàng tìm được nhà hàng gần tôi?

test.sh 실행시 missing arg 에러(_id)가뜹니다.

Viết

·

87

·

Đã chỉnh sửa

0

@dataclasses.dataclass(kw_only=True)
class BaseDocument:
    _id: ObjectId

    @property
    def id(self) -> ObjectId:
        return self._id

@dataclasses.dataclass
class ShopDeliveryAreaSubDocument(BaseDocument):
    poly: GeoJsonPolygon


@dataclasses.dataclass
class ShopDocument(BaseDocument):
    name: str
    category_codes: list[CategoryCode]
    delivery_areas: list[ShopDeliveryAreaSubDocument]

##test_shot_colleciton.py

async def test_shop_insert_one() -> None:
    # Given
    name = "치킨집"
    category_codes = [CategoryCode.CHICKEN]
    # 여기서 _id 값을 명시하지않아 에러가 나는것으로 보임.
    delivery_areas = [
        ShopDeliveryAreaSubDocument(
            poly=GeoJsonPolygon(coordinates=[[[0, 0], [0, 10], [10, 10], [10, 0], [0, 0]]]),
        )
    ]

 

에러코드

34 files left unchanged.
OK
Starting isort
Skipped 2 files
OK
Starting mypy
app/entities/collections/shop/shop_collection.py:51: error: Missing named argument "_id" for "ShopDeliveryAreaSubDocument"  [call-arg]
app/tests/entities/collections/shop/test_shop_collection.py:15: error: Missing named argument "_id" for "ShopDeliveryAreaSubDocument"  [call-arg]

 

BaseDocument 에는 _id : ObjectId 라는 attr이 항상 명시되도록 되어있는데 test 파일에는 명시가되어있지않아 나오는 에러같은데, 명시하지않아도 정상동작 되나요?? 아니면 Optional 값으로 주어야하는걸까요!?

 

감사합니다.

 

 

pythonmongodbFastAPI

Câu trả lời 1

0

안녕하세요, 인프런 AI 인턴입니다.

전재현님께서 질문하신 내용은 Python의 dataclass와 관련된 에러입니다. BaseDocument_id 필드는 필수적으로 지정되어야 하는데, ShopDeliveryAreaSubDocument 객체를 생성할 때 _id를 명시하지 않아서 발생한 문제로 보입니다.

우선, _id 필드가 BaseDocument에서 필수입니다. 따라서 해당 객체를 생성할 때 이 값을 제공해야 합니다. 만약 자동으로 생성하고 싶다면, Python의 dataclasses.fielddefault_factory 기능을 활용하여 옵션으로 처리할 수 있습니다.

예를 들어, ObjectId가 자동으로 생성되도록 하려면 bson.objectid.ObjectId의 생성자 호출을 default_factory로 설정할 수 있습니다.

from bson import ObjectId
import dataclasses

@dataclasses.dataclass(kw_only=True)
class BaseDocument:
    _id: ObjectId = dataclasses.field(default_factory=ObjectId)

# 이렇게 기본값을 설정하면 생성 시 `_id`를 명시적으로 지정하지 않아도 자동으로 생성됩니다.

위와 같이 설정하면 ShopDeliveryAreaSubDocument를 생성할 때 _id 값이 자동 생성되어 명시하지 않아도 됩니다.

이와 관련한 자세한 내용은 다음 링크에서 확인할 수 있습니다: Python Dataclasses.

추가적으로 mypy의 에러는 _id가 예상되는 곳에 명시되지 않았기 때문에 발생합니다. 위와 같은 방법으로 기본값을 설정하면 이러한 에러를 방지할 수 있습니다.

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다. 현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏 추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.

jahy53522475님의 프로필 이미지
jahy53522475
Người đặt câu hỏi

id가 명시되지않아서 생기는 오류입니다만. 강의자료 test_code 에서는 _id에 대한 코드가 없더라구요. 제가 빠트린부분이 있는지 궁금합니다.

 

async def test_shop_insert_one() -> None:
    # Given
    name = "치킨집"
    category_codes = [CategoryCode.CHICKEN]
    delivery_areas = [
        ShopDeliveryAreaSubDocument(
            poly=GeoJsonPolygon(coordinates=[[[0, 0], [0, 10], [10, 10], [10, 0], [0, 0]]]),
        )
    ]

    # When
    shop = await ShopCollection.insert_one(name, category_codes, delivery_areas)
    # cursor = await ShopCollection._collection.find({})
    # results = await cursor.to_list(None)
    results = await ShopCollection._collection.find({}).to_list(None)

    # Then
    assert len(results) == 1
    result = results[0]
    assert result["_id"] == shop.id
    assert result["name"] == shop.name
    assert result["category_codes"] == ["chicken"]
    assert result["delivery_areas"] == [
        {"poly": {"type": "Polygon", "coordinates": [[[0, 0], [0, 10], [10, 10], [10, 0], [0, 0]]]}}
    ]

# test_code의  result["delivery_areas"] 부분에 _id를 명시하지 않아도 통과가 되는지 궁금합니다. _id값은 매번 변할텐데 명시하는게 가능한가요?
jahy53522475님의 프로필 이미지
jahy53522475
Người đặt câu hỏi

import pytest
import pytest_asyncio
from deepdiff import DeepDiff

from app.entities.category.category_codes import CategoryCode
from app.entities.collections.geo_json import GeoJsonPolygon
from app.entities.collections.shop.shop_collection import ShopCollection
from app.entities.collections.shop.shop_document import ShopDeliveryAreaSubDocument


async def test_shop_insert_one() -> None:
    # Given
    name = "치킨집"
    category_codes = [CategoryCode.CHICKEN]
    delivery_areas = [
        ShopDeliveryAreaSubDocument(
            poly=GeoJsonPolygon(coordinates=[[[0, 0], [0, 10], [10, 10], [10, 0], [0, 0]]]),
        )
    ]

    # When
    shop = await ShopCollection.insert_one(name, category_codes, delivery_areas)
    # cursor = await ShopCollection._collection.find({})
    # results = await cursor.to_list(None)
    results = await ShopCollection._collection.find({}).to_list(None)

    # Then
    assert len(results) == 1
    result = results[0]
    assert result["_id"] == shop.id
    assert result["name"] == shop.name
    assert result["category_codes"] == ["chicken"]
    # assert result["delivery_areas"] == [
    #     {"poly": {"type": "Polygon", "coordinates": [[[0, 0], [0, 10], [10, 10], [10, 0], [0, 0]]]}}
    # ]
    diff = DeepDiff(
        result["delivery_areas"],
        [{"poly": {"type": "Polygon", "coordinates": [[[0, 0], [0, 10], [10, 10], [10, 0], [0, 0]]]}}],
        ignore_order=True,
        exclude_regex_paths=r"root\[\d+\]\['_id'\]",
    )
    assert diff == {}

deepdiff 라이브러리를 이용해서 해결하긴했습니다만 BaseDocument 를 상속하고있는 ShopDelieveryAreaSubDocument 는 id 없이 생성이 되는지는 잘 모르겠습니다. ( 강의코드에서는 _id에 대한 default값이 없는것으로 보여서요!)

recordable07111249님의 프로필 이미지
recordable07111249
Người chia sẻ kiến thức

재현님 안녕하세요! ShopDeliveryAreaSubDocument 는 BaseDocument 를 상속하지 않습니다~!

상속하지 않기 때문에 _id 가 없어도 생성할 수 있습니다~

Hình ảnh hồ sơ của jahy53522475
jahy53522475

câu hỏi đã được viết

Đặt câu hỏi