Как автоматически обновить поле в зависимости от пользователя, который изменил его в Django? - PullRequest
1 голос
/ 21 января 2020

Контекст:

В части блога может публиковать сообщения любой зарегистрированный пользователь, но все сообщения, сделанные не из учетных записей суперпользователя, должны быть одобрены администратором на странице администратора, где я также зарегистрировал модель. , Это работает так, как задумано.

Мой вопрос:

Как я могу сделать так, чтобы сообщение в блоге обновлялось суперпользователем (неважно, какие изменения, например: когда администратор открывает одно сообщение и добавляет дополнительный текст в текст сообщения или удаляет некоторую часть текста, потому что он кажется вредоносным или фальшивым), что он автоматически утверждается (поле утвержденное получает значение ИСТИНА)? Я уже думал о добавлении еще одного поля в модель с именем change_by, и оно изначально имеет значение null.

Код:

blog / 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})

blog / 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)

blog / 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

Буду признателен за любую помощь / предложения, которые у вас есть! Спасибо

1 Ответ

2 голосов
/ 21 января 2020

В вашем классе 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 Истиной, только если пользователь является суперпользователем, в противном случае он будет установлен в Ложь.

...