首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何逐代获取工厂的排除属性?

如何逐代获取工厂的排除属性?
EN

Stack Overflow用户
提问于 2022-08-14 21:37:56
回答 1查看 92关注 0票数 0

我使用工厂男孩生成一个假用户。我需要一个应该散列的字段password (在db中,这是唯一与密码相关的行)和一个clear_password值,以便知道哈希密码的相关清除密码是什么,以便以后在测试中使用。

我尝试了两种类似的方法,Paramsexclude。只有排除工作,以生成一个明确的密码后哈希。问题是:在对象生成之后,我无法访问clear_password

requirements.txt

代码语言:javascript
复制
passlib[bcrypt]
SQLAlchemy
factory-boy

最小可复制示例(python 3.10使用需求的最后版本)

代码语言:javascript
复制
import random

import factory
import passlib.context
import sqlalchemy as sa
from sqlalchemy import orm

engine = sa.create_engine(
    'sqlite:///test.db',
    echo=True,
)

Base = orm.declarative_base(bind=engine)
pwd_context = passlib.context.CryptContext(schemes=['bcrypt'], deprecated='auto')

BCRYPT_MAX_LENGTH = 72


class User(Base):
    __tablename__ = 'user'
    id = sa.Column(sa.Integer, primary_key=True, autoincrement=True)
    password = sa.Column(sa.LargeBinary(BCRYPT_MAX_LENGTH), nullable=False)
    ...


class UserFact(factory.Factory):
    class Meta:
        model = User
        exclude = ('clear_password',)

    clear_password = factory.Faker('password', length=random.randint(8, 64))
    password = factory.LazyAttribute(lambda o: bytes(
        pwd_context.hash(o.clear_password), encoding='utf-8'))
    ...


if __name__ == '__main__':
    print(UserFact().clear_password)

回溯

代码语言:javascript
复制
Traceback (most recent call last):
  File "path/to/file.py", line 38, in <module>
    print(User().clear_password)
AttributeError: 'User' object has no attribute 'clear_password'
EN

回答 1

Stack Overflow用户

发布于 2022-08-15 16:38:31

我知道这可能不是你想要的答案,但是,如何分配一个固定的(即。对clear_password的可预测)值?

从您的问题来看,您似乎不想测试passlib实现,因此在测试期间生成的所有User都有相同的密码应该是可以的。

对于最初的问题,您不能访问被排除的成员,因为在生成时,工厂返回它们的底层模型,而不是工厂本身。但是,您可以对返回的模型进行猴子补丁,如下所示:

代码语言:javascript
复制
# rest of code omitted
class UserFact(Factory):
    class Meta:
        model = User
        exclude = ('clear_password',)

    clear_password = Faker('password', length=random.randint(8, 64))
    password = LazyAttribute(lambda o: bytes(
        pwd_context.hash(o.clear_password), encoding='utf-8'))
    
    @classmethod
    def _generate(cls, create, kwargs):
        # Forcing the evaluation of the provider outside of the
        # _generate call in order to store the value and pass it as a kwarg
        clear_password = kwargs.get("clear_password", cls.clear_password.evaluate(None, None, {"locale": "fr"}))
        user = super()._generate(create, {**kwargs, "clear_password": clear_password})
        # Monkey-patching the generated model
        user._clear_password = clear_password
        return user


if __name__ == '__main__':
    # no password
    print("uf = UserFact()")
    uf = UserFact()
    print(f'uf._clear_password : {uf._clear_password}')
    print(f"Verified : {pwd_context.verify(uf._clear_password, uf.password)}")
    
    # clear_password in kwargs
    print('uf = UserFact(clear_password="test")')
    uf = UserFact(clear_password="test")
    print(f'uf._clear_password : {uf._clear_password}')
    print(f"Verified : {pwd_context.verify(uf._clear_password, uf.password)}")
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73355266

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档