I'm practicing Django and was doing the Commerce assignment of CS50, got an error in the watchlist view and don't understand how to fix it. Hopefully you can help me.
Here is the view:
def watchlist(request):
if request.method == "POST":
listing_id = request.POST.get("listing_id")
try:
listing = Listing.objects.get(pk=listing_id)
user = User.objects.get(id=request.user.id)
except Listing.DoesNotExist:
return render(request, "auctions/error_handling.html", {
"code": 404,
"message": "Listing id doesn't exist"
})
if request.POST.get("on_watchlist") == "True":
watchlist_item_to_delete = Watchlist.objects.filter(
user = user,
listing = listing
)
watchlist_item_to_delete.delete()
else:
try:
watchlist_item = Watchlist(
user = user,
listing = listing
)
watchlist_item.save()
except IntegrityError:
return render(request, "auctions/error_handling.html", {
"code": 400,
"message": "Listing is already on your watchlist"
})
return HttpResponseRedirect("/" + listing_id)
watchlist_listings_ids = User.objects.get(id=request.user.id).watchlist.values_list("listing")
watchlist_items = Listing.objects.filter(id__in=watchlist_listings_ids, active_status=True)
return render(request, "auctions/watchlist.html", {
"watchlist_items": watchlist_items
})
Django reports the error in this line listing = Listing.objects.get(pk=listing_id), so not even the exception is handling the error.
I checked all the models and other views, and also using the app itself in the local host and the only thing alerting an error is that part.
Related
i using pytest and coverage for testing django project But I don't know how to test the else block that has return redirect("account_login") and fix the red part that says coverage.
In your opinion, how can I write a test for that else piece and fix the red part that says coverage?
views.py
#verified_email_required
def profile_view(request, username):
# We check if the user is logged in?
if request.user.is_authenticated:
try:
profiles = Profile.objects.all()[:4]
# get user profile by username
profile = Profile.objects.get(user__username__iexact=username)
user = User.objects.get(username=username)
user_following = following(user)
user_followers = followers(user)
logged_in_user_following = following(request.user)
logged_in_user_followers = followers(request.user)
# if user not found raise 404 error
except ObjectDoesNotExist:
raise Http404
# context data
context = {
"user": user,
"profile": profile,
"profiles": profiles,
"following": user_following,
"followers": user_followers,
}
return render(request, "user_profile/profile.html", context)
# if a user is not login in redirecting to login page
else:
return redirect("account_login")
test_view.py
#pytest.mark.django_db
class TestProfileView:
#pytest.fixture
def user(self):
user, created = User.objects.get_or_create( # created user
username="test_username",
first_name="test_first_name",
last_name="test_last_name",
email="test#test.com",
is_active=True,
is_superuser=False,
)
(
user_email_address,
created,
) = EmailAddress.objects.get_or_create( # user email confirmation
email=user.email, user=user
)
user_email_address.verified = True
user_email_address.primary = True
user_email_address.save()
return user
def test_profile_view_when_user_is_authenticated_return_correct_profile(
self, user, client
):
client.force_login(user) # user logged in
response = client.get(user.profile.get_absolute_url())
content = response.content.decode(response.charset)
assert response.status_code == 200
assert (
'<h1 class="text-3xl md:text-4xl font-semibold">Test_first_name test_last_name</h1>'
in str(content)
)
response = client.get("/user_not_exist", follow=True)
assert response.status_code == 404
response = client.post("/accounts/logout/")
assert response.status_code == 302
def test_profile_view_when_user_is_anonymous_return_login_page(self, user, client):
response = client.get("/test_username/", follow=True)
content = response.content.decode(response.charset)
assertRedirects(response, "/accounts/login/?next=/test_username/")
assert response.status_code == 200
assert response.template_name[0] == "account/login.html"
assert '<h1 class="text-3xl font-semibold text-center">Login</h1>' in str(
content
)
assert response.resolver_match.url_name == "account_login"
assert response.resolver_match.view_name == "account_login"
I suspect you won't be able to as your decorator #verified_email_required will prevent any unlogged in people from reaching that line of code.
My assumption here is that you are using allauth as it provides a decorator of that precise name. See https://django-allauth.readthedocs.io/en/stable/decorators.html which states: If the user isn’t logged in, it acts identically to the login_required decorator.
I am trying to create a search functionality in django. I just wrote the view but i was getting an error with that. I have tried debugging the codes but I don't seems to know where the error is.
Error Log
File "C:\Users\Habib\Documents\django\FIVERR\Alex_SMS\SMS\core\urls.py", line 2, in <module>
from . import views
File "C:\Users\Habib\Documents\django\FIVERR\Alex_SMS\SMS\core\views.py", line 37
return render(request, "core/search.html", context)
^
SyntaxError: invalid syntax
views.py
def search(request):
if request.method == 'GET':
product_name = request.GET.get('search')
try:
product = Product.objects.filter(name__icontains=product_name)
context = {"product": product}
return render(request, "core/search.html", context)
except:
product = "What is this"
context = {"product":product}
else:
result = "Sorry there is no product with that name"
return render(request, "core/search.html", {"result":result})
You're trying to return during a try/except which you can't do.
You need to return after this block;
def search(request):
if request.method == 'GET':
product_name = request.GET.get('search')
try:
product = Product.objects.filter(name__icontains=product_name)
context = {"product": product}
except:
product = "What is this"
context = {"product":product}
return render(request, "core/search.html", context)
else:
result = "Sorry there is no product with that name"
return render(request, "core/search.html", {"result":result})
It's generally considered bad practise to not catch specific exceptions though.
Here's some good information on exception handling; https://wiki.python.org/moin/HandlingExceptions
I was able to solve the issue by adding an except block as well as removing the return statement after the try statement and adding to after the except block.
views.py
def search(request):
if request.method == 'GET':
product_name = request.GET.get('search')
try:
product = Product.objects.filter(name__icontains=product_name)
context = {"product": product}
except product_name.DoesNotExist:
product = None
return render(request, "core/search.html", context)
else:
result = "Sorry there is no product with that name"
return render(request, "core/search.html", {"result":result})
I am trying to pass user data from one template inside of another template. For this I use an ajax request, as well explained here How do I integrate Ajax with Django applications?
although no error shows up, nothing gets pulled.
here is what my model formset view look like inside of template 1:
def New_Sales(request):
#context = {}
form = modelformset_factory(historical_recent_data, fields=('id','Id', 'Date','Quantity', 'NetAmount', 'customer_name'))
if request.method == 'GET':
formset = form(queryset= historical_recent_data.objects.none())
#blank_form = formset.empty_form
elif request.method == 'POST':
formset = form(request.POST)
#blank_form = formset.empty_form
if formset.is_valid():
request.session['sale'] = request.POST.get('sale')
for check_form in formset:
check_form.save()
quantity = check_form.cleaned_data.get('Quantity')
id = check_form.cleaned_data.get('Id')
update = replenishment.objects.filter(Id = id).update(StockOnHand = F('StockOnHand') - quantity)
update2 = Item2.objects.filter(reference = id).update(stock_reel = F('stock_reel') - quantity)
return redirect('/invoice/pdf/assembly/')
#else:
#form = form(queryset= historical_recent_data.objects.none())
return render(request, 'new_sale.html', {'formset':formset})
and here is the view to access template 1 data into template 2:
def generate_pdf_assembly(request):
my_company = MyCompany.objects.get(id = 1)
request = request.session.get('sale')
context = {'request' : request, 'my_company' : my_company }
print(context)
and here is the ajax request to access the data from the template (in template 2):
<h3> {{ context }} </h3>
<script>
$.ajax({
method: "GET",
url: "/new_sale.html",
sucess: function(context){
alert(context);
},
failure: function(context){
alert('got an error');
}
});
</script>
I feel like there must be an issue with the request.session in the view since no evident error gets outputed neither in log nor chrome console but I am not competent to debug it further at this point.
UPDATE: after changing context for request in tag template, the value None shows up, definitely an issue with the requesting
def username_exists(request):
data = {'msg':''}
if request.method == 'GET':
username = request.GET.get('username').lower()
exists = Usernames.objects.filter(name=username).exists()
if exists:
data['msg'] = username + ' already exists.'
else:
data['msg'] = username + ' does not exists.'`enter code here`
return JsonResponse(data)
Here I am trying to redirect to another page if the form is submitted successfully but this code is not working properly .The code saves the form data sends the email , everything is fine but the problem is while redirecting to another page if the form succeed. The error I get is:
Django Version: 2.0.6
Exception Type: ValueError
Exception Value:
dictionary update sequence element #0 has length 0; 2 is required
context_processor.py
def volunteer_page2(request):
volunteer = Volunteer.objects.all().order_by('date')
if request.method == 'POST':
form = VForm(request.POST or None)
if form.is_valid():
name = form.cleaned_data['name']
email = form.cleaned_data['email']
message = "{0} with email address {1} has sent you new message \n\n{2}".format(name, email, form.cleaned_data['message'])
form.save(commit = False)
try:
send_mail(name, message, 'appname <settings.EMAIL_HOST_USER>', ['myemail'])
except:
return HttpResponse('Invalid header found')
form.save()
messages.success(request, 'Success')
return redirect('volunteer_page')
else:
messages.error(request, "Sorry try again")
else:
form = VForm()
return {'volunteer': volunteer, 'form':form}
views.py
def about_page(request):
about = About.objects.all().order_by('date')
banner = Banner.objects.all()
testimonial = Testimonial.objects.order_by('-pk')[0:2]
nav = Nav.objects.all()
footer = Footer.objects.all()
latest_event2 = Events.objects.order_by('-pk')[0:2]
context = {
'about': about,
'testimonial': testimonial,
'footer':footer,
'banner': banner,
'nav': nav,
'latest_event2': latest_event2,
}
return render(request, 'myapp/about.html', context)
settings.py
'myapp.context_processor.volunteer_page2'
Django's context processor should always return dictionary. In your code you are returning HttpResponse also. This is problem.
I'm trying to test the content of messages while processing ModelForms with Django. I've got the following View (assume there's a Thing model with a required name field):
#login_required
def update(request, thing_id):
thing = Thing.objects.get(id=thing_id) # assume this works
if request.method == "POST":
form = ThingModelForm(request.POST, instance=thing)
if form.is_valid():
form.save()
messages.success(request, "Success!")
return redirect("/wherever")
else:
messages.error(request, "Oops!")
else:
form = ThingModelForm(instance=thing)
args = ("myapp/update.html", {"form": form})
kwargs = {"context_instance": RequestContext(request)}
return render_to_response(*args, **kwargs)
Now, I've got two unit tests. The first tests valid data, while the second tests invalid data. (Note that client login happens during setUp):
def test_update_account(self):
url = reverse('update', args=[1]) # assume that's a valid id
resp = self.client.post(url, {"name": "foo"})
self.assertEqual(resp.status_code, 302)
m = resp.cookies.get('messages', '')
self.assertTrue("Success!" in m.output())
And now to test invalid data:
def test_update_account_failure(self):
url = reverse('update', args=[1]) # assume that's a valid id
resp = self.client.post(url, {"name": ""}) # name is required
self.assertEqual(resp.status_code, 200)
# This works:
self.assertTrue("Oops!" in resp.content)
# This fails:
m = resp.cookies.get('messages', '')
self.assertTrue("Oops!" in m.output())
Why would accessing the message's content through the cookie work in one instance but fail in another?
Two things you could check:
When you create the request self.client.post(url, {"name": ""}) is a Thing instance returned here: thing = Thing.objects.get(id=thing_id) If not it will not reach the line of code where you set your error message: messages.error(request, "Oops!") as Thing.objects.get will throw an error.
If there are no results that match the query, get() will raise a
DoesNotExist exception.
If the first thing does return a Thing instance, you could check whether a redirect return redirect("/wherever") after setting the error message messages.error(request, "Oops!") does change anything.