skip to Main Content

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


  1. Chosen as BEST ANSWER

    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.


  2. 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:

    def update_review(request, id):
        review = ProductReview.objects.get(pk=id)
        msg=None
        if request.method=='POST':
            form = ReviewAdd(request.POST,instance=review)
            if form.is_valid():
                saveForm = form.save(commit=False)
                saveForm.user=request.user
                saveForm.product=request.product
                saveForm.save()
                msg = 'Review changed'
                return redirect('/my-reviews')
        else:
            # this way if the form is not valid, it will hold the error msgs
            form=ReviewAdd(instance=review)
    
        return render(request, 'user/update-review.html', {'form':form, 'msg':msg})
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search