[英]Procfile for Heroku not working properly - Django using Waitress
[英]Using Validators in Django not working properly
我最近了解了验证器及其工作原理,但我正在尝试向我的博客项目添加一个函数,以便在使用坏词时引发错误。 我在 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(),并在更改视图中显示任何错误; 当一个字段被 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
文件 test.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'...
验证器仅在您使用ModelForm
时运行。 如果您直接调用comment.save()
,验证器将不会运行。 链接到文档
因此,您需要使用ModelForm
验证字段,或者您可以添加pre_save
信号并在那里运行验证(您需要手动调用该方法,或使用full_clean
运行验证)。 就像是:
from django.db.models.signals import pre_save
def validate_model(sender, instance, **kwargs):
instance.full_clean()
pre_save.connect(validate_model, dispatch_uid='validate_models')
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.