我在尝试保存Django User模型实例时遇到TransactionManagementError,并在其post_save信号中,我保存了一些将用户作为外键的模型.
在使用信号时,上下文和错误与此问题django TransactionManagementError非常相似
但是,在这种情况下,错误仅在单元测试时发生.
它在手动测试中运行良好,但单元测试失败.
有什么我想念的吗?
以下是代码段:
views.py
@csrf_exempt
def mobileRegister(request):
if request.method == 'GET':
response = {"error": "GET request not accepted!!"}
return HttpResponse(json.dumps(response), content_type="application/json",status=500)
elif request.method == 'POST':
postdata = json.loads(request.body)
try:
# Get POST data which is to be used to save the user
username = postdata.get('phone')
password = postdata.get('password')
email = postdata.get('email',"")
first_name = postdata.get('first_name',"")
last_name = postdata.get('last_name',"")
user = User(username=username, email=email,
first_name=first_name, last_name=last_name)
user._company = postdata.get('company',None)
user._country_code = postdata.get('country_code',"+91")
user.is_verified=True …Run Code Online (Sandbox Code Playgroud) 我在缠绕这个问题时遇到了麻烦.现在我有一些看起来像这样的模型:
def Review(models.Model)
...fields...
overall_score = models.FloatField(blank=True)
def Score(models.Model)
review = models.ForeignKey(Review)
question = models.TextField()
grade = models.IntegerField()
Run Code Online (Sandbox Code Playgroud)
评论有几个"分数",整体分数是分数的平均值.保存评论或分数时,我需要重新计算total_score平均值.现在我正在使用重写的保存方法.使用Django的信号调度程序会有什么好处吗?
基于我正在阅读的Django文档,似乎signals.py在app文件夹中是一个很好的开始,但我面临的问题是,当我创建信号时pre_save,我尝试从模型中导入类,它与import在我的模型中.
# models.py
from django.contrib.auth.models import User
from django.db import models
from django.utils.translation import gettext as _
from signals import *
class Comm_Queue(CommunicatorAbstract):
queue_statuses = (
('P', _('Pending')),
('S', _('Sent')),
('E', _('Error')),
('R', _('Rejected')),
)
status = models.CharField(max_length=10, db_index=True, default='P')
is_html = models.BooleanField(default=False)
language = models.CharField(max_length=6, choices=settings.LANGUAGES)
sender_email = models.EmailField()
recipient_email = models.EmailField()
subject = models.CharField(max_length=100)
content = models.TextField()
Run Code Online (Sandbox Code Playgroud)
# signals.py
from django.conf import settings
from django.db.models.signals import pre_save
from django.dispatch import receiver
from …Run Code Online (Sandbox Code Playgroud) 我有一个关于django的问题.
我在这里有ManyToMany模型
class Product(models.Model):
name = models.CharField(max_length=255)
price = models.DecimalField(default=0.0, max_digits=9, decimal_places=2)
stock = models.IntegerField(default=0)
def __unicode__(self):
return self.name
class Cart(models.Model):
customer = models.ForeignKey(Customer)
products = models.ManyToManyField(Product, through='TransactionDetail')
t_date = models.DateField(default=datetime.now())
t_sum = models.FloatField(default=0.0)
def __unicode__(self):
return str(self.id)
class TransactionDetail(models.Model):
product = models.ForeignKey(Product)
cart = models.ForeignKey(Cart)
amount = models.IntegerField(default=0)
Run Code Online (Sandbox Code Playgroud)
对于创建的1个购物车对象,我可以插入尽可能多的新TransactionDetail对象(产品和金额).我的问题是.我该如何实现触发器?我想要的是每当创建交易细节时,我希望产品库存的数量减去transactiondetail中的金额.
我读过有关post_save()但我不确定如何实现它.也许这样的事情
when:post_save(TransactionDetail,Cart)#Cart对象,其中TransactionDetail.cart = Cart.id
post_save(TransactionDetail,
Cart) #Cart object where TransactionDetail.cart= Cart.id
Cart.stock -= TransactionDetail.amount
Run Code Online (Sandbox Code Playgroud) Django模型通常可以非常充分地处理ON DELETE CASCADE行为(以适用于本机不支持它的数据库的方式).
但是,我在努力发现在不适合的情况下覆盖此行为的最佳方法是什么,例如在以下场景中:
ON DELETE RESTRICT(即如果有子记录,则阻止删除对象)
ON DELETE SET NULL(即不删除子记录,但将其父键设置为NULL而不是断开关系)
删除记录时更新其他相关数据(例如删除上传的图像文件)
以下是我所知道的实现这些目标的潜在方法:
覆盖模型的delete()方法.虽然这种方法有效,但是当通过a删除记录时,它会被回避QuerySet.此外,delete()必须重写每个模型,以确保Django的代码永远不会被调用,super()并且无法调用,因为它可能使用a QuerySet来删除子对象.
使用信号.这似乎是理想的,因为在直接删除模型或通过QuerySet删除时会调用它们.但是,不可能阻止删除子对象,因此无法实现ON CASCADE RESTRICT或SET NULL.
使用正确处理此问题的数据库引擎(在这种情况下Django会做什么?)
等到Django支持它(直到那时还有bug ...)
似乎第一种选择是唯一可行的选择,但它很难看,用洗澡水将婴儿扔出去,并且当添加新的模型/关系时可能会遗漏某些东西.
我错过了什么吗?有什么建议?
我有一个django模型,我需要在保存之前比较字段的新旧值.
我已经尝试了save()继承和pre_save信号.它被正确触发,但我找不到实际更改字段的列表,无法比较新旧值.有一种方法?我需要它来优化预先行动.
谢谢!
我需要对Django中新创建的对象进行一些后台后处理.此后处理应仅在新对象上运行,而不是刚刚更新的对象.
我知道在pre_save中我可以检查对象是否有id,如果没有则那么它是一个新对象.但问题是在后处理中我需要访问id(这样我就可以将结果保存回数据库).
我怎么能以干净的方式做到这一点?
在我的应用程序中,我想在新用户注册时在某些表中创建条目.例如,我想创建一个userprofile,然后引用他们的公司和其他一些记录.我用post_save信号实现了这个:
def callback_create_profile(sender, **kwargs):
# check if we are creating a new User
if kwargs.get('created', True):
user = kwargs.get('instance')
company = Company.objects.create(name="My Company")
employee = Employee.objects.create(company=company, name_first=user.first_name, name_last=user.last_name)
profile = UserProfile.objects.create(user=user, employee=employee, partner=partner)
# Register the callback
post_save.connect(callback_create_profile, sender=User, dispatch_uid="core.models")
Run Code Online (Sandbox Code Playgroud)
运行时效果很好.我可以使用admin创建一个新用户,其他三个表也可以获得合理的条目.(除此之外,员工因为user.first_name和user.last_name在保存时未在管理员表单中填写.我仍然不明白为什么这样做)
当我运行我的测试套件时出现问题.在此之前,我创建了一堆灯具来在表格中创建这些条目.现在我收到一条错误,指出:
IntegrityError: duplicate key value violates unique constraint "core_userprofile_user_id_key"
Run Code Online (Sandbox Code Playgroud)
我想这是因为我已经在id为"1"的灯具中创建了公司,员工和个人资料记录,现在post_save信号正在尝试重新创建它.
我的问题是:我可以在运行灯具时禁用此post_save信号吗?我可以检测到我作为测试套件的一部分运行而不是创建这些记录吗?我现在应该从灯具中删除这些记录吗(虽然信号只设置默认值而不是我想要测试的值)?为什么夹具加载代码不会覆盖创建的记录?
人们如何做到这一点?
我有一个通过装饰器连接的signal_handler,这个非常简单:
@receiver(post_save, sender=User,
dispatch_uid='myfile.signal_handler_post_save_user')
def signal_handler_post_save_user(sender, *args, **kwargs):
# do stuff
Run Code Online (Sandbox Code Playgroud)
我想做的是在测试中使用模拟库http://www.voidspace.org.uk/python/mock/进行模拟,以检查django调用它的次数.我的代码目前是这样的:
def test_cache():
with mock.patch('myapp.myfile.signal_handler_post_save_user') as mocked_handler:
# do stuff that will call the post_save of User
self.assert_equal(mocked_handler.call_count, 1)
Run Code Online (Sandbox Code Playgroud)
这里的问题是即使被模拟也会调用原始的信号处理程序,这很可能是因为@receiver装饰器正在某处存储信号处理程序的副本,所以我在嘲笑错误的代码.
所以问题是:如何模拟我的信号处理程序以使我的测试工作?
请注意,如果我将信号处理程序更改为:
def _support_function(*args, **kwargs):
# do stuff
@receiver(post_save, sender=User,
dispatch_uid='myfile.signal_handler_post_save_user')
def signal_handler_post_save_user(sender, *args, **kwargs):
_support_function(*args, **kwargs)
Run Code Online (Sandbox Code Playgroud)
而我嘲笑_support_function,一切都按预期工作.
我在Django中有一些模型继承级别:
class WorkAttachment(models.Model):
""" Abstract class that holds all fields that are required in each attachment """
work = models.ForeignKey(Work)
added = models.DateTimeField(default=datetime.datetime.now)
views = models.IntegerField(default=0)
class Meta:
abstract = True
class WorkAttachmentFileBased(WorkAttachment):
""" Another base class, but for file based attachments """
description = models.CharField(max_length=500, blank=True)
size = models.IntegerField(verbose_name=_('size in bytes'))
class Meta:
abstract = True
class WorkAttachmentPicture(WorkAttachmentFileBased):
""" Picture attached to work """
image = models.ImageField(upload_to='works/images', width_field='width', height_field='height')
width = models.IntegerField()
height = models.IntegerField()
Run Code Online (Sandbox Code Playgroud)
有许多不同的模型继承自WorkAttachmentFileBased和WorkAttachment …