首页 > 解决方案 > 如何根据在 Django 中更改字段的用户自动更新字段?

问题描述

语境:

在页面的博客部分,任何注册用户都可以发布,但所有来自非超级用户帐户的帖子都必须在我注册模型的管理页面上得到管理员的批准。这按预期工作。

我的问题:

我怎样才能做到这一点,如果博客帖子被超级用户更新(不管什么样的变化,例如:当管理员打开一个帖子并在帖子正文中添加进一步的文本时,或删除文本的某些部分,因为它看起来是恶意的或伪造的),它被自动批准(批准的字段然后设置为 TRUE)?我已经考虑在模型中添加一个名为 changed_by 的进一步字段,并使其最初为 null。

代码:

博客/models.py

from django.db import models
from django.utils import timezone
from django.contrib.auth.models import User
from django.urls import reverse


class BlogPost(models.Model):
    title = models.CharField(max_length=100)
    content = models.TextField()
    date_posted = models.DateTimeField(default=timezone.now)
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    approved = models.BooleanField(default=False)
    changed_by = models.ForeignKey(User, default=None) # I am planning to use this but how?

    def __str__(self):
        return self.title

    def get_absolute_url(self):
        return reverse('blogPost-detail', kwargs={'pk': self.pk})

博客/admin.py

from django.contrib import admin
from .models import BlogPost


def approve_multiple_posts(modeladmin, request, queryset):
    for blogPost in queryset:
        if blogPost.approved:
            blogPost.approved = False
        else:
            blogPost.approved = True
        blogPost.save()


approve_multiple_posts.short_description = 'Change approval status'


class PostAdmin(admin.ModelAdmin):
    list_display = ['title', 'author', 'date_posted', 'approved']
    actions = [approve_multiple_posts, ]


admin.site.register(BlogPost, PostAdmin)

博客/views.py

from django.shortcuts import render, get_object_or_404
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
from django.contrib.auth.models import User
from .models import BlogPost
from django.views.generic import (
    ListView,
    DetailView,
    CreateView,
    UpdateView,
    DeleteView
)


def blog(request):
    context = {
        'blogPosts': BlogPost.objects.all()
    }
    return render(request, 'blog/blog.html', context)


class PostListView(ListView):
    model = BlogPost
    template_name = 'blog/blog.html'
    context_object_name = 'blogPosts'
    ordering = ['-date_posted']
    paginate_by = 5

    def get_queryset(self):
        return BlogPost.objects.filter(approved=True).order_by('-date_posted')


class UserPostListView(ListView):
    model = BlogPost
    template_name = 'blog/user_blogPosts.html'
    context_object_name = 'blogPosts'
    paginate_by = 5

    def get_queryset(self):
        user = get_object_or_404(User, username=self.kwargs.get('username'))
        return BlogPost.objects.filter(author=user, approved=True).order_by('-date_posted')


class PostDetailView(DetailView):
    model = BlogPost


class PostCreateView(LoginRequiredMixin, CreateView):
    model = BlogPost
    fields = ['title', 'content']

    def form_valid(self, form):
        form.instance.author = self.request.user
        if self.request.user.is_superuser:
            form.instance.approved = True
        return super().form_valid(form)


class PostUpdateView(LoginRequiredMixin, UserPassesTestMixin, UpdateView):
    model = BlogPost
    fields = ['title', 'content']

    def form_valid(self, form):
        form.instance.author = self.request.user
        return super().form_valid(form)

    def test_func(self):
        blog_post = self.get_object()
        if self.request.user == blog_post.author:
            return True
        return False


class PostDeleteView(LoginRequiredMixin, UserPassesTestMixin, DeleteView):
    model = BlogPost
    success_url = '/blog'

    def test_func(self):
        blog_post = self.get_object()
        if self.request.user == blog_post.author:
            return True
        return False

如果您有任何帮助/建议,我将不胜感激!谢谢

标签: pythondjangodjango-modelsarchitecturedjango-views

解决方案


在您的PostAdmin课程中,您可以覆盖一个名为save_model( Django docs ) 的方法。尝试这样的事情:

class PostAdmin(admin.ModelAdmin):
    list_display = ['title', 'author', 'date_posted', 'approved']
    actions = [approve_multiple_posts, ]

    def save_model(self, request, obj, form, change):
        important_fields = ['title', 'content']  # modify save if these fields changed
        if any(x in important_fields for x in form.changed_data):
            obj.approved = request.user.is_superuser
        super().save_model(request, obj, form, change)

仅当用户是超级用户时才会approved设置为 True,否则将设置为 False。


推荐阅读