我有一个Django模型,有一个开始和结束日期。 结束日期可以为空,如果模型处于活动状态,则将其视为正在进行的 。在Django的自定义验证管理员休息日期时间部件
模型的每个实例都有一个由动态列表生成的字段foo。 Foo在实例中并不唯一,但具有相同foo字段的两个实例不能同时处于活动状态。
我正在使用的数据库是PostgreSQL,并且afaik无法在数据库级别实施。然后我选择在管理员层面执行此操作。当添加我的模型的新实例时,我想验证此时没有冲突的实例并引发验证错误。当我要在本地测试时,日期时间小部件完全不显示,只有文本框。
我的问题是这是最好的方式来实现我想要的东西,如果是的话为什么是datetime部件丢失,我该如何取回它?
代码片段:
class MyModelAdmin(admin.ModelAdmin):
list_display = ['name',
'foo',
'active',
'created',
'started',
'ended']
list_editable = ['name',
'active',
'ended']
def formfield_for_dbfield(self, db_field, *args, **kwargs):
if db_field.name.lower() == 'foo':
choices = sorted(some_dynamic_list)
db_field.choices = choices
return super().formfield_for_dbfield(db_field, *args, **kwargs)
def get_changelist_form(self, request, *args, **kwargs):
parent_form = super().get_changelist_form(request, *args, **kwargs)
return self.get_childform(parent_form)
def get_form(self, request, obj=None, *args, **kwargs):
parent_form = super().get_form(request, obj, *args, **kwargs)
return self.get_childform(parent_form, obj)
def get_childform(self, parent_form, obj=None):
class ChildForm(parent_form):
def clean(self, *args, **kwargs):
instance_dict = {}
for instance in MyModel.objects.filter(active=True):
foo = instance.config_type.lower()
if foo in instance_dict:
instance_dict[foo].append(instance)
else:
instance_dict[foo] = [instance, ]
if not obj:
for foo, instances in instance_dict.items():
for list_index, instance in enumerate(instances):
for other_instance in instances[list_index + 1:]:
if self.instances_conflict(instance, other_instance):
raise forms.ValidationError("Instances of the same type must not overlap!")
else:
for instance in instance_dict[obj.foo]:
if instance is not obj:
if self.instances_conflict(obj, instance):
raise forms.ValidationError("Instances of the same type must not overlap!")
return super().clean(*args, **kwargs)
def instances_conflict(self, instance_1, instance_2):
if instance_1.ended is None and instance_2.started > instance_1.started:
return True
if instance_2.ended is None and instance_1.started > instance_2.started:
return True
if instance_1.started > instance_2.started and instance_1.started < instance_2.ended:
return True
if instance_2.started > instance_1.started and instance_2.started < instance_1.ended:
return True
return False
return ChildForm
你试过我的回答吗? – e4c5
最后我为此使用了自定义表单,并在验证过程中发现了这种情况。约束是我还没有尝试过的东西。然而,我引入了一个预处理钩子来引发异常,如果这种方式超过了模型。理论上这意味着有人可以从psql控制台中解决这个问题。如果我实施限制条件,我会进一步更新。 – xgadam
如果在查询集上调用.update(),它也会中断,因为pre_save信号不会触发。 – e4c5