我有两个型号:
class User(models.Model):
name = models.CharField(max_length=32)
class Referral(models.Model):
referring_user = models.ForeignKey(User, related_name="referrals")
referred_user = models.ForeignKey(User, related_name="referrers")
percentage = models.PositiveIntegerField()
Run Code Online (Sandbox Code Playgroud)
这个想法是每个用户都有n推荐人,至少应该有一个推荐人.每个推荐人都有一个percentage值,当添加到其他推荐人时,应该加起来为100%.
因此,用户"Alice"可能有推荐人"Bob"(50%)和"Cynthia"(50%),而用户"Donald"可能有一个推荐人:"Erin"(100%).
我遇到的问题是验证.有没有办法(最好是与Django管理员一起使用的方式admin.TabularInline),我可以验证拒绝保存a User如果总和Refferrals != 100%?
理想情况下,我希望这发生在表单/管理员级别而不是覆盖User.save(),但此时我不知道从哪里开始.大多数Django的验证代码似乎都是原子的,并且多行验证不是我以前在Django中完成的.
在杰里·孟建议我查看该data属性而不是后cleaned_data,我开始四处admin.ModelAdmin寻找如何访问该方法。我发现get_form它似乎返回一个表单类,所以我重写了该方法来捕获返回的类,对其进行子类化,并.clean()在那里进行重写。
进入内部后,我循环遍历self.data,使用正则表达式查找相关字段,然后逐字进行数学计算。
import re
from django import forms
from django.contrib import admin
class UserAdmin(admin.ModelAdmin):
# ...
def get_form(self, request, obj=None, **kwargs):
parent = admin.ModelAdmin.get_form(self, request, obj=None, **kwargs)
class PercentageSummingForm(parent):
def clean(self):
cleaned_data = parent.clean(self)
total_percentage = 0
regex = re.compile(r"^referrers-(\d+)-percentage$")
for k, v in self.data.items():
match = re.match(regex, k)
if match:
try:
total_percentage += int(v)
except ValueError:
raise forms.ValidationError(
"Percentage values must be integers"
)
if not total_percentage == 100:
raise forms.ValidationError(
"Percentage values must add up to 100"
)
return cleaned_data
return PercentageSummingForm
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
559 次 |
| 最近记录: |