我有DateTimeField
并希望按月/年限制,即每月只有一个条目。
目前我使用了两个额外的字段(month
/ year
)和unique_together = ("month", "year")
,但肯定有更好的解决方案。
class someModel(models.Model):
datetime = models.DateTimeField(unique=True)
...
class Meta:
ordering = ['datetime']
答案 0 :(得分:4)
除了你现在正在做的方式之外,你不能真正“原生”地做到这一点,因为在定义模型时你正在定义数据库级验证,并说MySQL不支持带有YEAR的DATETIME字段+ MONTH唯一约束。
但是,您可以在该字段上添加自己的验证器,但这将需要额外的开销来保存/更新模型的实例。我以前自己遇到了日期时间/时间戳值的麻烦,通常年+月独特约束解决方案是最有效/透明的,即使它导致额外的存储(但这是最便宜的元素,对吗?)
但是,如果您决定使用单字段唯一约束,请参阅https://docs.djangoproject.com/en/dev/ref/validators/ - 您需要在字段中添加验证器,以检查是否存在具有该年份+月份组合的其他对象。请注意,这在大型系统上效率非常低,因为MySQL不支持DATETIME字段上的年/月索引 - 该值将通过完整表扫描中的函数传递并在之后进行过滤:(
答案 1 :(得分:1)
Field.unique_for_date会使某个字段值的实例唯一。 这将按月限制:
from django.core.exceptions import ValidationError
class SomeModel(models.Model):
# Set index to field
datetime = models.DateTimeField(db_index=True)
def save(self, *args, **kwargs):
# If new instance created
queryset = SomeModel.objects.filter(
datetime__startswith=self.datetime.strftime('%Y-%m-'))
# If instance changed
if self.id is not None:
queryset = queryset.exclude(id=self.id)
if queryset.exists():
raise ValidationError('Choose another date')
super(SomeModel, self).save(*args, **kwargs)