在 Django 博客模型中实现保存 draft/publish 功能

implementing save draft/publish feature in django blog model

所以我用 Django 建立了一个非常基本的博客。我一直在努力添加一项新功能,允许我将新的 post 保存为草稿以便稍后发布,或者取消发布已经发布的 post。我是 Django/Python 的新手,所以我可能在这里犯了一个新手错误。

为此,我在 Post 模型中添加了两个字段。一个名为 publishedBooleanField 和一个名为 publish_dateDateTimeField。我只希望 publish_datepublish 设置为 True 且之前为 False 时进行更新。我采用的方法是重写 Post 模型的 save() 方法。在该方法中,我要么将 publish_date 设置为 None(如果 published 在表单上未选中)或者我我正在将 publish_date 设置为 timezone.now() (如果 published 在表单上被选中)。

这个方法没问题,虽然publish_date每次更新post都会更新,即使没有unpublished/republished .这不可能发生。我仍在学习视图、模型和表单之间的交互,因此非常感谢任何指导。

请查看所有相关代码,让我知道解决此问题的更好方法。感谢您的帮助!

models.py

class Post(models.Model):
    title = models.CharField(max_length=255)
    body = RichTextUploadingField(blank=True, null=True)
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    header_image = models.ImageField(upload_to="images/header_images/", default='images/header_images/default.jpg')
    slug = models.SlugField(max_length=255, blank=True, null=True)
    snippet = models.CharField(max_length=255)
    created_date = models.DateTimeField(auto_now_add=True)
    updated_date = models.DateTimeField(auto_now=True, blank=False, null=False)
    publish_date = models.DateTimeField(auto_now_add=False, blank=True, null=True)
    likes = models.ManyToManyField(User, related_name='blog_post', blank=True)
    published = models.BooleanField()

    def __str__(self):
        return self.title

    def get_absolute_url(self):
        return reverse('article-details', kwargs={"pk":self.pk,"slug":self.slug})

    def total_likes(self):
        return self.likes.count()

    def save(self, *args, **kwargs):
        if self.published == True:
            self.publish_date = timezone.now()
        else:
            self.publish_date = None
        super(FakePost, self).save(*args, **kwargs)

Forms.py

class ArticleNewForm(forms.ModelForm):
    class Meta:
        model = Post
        fields = (
            'title',
            'slug',
            'author',
            'header_image',
            'body',
            'snippet',
            'publish_date',
            'published',
        )

        widgets = {
            'title': forms.TextInput(),
            'author': forms.TextInput(attrs={'class':'form-control', 'value':'','id':'userfield','type':'hidden',}),
            'body': forms.Textarea(),
            'snippet': forms.Textarea(),
            'publish_date': DateTimeInput(attrs={'type': 'datetime-local'}),
        }

为避免 publish_date 每次更新 post 时都会更新,即使尚未 unpublished/republished 也应检查如果 self.published 的新值与之前的值发生了变化,如果他这样做了,请执行您的代码。

Django 本身没有给你一个简单的工具来检查值是否已经改变,所以你将不得不使用 this question.

的一些答案

您可以一直避免使用已发布的,并将发布日期设置为“发布”Post。

from django.utils import timezone
from django.utils.functional import cached_propery

class Post(models.Model):
    # ...
    publish_date = models.DateTimeField(blank=True, null=True, default=None)
    
    @cached_property
    def is_published(self):
        return self.publish_date <= timezone.now()
    
    def publish(self):
        self.publish_date = timezone.now()

检查是否在模板中发布:

{% if post.is_published %}
    <span>Published!</span>
{% endif %}

发表一篇post:

post = Post()
post.publish()
post.save()

所有已发布 posts 的查询集:

Post.objects.filter(publish_date__isnull=False).all()

相反,post尚未发布:

Post.objects.filter(publish_date__isnull=True).all()

在查询集中发布所有 post:

Post.objects.update(publish_date=timezone.now())

甚至,您可以实现未来的发布,例如3 天内:

Post.objects.update(publish_date=timezone.now() + timezone.timedelta(days=3))