python - 在 Django 中使用验证器无法正常工作

标签 python django

我最近了解了验证器及其工作原理,但我正在尝试向我的博客项目添加一个功能,以便在使用错误词时引发错误。 我在 txt 中有一个坏词列表,并将代码添加到 models.py 中,问题是由于某种我不确定的原因,没有任何东西被阻止。

这是models.py

class Post(models.Model):
       title = models.CharField(max_length=100, unique=True)
       ---------------other unrelated------------------------

def validate_comment_text(text):
    with open("badwords.txt") as f:
        censored_word = f.readlines()
    words = set(re.sub("[^\w]", " ", text).split())
    if any(censored_word in words for censored_word in CENSORED_WORDS):
        raise ValidationError(f"{censored_word} is censored!")

class Comment(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    post = models.ForeignKey(Post, on_delete=models.CASCADE)
    content = models.TextField(max_length=300, validators=[validate_comment_text])
    updated = models.DateTimeField(auto_now=True)
    created = models.DateTimeField(auto_now=True)

这里是 views.py:

class PostDetailView(DetailView):
    model = Post
    template_name = "blog/post_detail.html"  # <app>/<model>_<viewtype>.html

    def get_context_data(self, *args, **kwargs):
        context = super(PostDetailView, self).get_context_data()
        post = get_object_or_404(Post, slug=self.kwargs['slug'])
        comments = Comment.objects.filter(
            post=post).order_by('-id')
        total_likes = post.total_likes()
        liked = False
        if post.likes.filter(id=self.request.user.id).exists():
            liked = True

        if self.request.method == 'POST':
            comment_form = CommentForm(self.request.POST or None)
            if comment_form.is_valid():
                content = self.request.POST.get('content')
                comment_qs = None

                comment = Comment.objects.create(
                    post=post, user=self.request.user, content=content)
                comment.save()
                return HttpResponseRedirect("blog/post_detail.html")
        else:
            comment_form = CommentForm()

        context["comments"] = comments
        context["comment_form"] = comment_form
        context["total_likes"] = total_likes
        context["liked"] = liked
        return context

    def get(self, request, *args, **kwargs):
        res = super().get(request, *args, **kwargs)
        self.object.incrementViewCount()
        if self.request.is_ajax():
            context = self.get_context_data(self, *args, **kwargs)
            html = render_to_string('blog/comments.html', context, request=self.request)
            return JsonResponse({'form': html})
        return res

class PostCommentCreateView(LoginRequiredMixin, CreateView):
    model = Comment
    form_class = CommentForm

    def form_valid(self, form):
        post = get_object_or_404(Post, slug=self.kwargs['slug'])
        form.instance.user = self.request.user
        form.instance.post = post
        return super().form_valid(form)

这是我的试用版,但没有成功

def validate_comment_text(sender,text, instance, **kwargs):
    instance.full_clean()
    with open("badwords.txt") as f:
        CENSORED_WORDS = f.readlines()

    words = set(re.sub("[^\w]", " ", text).split())
    if any(censored_word in words for censored_word in CENSORED_WORDS):
        raise ValidationError(f"{censored_word} is censored!")

pre_save.connect(validate_comment_text, dispatch_uid='validate_comment_text')

我是新手,所以如果你能对答案提供一些解释,我将不胜感激,这样我就可以避免重复同样的错误。

最佳答案

我确信有很多方法可以处理这个问题,但我最终决定在我的所有 Django 项目中采用一种通用做法:

当模型需要验证时,我会覆盖 clean() 以在一个地方收集所有验证逻辑并提供适当的错误消息。

在clean()中,你可以访问所有模型字段,不需要返回任何东西;只需根据需要提出 ValidationErrors:

from django.db import models
from django.core.exceptions import ValidationError


class MyModel(models.Model):

    def clean(self):
         
        if (...something is wrong in "self.field1" ...) {
            raise ValidationError({'field1': "Please check field1"})
        }
        if (...something is wrong in "self.field2" ...) {
            raise ValidationError({'field2': "Please check field2"})
        }

        if (... something is globally wrong in the model ...) {
            raise ValidationError('Error message here')
        }

管理员已经从中受益,从 ModelAdmin.save_model() 调用 clean(), 并在更改 View 中显示任何错误;当一个字段被 ValidationError 寻址时, 相应的小部件将在表单中强调。

要在以编程方式保存模型时运行完全相同的验证,只需重写 save() 如下:

class MyModel(models.Model):

    def save(self, *args, **kwargs):
        self.full_clean()
        ...
        return super().save(*args, **kwargs)

证明:

文件模型.py

from django.db import models


class Model1(models.Model):

    def clean(self):
        print("Inside Model1.clean()")

    def save(self, *args, **kwargs):
        print('Enter Model1.save() ...')
        super().save(*args, **kwargs)
        print('Leave Model1.save() ...')
        return

class Model2(models.Model):

    def clean(self):
        print("Inside Model2.clean()")

    def save(self, *args, **kwargs):
        print('Enter Model2.save() ...')
        self.full_clean()
        super().save(*args, **kwargs)
        print('Leave Model2.save() ...')
        return

文件测试.py

from django.test import TestCase
from project.models import Model1
from project.models import Model2

class SillyTestCase(TestCase):

    def test_save_model1(self):
        model1 = Model1()
        model1.save()

    def test_save_model2(self):
        model2 = Model2()
        model2.save()

结果:

❯ python manage.py test
Creating test database for alias 'default'...
System check identified no issues (0 silenced).
Enter Model1.save() ...
Leave Model1.save() ...
.Enter Model2.save() ...
Inside Model2.clean()
Leave Model2.save() ...
.
----------------------------------------------------------------------
Ran 2 tests in 0.002s

OK
Destroying test database for alias 'default'...

关于python - 在 Django 中使用验证器无法正常工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64830056/

相关文章:

python - 使用具有多个返回值和有序字典的多处理

python - 反卷积维纳滤波器能否在不使图像模糊的情况下减少噪声?

Python:通过通配符获取内存缓存键值列表

python - html代码问题如何放入数据库

python - Codecademy 循环 8/19

python - 如何加速 PyMC 马尔可夫模型?

python - 在 python Bokeh 图中动态链接 Span 和 Slider

python - 从 Url 参数过滤 Django ModelViewSet 列表

python - Django REST Framework 过滤多个字段

python - 继承模型更新到其父模型