唯一约束失败 - 重定向视图?
Unique constraint failed - redirect view?
我设法将以下代码限制为每个餐厅 1 个用户评论,并且使用 class 元 "unique together"
效果很好
class UserReview(models.Model):
# Defining the possible grades
Grade_1 = 1
Grade_2 = 2
Grade_3 = 3
Grade_4 = 4
Grade_5 = 5
# All those grades will sit under Review_Grade to appear in choices
Review_Grade = (
(1, '1 - Not satisfied'),
(2, '2 - Almost satisfied'),
(3, '3 - Satisfied'),
(4, '4 - Very satisfied'),
(5, '5 - Exceptionally satisfied')
)
restaurant = models.ForeignKey(Restaurant, on_delete=models.CASCADE)
user_review_grade = models.IntegerField(default=None, choices=Review_Grade) # default=None pour eviter d'avoir un bouton vide sur ma template
user_review_comment = models.CharField(max_length=1500)
posted_by = models.ForeignKey(User, on_delete=models.DO_NOTHING)
class Meta:
unique_together = ['restaurant', 'posted_by']
我现在意识到我需要更新我的视图,以便此约束失败我被带到错误页面,但我找不到如何,任何指导将不胜感激
查看:
class Reviewing (LoginRequiredMixin, CreateView):
template_name = 'restaurants/reviewing.html'
form_class = UserReviewForm
# Get the initial information needed for the form to function: restaurant field
def get_initial(self, *args, **kwargs):
initial = super(Reviewing, self).get_initial(**kwargs)
initial['restaurant'] = self.kwargs['restaurant_id']
return initial
# Post the data into the DB
def post(self, request, restaurant_id, *args, **kwargs):
form = UserReviewForm(request.POST)
restaurant = get_object_or_404(Restaurant, pk=restaurant_id)
if form.is_valid():
review = form.save(commit=False)
form.instance.posted_by = self.request.user
print(review) # Print so I can see in cmd prompt that something posts as it should
review.save()
# this return below need reverse_lazy in order to be loaded once all the urls are loaded
return HttpResponseRedirect(reverse_lazy('restaurants:details', args=[restaurant.id]))
return render(request, 'restaurants/oops.html')
表格:
# Form for user reviews per restaurant
class UserReviewForm(forms.ModelForm):
class Meta:
model = UserReview
# restaurant = forms.ModelChoiceField(queryset=Restaurant.objects.filter(pk=id))
fields = [
'restaurant',
'user_review_grade',
'user_review_comment'
]
widgets = {
'restaurant': forms.HiddenInput,
'user_review_grade': forms.RadioSelect,
'user_review_comment': forms.Textarea
}
labels = {
'user_review_grade': 'Chose a satisfaction level:',
'user_review_comment': 'And write your comments:'
}
如果表单无效,您可以重定向到错误页面:
from django.db import IntegrityError
class Reviewing (LoginRequiredMixin, CreateView):
template_name = 'restaurants/reviewing.html'
form_class = UserReviewForm
# Get the initial information needed for the form to function: restaurant field
def get_initial(self, *args, **kwargs):
initial = super(Reviewing, self).get_initial(**kwargs)
initial['restaurant'] = self.kwargs['restaurant_id']
return initial
# Post the data into the DB
def post(self, request, restaurant_id, *args, **kwargs):
form = UserReviewForm(request.POST)
restaurant = get_object_or_404(Restaurant, pk=restaurant_id)
if form.is_valid():
review = form.save(commit=False)
form.instance.posted_by = self.request.user
print(review) # Print so I can see in cmd prompt that something posts as it should
try:
review.save()
except IntegrityError:
return redirect(<i>'name-of-some-view'</i>)
# this return below need reverse_lazy in order to be loaded once all the urls are loaded
return redirect('restaurants:details', restaurant.id)
return redirect(<i>'name-of-some-view'</i>)
话虽这么说,但在您看来,您太多了。 Django 的 CreateView
旨在为您删除大部分样板代码。
因此您可以将其实现为:
class Reviewing (LoginRequiredMixin, CreateView):
template_name = 'restaurants/reviewing.html'
form_class = UserReviewForm
# Get the initial information needed for the form to function: restaurant field
def get_initial(self, *args, **kwargs):
initial = super(Reviewing, self).get_initial(**kwargs)
initial['restaurant'] = self.kwargs['restaurant_id']
return initial
def form_valid(self, form):
form.instance = self.request.user
return super().form_valid(form)
def get_success_url(self, **kwargs):
return reverse('restaurants:details', args=[self.kwargs['restaurant_id']])
def form_invalid(self, form):
return redirect(<i>'name-of-some-view'</i>)
我设法将以下代码限制为每个餐厅 1 个用户评论,并且使用 class 元 "unique together"
效果很好class UserReview(models.Model):
# Defining the possible grades
Grade_1 = 1
Grade_2 = 2
Grade_3 = 3
Grade_4 = 4
Grade_5 = 5
# All those grades will sit under Review_Grade to appear in choices
Review_Grade = (
(1, '1 - Not satisfied'),
(2, '2 - Almost satisfied'),
(3, '3 - Satisfied'),
(4, '4 - Very satisfied'),
(5, '5 - Exceptionally satisfied')
)
restaurant = models.ForeignKey(Restaurant, on_delete=models.CASCADE)
user_review_grade = models.IntegerField(default=None, choices=Review_Grade) # default=None pour eviter d'avoir un bouton vide sur ma template
user_review_comment = models.CharField(max_length=1500)
posted_by = models.ForeignKey(User, on_delete=models.DO_NOTHING)
class Meta:
unique_together = ['restaurant', 'posted_by']
我现在意识到我需要更新我的视图,以便此约束失败我被带到错误页面,但我找不到如何,任何指导将不胜感激 查看:
class Reviewing (LoginRequiredMixin, CreateView):
template_name = 'restaurants/reviewing.html'
form_class = UserReviewForm
# Get the initial information needed for the form to function: restaurant field
def get_initial(self, *args, **kwargs):
initial = super(Reviewing, self).get_initial(**kwargs)
initial['restaurant'] = self.kwargs['restaurant_id']
return initial
# Post the data into the DB
def post(self, request, restaurant_id, *args, **kwargs):
form = UserReviewForm(request.POST)
restaurant = get_object_or_404(Restaurant, pk=restaurant_id)
if form.is_valid():
review = form.save(commit=False)
form.instance.posted_by = self.request.user
print(review) # Print so I can see in cmd prompt that something posts as it should
review.save()
# this return below need reverse_lazy in order to be loaded once all the urls are loaded
return HttpResponseRedirect(reverse_lazy('restaurants:details', args=[restaurant.id]))
return render(request, 'restaurants/oops.html')
表格:
# Form for user reviews per restaurant
class UserReviewForm(forms.ModelForm):
class Meta:
model = UserReview
# restaurant = forms.ModelChoiceField(queryset=Restaurant.objects.filter(pk=id))
fields = [
'restaurant',
'user_review_grade',
'user_review_comment'
]
widgets = {
'restaurant': forms.HiddenInput,
'user_review_grade': forms.RadioSelect,
'user_review_comment': forms.Textarea
}
labels = {
'user_review_grade': 'Chose a satisfaction level:',
'user_review_comment': 'And write your comments:'
}
如果表单无效,您可以重定向到错误页面:
from django.db import IntegrityError
class Reviewing (LoginRequiredMixin, CreateView):
template_name = 'restaurants/reviewing.html'
form_class = UserReviewForm
# Get the initial information needed for the form to function: restaurant field
def get_initial(self, *args, **kwargs):
initial = super(Reviewing, self).get_initial(**kwargs)
initial['restaurant'] = self.kwargs['restaurant_id']
return initial
# Post the data into the DB
def post(self, request, restaurant_id, *args, **kwargs):
form = UserReviewForm(request.POST)
restaurant = get_object_or_404(Restaurant, pk=restaurant_id)
if form.is_valid():
review = form.save(commit=False)
form.instance.posted_by = self.request.user
print(review) # Print so I can see in cmd prompt that something posts as it should
try:
review.save()
except IntegrityError:
return redirect(<i>'name-of-some-view'</i>)
# this return below need reverse_lazy in order to be loaded once all the urls are loaded
return redirect('restaurants:details', restaurant.id)
return redirect(<i>'name-of-some-view'</i>)
话虽这么说,但在您看来,您太多了。 Django 的 CreateView
旨在为您删除大部分样板代码。
因此您可以将其实现为:
class Reviewing (LoginRequiredMixin, CreateView):
template_name = 'restaurants/reviewing.html'
form_class = UserReviewForm
# Get the initial information needed for the form to function: restaurant field
def get_initial(self, *args, **kwargs):
initial = super(Reviewing, self).get_initial(**kwargs)
initial['restaurant'] = self.kwargs['restaurant_id']
return initial
def form_valid(self, form):
form.instance = self.request.user
return super().form_valid(form)
def get_success_url(self, **kwargs):
return reverse('restaurants:details', args=[self.kwargs['restaurant_id']])
def form_invalid(self, form):
return redirect(<i>'name-of-some-view'</i>)