- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我有一个模型 Profile
,它有一个与 User
一对一的字段:
from django.db import models
class Profile(models.Model):
user = models.OneToOneField(User, related_name='user_profile', on_delete=models.CASCADE)
我正在尝试使用委托(delegate)给 Profile
模型的 __getattr__
方法更新 User
模型,类似于 http://blog.thedigitalcatonline.com/blog/2014/08/20/python-3-oop-part-3-delegation-composition-and-inheritance/#enter-the-composition :
from django.contrib.auth.models import User
def user__getattr__(self, attr):
return getattr(self.user_profile, attr)
User.add_to_class('__getattr__', user__getattr__)
这似乎按预期工作。例如,在 Profile
模型上定义的字段之一是 timezone
,现在我可以访问它了
In [4]: from lucy_web.models import *
In [5]: User.objects.first().timezone
Out[5]: 'America/Los_Angeles'
当我尝试使用 factory_boy
生成用户时出现问题.我有一个 UserFactory
和一个 RelatedFactory
引用 ProfileFactory
:
import factory
from lucy_web.models import User
from .profile_factory import ProfileFactory
class UserFactory(factory.django.DjangoModelFactory):
class Meta:
model = User
user_profile = factory.RelatedFactory(ProfileFactory, 'user')
@classmethod
def _create(cls, model_class, *args, **kwargs):
"""Override the default ``_create`` with create_user."""
manager = cls._get_manager(model_class)
# The default would use ``manager.create(*args, **kwargs)``
return manager.create_user(*args, **kwargs)
ProfileFactory
非常简单,类似于
class ProfileFactory(factory.django.DjangoModelFactory):
class Meta:
model = Profile
问题是,如果我现在尝试使用 UserFactory
创建用户,我会得到一个无限递归错误:
(lucy-web-CVxkrCFK) bash-3.2$ python manage.py shell
Python 3.7.0 (v3.7.0:1bf9cc5093, Jun 26 2018, 23:26:24)
Type 'copyright', 'credits' or 'license' for more information
IPython 6.4.0 -- An enhanced Interactive Python. Type '?' for help.
In [1]: from lucy_web.test_factories import *
In [2]: UserFactory()
(0.034) SELECT t.oid, typarray FROM pg_type t JOIN pg_namespace ns ON typnamespace = ns.oid WHERE typname = 'hstore'; args=None
(0.001) SELECT typarray FROM pg_type WHERE typname = 'citext'; args=None
(0.073) INSERT INTO "auth_user" ("password", "last_login", "is_superuser", "username", "first_name", "last_name", "email", "is_staff", "is_active", "date_joined") VALUES ('pbkdf2_sha256$100000$QuDq3QCL8zp7$Ru1O4K6I/KaMZZXDj2WVY8TV8/7rQNIL9OYL+1hWvTI=', NULL, false, 'ypearson-0@davis.biz', 'Jeffrey', 'Kim', 'ashleypham-0@scott.info', false, true, '2018-07-31T21:43:35.374902+00:00'::timestamptz) RETURNING "auth_user"."id"; args=('pbkdf2_sha256$100000$QuDq3QCL8zp7$Ru1O4K6I/KaMZZXDj2WVY8TV8/7rQNIL9OYL+1hWvTI=', None, False, 'ypearson-0@davis.biz', 'Jeffrey', 'Kim', 'ashleypham-0@scott.info', False, True, datetime.datetime(2018, 7, 31, 21, 43, 35, 374902, tzinfo=<UTC>))
(0.002) SELECT "lucy_web_profile"."id", "lucy_web_profile"."created_at", "lucy_web_profile"."updated_at", "lucy_web_profile"."user_id", "lucy_web_profile"."using_app", "lucy_web_profile"."phone", "lucy_web_profile"."phone_country", "lucy_web_profile"."street", "lucy_web_profile"."street2", "lucy_web_profile"."city", "lucy_web_profile"."state", "lucy_web_profile"."country", "lucy_web_profile"."zip_code", "lucy_web_profile"."timezone", "lucy_web_profile"."phone_type", "lucy_web_profile"."alternate_email", "lucy_web_profile"."activation_code" FROM "lucy_web_profile" WHERE "lucy_web_profile"."user_id" = 2159; args=(2159,)
---------------------------------------------------------------------------
RecursionError Traceback (most recent call last)
<ipython-input-2-96e87501585e> in <module>()
----> 1 UserFactory()
~/.local/share/virtualenvs/lucy-web-CVxkrCFK/lib/python3.7/site-packages/factory/base.py in __call__(cls, **kwargs)
44 return cls.build(**kwargs)
45 elif cls._meta.strategy == enums.CREATE_STRATEGY:
---> 46 return cls.create(**kwargs)
47 elif cls._meta.strategy == enums.STUB_STRATEGY:
48 return cls.stub(**kwargs)
~/.local/share/virtualenvs/lucy-web-CVxkrCFK/lib/python3.7/site-packages/factory/base.py in create(cls, **kwargs)
561 def create(cls, **kwargs):
562 """Create an instance of the associated class, with overriden attrs."""
--> 563 return cls._generate(enums.CREATE_STRATEGY, kwargs)
564
565 @classmethod
~/.local/share/virtualenvs/lucy-web-CVxkrCFK/lib/python3.7/site-packages/factory/base.py in _generate(cls, strategy, params)
498
499 step = builder.StepBuilder(cls._meta, params, strategy)
--> 500 return step.build()
501
502 @classmethod
~/.local/share/virtualenvs/lucy-web-CVxkrCFK/lib/python3.7/site-packages/factory/builder.py in build(self, parent_step, force_sequence)
277 step=step,
278 args=args,
--> 279 kwargs=kwargs,
280 )
281
~/.local/share/virtualenvs/lucy-web-CVxkrCFK/lib/python3.7/site-packages/factory/base.py in instantiate(self, step, args, kwargs)
312 return self.factory._build(model, *args, **kwargs)
313 elif step.builder.strategy == enums.CREATE_STRATEGY:
--> 314 return self.factory._create(model, *args, **kwargs)
315 else:
316 assert step.builder.strategy == enums.STUB_STRATEGY
~/Documents/Dev/lucy2/lucy-web/lucy_web/test_factories/user_factory.py in _create(cls, model_class, *args, **kwargs)
48 manager = cls._get_manager(model_class)
49 # The default would use ``manager.create(*args, **kwargs)``
---> 50 return manager.create_user(*args, **kwargs)
~/.local/share/virtualenvs/lucy-web-CVxkrCFK/lib/python3.7/site-packages/django/contrib/auth/models.py in create_user(self, username, email, password, **extra_fields)
148 extra_fields.setdefault('is_staff', False)
149 extra_fields.setdefault('is_superuser', False)
--> 150 return self._create_user(username, email, password, **extra_fields)
151
152 def create_superuser(self, username, email, password, **extra_fields):
~/.local/share/virtualenvs/lucy-web-CVxkrCFK/lib/python3.7/site-packages/django/contrib/auth/models.py in _create_user(self, username, email, password, **extra_fields)
142 user = self.model(username=username, email=email, **extra_fields)
143 user.set_password(password)
--> 144 user.save(using=self._db)
145 return user
146
~/.local/share/virtualenvs/lucy-web-CVxkrCFK/lib/python3.7/site-packages/django/contrib/auth/base_user.py in save(self, *args, **kwargs)
71
72 def save(self, *args, **kwargs):
---> 73 super().save(*args, **kwargs)
74 if self._password is not None:
75 password_validation.password_changed(self._password, self)
~/.local/share/virtualenvs/lucy-web-CVxkrCFK/lib/python3.7/site-packages/django/db/models/base.py in save(self, force_insert, force_update, using, update_fields)
727
728 self.save_base(using=using, force_insert=force_insert,
--> 729 force_update=force_update, update_fields=update_fields)
730 save.alters_data = True
731
~/.local/share/virtualenvs/lucy-web-CVxkrCFK/lib/python3.7/site-packages/django/db/models/base.py in save_base(self, raw, force_insert, force_update, using, update_fields)
767 post_save.send(
768 sender=origin, instance=self, created=(not updated),
--> 769 update_fields=update_fields, raw=raw, using=using,
770 )
771
~/.local/share/virtualenvs/lucy-web-CVxkrCFK/lib/python3.7/site-packages/django/dispatch/dispatcher.py in send(self, sender, **named)
176 return [
177 (receiver, receiver(signal=self, sender=sender, **named))
--> 178 for receiver in self._live_receivers(sender)
179 ]
180
~/.local/share/virtualenvs/lucy-web-CVxkrCFK/lib/python3.7/site-packages/django/dispatch/dispatcher.py in <listcomp>(.0)
176 return [
177 (receiver, receiver(signal=self, sender=sender, **named))
--> 178 for receiver in self._live_receivers(sender)
179 ]
180
~/.local/share/virtualenvs/lucy-web-CVxkrCFK/lib/python3.7/site-packages/auditlog/receivers.py in log_create(sender, instance, created, **kwargs)
14 """
15 if created:
---> 16 changes = model_instance_diff(None, instance)
17
18 log_entry = LogEntry.objects.log_create(
~/.local/share/virtualenvs/lucy-web-CVxkrCFK/lib/python3.7/site-packages/auditlog/diff.py in model_instance_diff(old, new)
133 for field in fields:
134 old_value = get_field_value(old, field)
--> 135 new_value = get_field_value(new, field)
136
137 if old_value != new_value:
~/.local/share/virtualenvs/lucy-web-CVxkrCFK/lib/python3.7/site-packages/auditlog/diff.py in get_field_value(obj, field)
76 else:
77 try:
---> 78 value = smart_text(getattr(obj, field.name, None))
79 except ObjectDoesNotExist:
80 value = field.default if field.default is not NOT_PROVIDED else None
~/Documents/Dev/lucy2/lucy-web/lucy_web/models/user.py in user__getattr__(self, attr)
86 In accordance with PEP 562, we cannot name it '__getattr__' here as that refers to the module __getattr__ method.
87 """
---> 88 return getattr(self.user_profile, attr)
89 # if self.user_profile:
90 # return self.user_profile.__getattribute__(attr)
... last 1 frames repeated, from the frame below ...
~/Documents/Dev/lucy2/lucy-web/lucy_web/models/user.py in user__getattr__(self, attr)
86 In accordance with PEP 562, we cannot name it '__getattr__' here as that refers to the module __getattr__ method.
87 """
---> 88 return getattr(self.user_profile, attr)
89 # if self.user_profile:
90 # return self.user_profile.__getattribute__(attr)
RecursionError: maximum recursion depth exceeded
我有点困惑为什么只有 UserFactory
会导致此错误,而“正常”属性查找似乎工作正常。关于如何解决此问题的任何想法?
最佳答案
这似乎与 factory_boy 无关:对于您的工厂,代码严格等同于:
user = User.objects.create_user()
profile = Profile.objects.create(user=user)
但是,从您的堆栈跟踪来看,您似乎已经安装了一个信号处理程序并将其连接到您的 post_save()
信号(在 auditlog/receivers.py
中)。
该信号处理程序似乎正在计算更新字段的列表;并因此尝试访问 User
对象的某些字段。但是,由于 Profile
尚未创建,因此对自定义 __getattr__
的调用失败。
解决此问题的正确方法是更改您的 user__getattr__
以在尝试读取它之前正确检查是否定义了 self.user_profile
;以下是适用于您的情况的代码示例:
def user__getattr__(user, attr):
try:
profile = user.user_profile
except ObjectDoesNotExist: # Generated by Django if the lookup fails
raise
return getattr(profile, attr)
注意:虽然您也可以使用 factory_boy 助手“静音”信号,但这只会隐藏问题:从数据库的角度来看,不能保证 UserProfile
存在于给定的 User
对象——您的代码应该准备好处理这种情况。
关于python - 使用组合模式会导致 Django Factory Boy 的无限递归?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51622768/
我有 3 个列表项,每 3 秒向上旋转一次。我正在使用 transformY 属性来做这件事。问题是,当它到达最后一个元素时,它会循环返回,从而产生重新开始的效果。 如何通过在最后一项之后继续向上旋转
我如何制作一个处理旋转的无限/重复世界,就像在这个游戏中一样: http://bloodfromastone.co.uk/retaliation.html 我通过具有这样的层次结构对我的旋转移动世界进
这个问题已经有答案了: Using explicitly numbered repetition instead of question mark, star and plus (4 个回答) 已关闭
程序说明: I have this program of mine which is intended to read every word from a file (large one) and t
while 循环应该比较这两个对象的 ibsn。正在比较的对象: list[0] = new ReadingMatter ("Words and Stuff", "9-082-1090-1");
已关闭。这个问题是 not reproducible or was caused by typos 。目前不接受答案。 这个问题是由拼写错误或无法再重现的问题引起的。虽然类似的问题可能是 on-top
我完全被屏蔽了。我尝试修改 C 中的“警报”信号,以便在秒数到期时读取一个简单的变量。我的代码如下: 在主要部分: int semnal; signal(SIGALRM, alarmHandle
我正在接受多行信息(字符串,直到我稍后解析它们)。例如: 1 5 0 2 9 6 2 9 1 我编写这段代码来分隔行,因为我将不得不以某种方式操作每一行。 Scanner scan = new Sca
我不熟悉 jQuery,并且我有多余的 jQuery 调用,我想将它们放入循环中。 $('.class1').on('click', function () { ... $('.class2').on
我有一个树结构,其中每个节点都有 5 个子节点,并且不允许超过 5 个。我希望以广度优先搜索的方式遍历这棵树。 现在我想使用广度优先搜索方式从选定的父节点计算空节点。 例如 如果给定的父节点为 1,则
目标/动机 我想写一个服务,它应该一直运行。但是当服务已经运行时,应该不可能再次启动该服务。 用例 用户 X 打开页面 myService.php 并通过单击页面上的按钮启动服务。之后关闭浏览器。一段
我正在尝试编译 shogun 工具箱,但遇到了这个错误 C:/shogun-3.0.0/shogun-3.0.0/src/shogun/../shogun/mathematics/Math.h
需要学校的 JavaScript 作业帮助,但不知道该怎么做,希望得到一些提示? 我们应该创建一个 6 面掷骰子程序,用户可以选择应该掷多少个骰子,最少 1 个和最多 5 个骰子。 所用骰子数量的总和
我在无限 ScrollView 中有 5 张图片。 因此,为了使 scrollView 无限/循环,我将图像定位如下: 5 1 2 3 4 5 1含义:最后一张图片第一张图片第二张图片.....最后一
我正在使用 ExTwitter库,并希望能够偶尔终止对流式 API 的调用以更改参数。 我当前的代码看起来像这样: for tweet #finished end 关于elixir - 如何中断(无
我想每 3 秒更改一次 div 的背景。这需要循环,因此一旦最后一个背景图像显示,它就会循环回到第一个背景图像,依此类推。我在这样做时遇到了麻烦。 我之前发过一篇文章,内容非常模糊,没有得到帮助。
我在做this教程,无法让我的页面正确加载。我不断在控制台中收到错误:[$rootScope:infdig]。 我对 Angular 很陌生,但从我读到的内容来看,我在某个地方有一个无限循环。我预计它
所以我试图创建一个无限的 asyncIterator/生成器。该代码应该为“for wait of”循环生成“Hello”和“Hi”,然后永远等待下一个值。问题是它不等待第三个值,也不在循环后打印 2
下图显示了我如何在 HTML5/JS 中制作无限背景滚动。我的连续背景由 X block Canvas 组成。我将在到达下一个 Canvas 之前立即渲染它,并释放上一个 Canvas。这里的问题是动
作为一个业余项目,我正在研究一些自制的素数生成问题,尝试编写一些不同的实现作为自学 C 和 C++ 的方法。当然,生成低素数的最快方法是已经拥有它们,所以我想着手建立一个硬盘素数列表数据文件。我想编写
我是一名优秀的程序员,十分优秀!