我被要求添加一些逻辑来建模唯一性。每个付款必须填写 transaction_id 或 payment_id。每个付款由 (transaction_id, operation, payment_created_date) 或 (payment_id, operation, payment_created_date) 标识。在数据库级别这工作正常。两次插入具有相同 transaction_id、操作、payment_created_date 的 Payment 会导致违反唯一约束。对于这个模型,我创建了管理页面。但是插入与管理页面相同的行会导致IntegrityError at /admin/finance/payment/add/ duplicate key value violates unique constraint "unique_finance_payment_without_payment_id" DETAIL: Key (transaction_id, operation, payment_created_date)=(dasdasd, Refund, 2021-10-04) already exists.而不是简单的用户友好管理错误Please correct the error below. Payment with this Transaction id, Operation and Payment created date already exists。如何让 Django 管理员捕获此 IntegrityError 并以管理员形式显示?
这是我的models.py
class ReportName(DiModel):
name = CharField(
max_length=50,
blank=False,
null=False)
def __str__(self):
return self.name
class Payment(DiModel):
class Meta:
unique_together = ('transaction_id', 'payment_id', 'operation', 'payment_created_date')
constraints=[UniqueConstraint(fields=['transaction_id', 'operation', 'payment_created_date'],
condition=Q(payment_id=None),
name='unique_finance_payment_without_payment_id'),
UniqueConstraint(fields=['payment_id', 'operation', 'payment_created_date'],
condition=Q(transaction_id=None),
name='unique_finance_payment_without_transaction_id'),]
OPERATION_TYPE = [
('Refund', 'Refund'),
('Charge', 'Charge'),
]
CURRENCY_CODE = [
('EUR', 'EUR'),
('RUB', 'RUB'),
('USD', 'USD'),
('GBP', 'GBP'),
('AUD', 'AUD'),
('PLN', 'PLN'),
('SGD', 'SGD'),
('MYR', 'MYR'),
('RON', 'RON'),
('ZAR', 'ZAR'),
]
report_name = ForeignKey(ReportName,
on_delete=models.PROTECT,
blank=False,
null=False,
help_text="Processor and report type")
operation = CharField(max_length=6,
choices=OPERATION_TYPE,
blank=False,
null=False,
default=OPERATION_TYPE[0][0],
help_text='Payment operation type')
payment_created_date = DateField(blank=False,
null=False,
default=timezone.now)
amount = DecimalField(blank=True,
null=True,
max_digits=10,
decimal_places=2,
help_text='Payment amount')
commission = DecimalField(blank=False,
null=False,
max_digits=10,
decimal_places=2,
help_text='Transaction fee')
currency = CharField(max_length=3,
choices=CURRENCY_CODE,
blank=False,
null=False,
default=CURRENCY_CODE[0][0],
help_text='Amount and commission currency code')
transaction_id = CharField(max_length=32,
blank=True,
null=True,
help_text='Payota transaction id')
payment_id = IntegerField(blank=True,
null=True,
help_text='Payota payment id')
author_user = models.ForeignKey(User,
on_delete=models.PROTECT,
null=True,
related_name='finance_author_user')
def __str__(self):
return f"{self.report_name} {self.operation} {self.created_at}"
这是我的 admin.py
class PaymentForm(forms.ModelForm):
class Meta:
fields = (
'report_name',
'operation',
'payment_created_date',
'amount',
'commission',
'currency',
'transaction_id',
'payment_id',
)
@admin.register(Payment)
class PaymentAdmin(ImportExportMixin, admin.ModelAdmin):
form = PaymentForm
list_display = [
'report_name',
'operation',
'payment_created_date',
'amount',
'commission',
'currency',
'transaction_id',
'payment_id',
]
list_filter = (
'report_name',
'operation',
('payment_created_date', DateRangeFilter),
)
search_fields = ['report_name__name', 'operation']
resource_class = PaymentResource
class Meta:
model = Payment