我正在尝试使用unique_for_date选项来阻止在同一日期创建具有相同slug的多个帖子。但它似乎根本不起作用:我仍然可以从shell和管理仪表板创建具有相同slug的帖子。 ModelForm也是如此。 我的models.py:
class Post(models.Model):
STATUS_CHOICES = (
('draft', 'Draft'),
('published', 'Published'),
('suspended', 'Suspended'),
)
title = models.CharField(max_length=200)
slug = models.SlugField(max_length=200, unique_for_date='created')
status = models.CharField(max_length=15,
choices=STATUS_CHOICES,
default='draft')
content = models.TextField(max_length=200000, blank=True)
# dates
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
publish = models.DateTimeField(default=timezone.now)
我通过将auto_now_add=True
更改为default=timezone.now
找到了某种解决问题的方法,但它只在通过django admin创建对象时显示错误 - 从shell或表单创建对象时仍然没有错误。
更新:我知道使用auto_now_add设置editable = False会导致django跳过字段验证,但它无法解释为什么即使使用default=timezone.now
更新2 :由于某种原因,unique_for_date仅适用于django-admin仪表板表单(至少在我的情况下)。为了获得与其他表单相同的效果,我已经覆盖了模型的clean_fields方法(强制django验证唯一字段):
def clean_fields(self, exclude=None):
super().clean_fields(exclude=exclude)
self.validate_unique()
答案 0 :(得分:2)
我认为您created
为DateTimeField
,所以它也在考虑时间。尝试将其更改为DateField
答案 1 :(得分:1)
unique_for_date
约束在Django管理员表单级别强制执行,但不在数据库级别强制执行。如果你看一下文档,
这是在模型验证期间由Model.validate_unique()强制实施的,但不是在数据库级别强制执行。如果任何unique_for_date约束涉及不属于ModelForm的字段(例如,如果其中一个字段在exclude中列出或具有editable = False),Model.validate_unique()将跳过该特定约束的验证。
如果您需要强制执行数据库级别唯一约束,那么我可能会建议您在unique_together
类中添加Meta
约束。此外,如果您愿意,可能需要将created
字段更改为DateField()
。
答案 2 :(得分:1)
感谢您发布该问题,我遇到了完全相同的问题(奇怪的是,代码大致相同——我们是否遵循 same book?:))。已经三年了,这个问题已经有了一些变化,但你是否有机会使用 WSL 进行开发?
我也将 unique_for_date
设置为 slug 的参数,并且本地版本的管理界面按预期运行,即。 e.它不允许在同一日期出现两个相同的 slug。有趣的是,在 WSL 版本中,可以为任何给定日期创建多个相同的 slug,即使代码与 Windows 版本相同。
我在 WSL 版本的相同代码中遇到了另一个莫名其妙的错误(tl;dr: 本地版本再次按预期工作):我正在显示博客列表使用 django 的面包和黄油 HTML templates 以节略形式发布。单击列表条目的标题(使用 canonical url 中描述的 urlpattern path('articles/<int:year>/<int:month>/<slug:slug>/', views.article_detail)
的 the Django documentation)应该打开其未删节的详细视图,但是,尽管列表显示正确,详细视图的条目不能显示是因为系统找不到条目并抛出 404 错误。我正在传递 'published'
日期来构建规范网址;虽然可以使用 'published__year'
检索包含 slug 的帖子,但 'published__month'
和 'published__day'
都不会返回任何内容(当我保存测试条目时,日期格式正确)。同样,完全相同的代码在本地版本(即 WSL 之外)中完美运行。如果细节太紧凑,请随意纠缠我。
我的观察指向 WSL 本身(存在一些内存问题)或我在其中运行的数据库。很难说,但是你的问题有没有可能是类似的原因造成的?
我的代码有两个不同版本,一个在我的本地文件系统 (Windows) 中,另一个在 WSL 2(Linux 的 Windows 子系统,显然;Debian)中,因此能够比较两个系统的行为:我在本地和 WSL 中使用相同的代码(通过 github 传输)和要求。 G。 Django 3.1.6,以及相同的 DBMS(MySQL;在我的 WSL/Debian 中,无论是 MySQL 还是 MariaDB 都不是 100% 清楚,但后者旨在替代前者,所以我会如果这会导致我在这里描述的错误,我会感到惊讶)。我也在这两种环境中使用 Visual Studio 代码。
答案 3 :(得分:0)
摘自官方文档:https://docs.djangoproject.com/en/2.2/ref/models/fields/#unique-for-date
如果任何unique_for_date约束涉及不属于ModelForm的字段(例如,如果其中一个字段列在exclude中或具有editable = False),则Model.validate_unique()将跳过对该特定字段的验证约束。
问题可能出在“ 不是ModelForm一部分的字段将跳过对该特定约束的验证”。