Learning Django and have some problem. I created a function to change user review, but when I click on the save button, I have error: "Select a valid choice. 2 is not one of the available choices.".
models.py
class ProductReview(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
product = models.ForeignKey(Product, on_delete=models.CASCADE)
review_text = models.TextField()
review_rating = models.CharField(choices=RATING, max_length=150)
def get_review_rating(self):
return self.review_rating
class UserAddressBook(models.Model):
user = models.ForeignKey(User,on_delete=models.CASCADE)
mobile = models.CharField(max_length=12, null=True)
address = models.TextField()
status = models.BooleanField(default=False)
views.py
def my_reviews(request):
reviews = ProductReview.objects.filter(user=request.user).order_by('-id')
return render(request, 'user/reviews.html', {'reviews':reviews})
def save_review(request, pid):
product = Product.objects.get(pk=pid)
user = request.user
review = ProductReview.objects.create(
user=user,
product=product,
review_text=request.POST['review_text'],
review_rating=request.POST['review_rating'],
)
data = {
'user': user.username,
'review_text': request.POST['review_text'],
'review_rating': request.POST['review_rating'],
}
avg_reviews = ProductReview.objects.filter(product=product).aggregate(avg_rating=Avg('review_rating'))
return JsonResponse({'bool': True, 'data': data, 'avg_reviews': avg_reviews})
def update_review(request, id):
review = ProductReview.objects.get(pk=id)
if request.method=='POST':
form = ReviewAdd(request.POST,instance=review)
if form.is_valid():
saveForm = form.save(commit=False)
saveForm.user=request.user
saveForm.save()
return redirect('/my-reviews')
else:
form=ReviewAdd(instance=review)
return render(request, 'user/update-review.html', {'form':form})
def my_addressbook(request):
addbook = UserAddressBook.objects.filter(user=request.user).order_by('-id')
return render(request, 'user/addressbook.html', {'addbook':addbook})
def save_address(request):
msg = None
if request.method=='POST':
form=AddressBookForm(request.POST)
if form.is_valid():
saveForm = form.save(commit=False)
saveForm.user = request.user
if 'status' in request.POST:
UserAddressBook.objects.update(status=False)
saveForm.save()
msg='Address changed'
return redirect('/my-addressbook')
form=AddressBookForm
return render(request, 'user/add-address.html', {'form':form, 'msg':msg})
def activate_address(request):
a_id = str(request.GET['id'])
UserAddressBook.objects.update(status=False)
UserAddressBook.objects.filter(id=a_id).update(status=True)
return JsonResponse({'bool':True})
def delete_address(request):
a_id = str(request.GET['id'])
UserAddressBook.objects.filter(id=a_id).delete()
return JsonResponse({'bool': True})
def update_address(request,id):
address = UserAddressBook.objects.get(pk=id)
msg=None
if request.method=='POST':
form = AddressBookForm(request.POST,instance=address)
if form.is_valid():
saveForm = form.save(commit=False)
saveForm.user=request.user
if 'status' in request.POST:
UserAddressBook.objects.update(status=False)
saveForm.save()
msg = 'Address changed'
return redirect('/my-addressbook')
form=AddressBookForm(instance=address)
return render(request, 'user/update-address.html', {'form':form, 'msg':msg})
urls.py
from django.urls import path, include
from . import views
from django.conf import settings
from django.conf.urls.static import static
urlpatterns=[
path('', views.home, name='home'),
path('my-reviews',views.my_reviews, name='my-reviews'),
path('save-review/<int:pid>', views.save_review, name='save_review'),
path('update-review/<int:id>',views.update_review, name='update-review'),
path('my-addressbook',views.my_addressbook, name='my-addressbook'),
path('add-address', views.save_address, name='add_address'),
path('update-address/<int:id>',views.update_address, name='update-address'),
path('delete-address', views.delete_address, name='delete-address'),
]
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
review.html
{% extends 'base.html' %}
{% load static %}
{% block content %}
<main class="container my-4">
<h3 class="my-4 border-bottom pb-1">Reviews</h3>
<div class="row">
<div class="col-md-3">
{% include 'user/user-sidebar.html' %}
</div>
<div class="col-md-9">
<div class="table-responsive">
<table class="table-bordered table">
<thead>
<tr>
<th>Title</th>
<th>Image</th>
<th>Price</th>
<th>Review text</th>
<th>Review rating</th>
</tr>
</thead>
<tbody>
{% for review in reviews %}
<tr>
<td><a href="/product/{{review.product.id}}">{{review.product.title}}</a></td>
<td>
<img width="100" src="/media/{{review.product.image}}" alt="{{review.product.title}}">
</td>
<td>{{review.product.price}}</td>
<td>
<a href="{% url 'update-review' review.id %}" class="float-right"><i class="fa fa-edit"></i></a>
{{review.review_text}}
</td>
<td>{{review.review_rating}}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</main>
{% endblock %}
update-review.html
{% extends 'base.html' %}
{% load static %}
{% block content %}
<main class="container my-4">
<h3 class="my-4 border-bottom pb-1">Change review</h3>
<div class="row">
<div class="col-md-3">
{% include 'user/user-sidebar.html' %}
</div>
<div class="col-md-9">
{% if msg %}
<p class="text-success">{{msg}}</p>
{% endif %}
<table class="table table-bordered">
<form method="post">
{% csrf_token %}
{{form.as_table}}
<tr>
<td colspan="2">
<input type="submit" value="Save" class="btn btn-primary" />
</td>
</tr>
</form>
</table>
</div>
</div>
</main>
{% endblock %}
I followed the creation algorithm from the tutorial to update the address book. Changing the address book works. Maybe I’m missing something, but I’ve been reviewing the code for several hours now and can’t find an error.
2
Answers
In the end, the problem is small. I just changed string in models.py
review_rating = models.CharField(choices=RATING, max_length=150)
to
review_rating = models.IntegerField(choices=RATING)
.I do not know why, but the rating through .CharField is not accepted, at the stage of update. At the create review with raiting everything worked.
Thanks "AMG" for the advice.
My bet is you are getting an error on your form, but since you overwrite the form with the instance, instead of showing the form with the errors, you aren’t seeing the error.
Alter the
update_review
function to have an else – something like: