local variable 'user' referenced before assignment error in django function - python

I have this function in django that adds a new item to the wishlist, the function is doing what it should do but when I add a new user that was not registered, when adding an item to the wish list it returns this error, but when i refresh the page the error no longer exist.
I think the problem is that when a new user registers, he still does not have the database created in the wishlist model, so the try: condition fails because the user does not yet exist in the model, passing the except: condition where the user database is created, but I have to manually refresh the page so that the page no longer shows me the error.
How can I fix this so that the page no longer shows me this error?
def add_or_remove(request, listing_id):
if request.method == "POST":
if (request.POST["action"]) == "add":
try:
user = Wishlist.objects.get(user=request.user)
listing = Listing.objects.get(pk=listing_id)
user.item.add(listing)
except:
create = Wishlist(
user=request.user,
)
create.save()
user.item.add(listing)
messages.success(request, 'you added to Wishlist')
elif (request.POST["action"]) == "remove":
user = Wishlist.objects.get(user=request.user)
item = user.item.get(id=listing_id)
user.item.remove(item)
messages.success(request, 'you removed from Wishlist')
return redirect(reverse("listing", args=[listing_id]))

Django ORM's 'get' function may raise an exception when the requested object is not in the database, you can assure the existence of the 'user' object before going to the next line with a simple logic like this (I've renamed it to 'wishlist' according to the model name):
try:
wishlist = Wishlist.objects.get(user=request.user)
except Wishlist.DoesNotExist:
wishlist = Wishtlist(user=request.user)
wishlist.save()
Or you can use Django's built-in get_or_create() function that does the same thing out-of-the-box.
wishlist = Wishlist.objects.get_or_create(user=request.user)
Please note that your naming conventions may be a little misleading. And also, you need the same logic for the 'listing' object after 'user'.

As the error suggests, simply assign it as empty string at just starting of POST method, so:
def add_or_remove(request, listing_id):
if request.method == "POST":
user=""
if (request.POST["action"]) == "add":
try:
user = Wishlist.objects.get(user=request.user)
listing = Listing.objects.get(pk=listing_id)
user.item.add(listing)
except:
create = Wishlist(
user=request.user,
)
create.save()
user.item.add(listing)
messages.success(request, 'you added to Wishlist')
elif (request.POST["action"]) == "remove":
user = Wishlist.objects.get(user=request.user)
item = user.item.get(id=listing_id)
user.item.remove(item)
messages.success(request, 'you removed from Wishlist')
return redirect(reverse("listing", args=[listing_id]))

Related

How can i fetch my data from database to django template?

Whenever I run this,
Exception Value:
name 'current_user' is not defined;
error is raised.
I am not getting where i am doing the mistake as I m new in django programming. Please help me fetch the data
# To add a new product in the database
def AddNewProduct(request):
if request.method == "POST":
current_user = request.user
product_title =request.POST['product_title']
uid = request.POST['uid']
specification =request.POST['specification']
sale_price = request.POST['sale_price']
discount = request.POST['discount']
img1 = request.FILES['img1']
img2 = request.FILES['img2']
promote_method = request.POST['promote_method']
terms_conditions = request.POST['terms_conditions']
newproduct = AffProduct(user_id=current_user.id, product_title=product_title, uid=uid, specification=specification, sale_price=sale_price,
discount=discount, img1=request.FILES.get('img1'), img2=request.FILES.get('img2'),
promote_method=promote_method, terms_conditions=terms_conditions)
newproduct.save()
# Status message
messages.success(request, 'Product added successfully')
return render(request, 'blink_network.html')
else:
return render(request, 'blink_network.html')
#Here i m trying to fetch my data.
def showproduct(request):
if request.user.is_authenticated:
result = AffProduct.objects.filter(user_id=current_user.id)
else:
result = AffProduct.objects.all()
return render(request, 'blink_viewproduct.html', {'result': result})
It looks like you will be getting that problem from showproduct(request) because you don't define current_user in that method before calling it.
to call this
result = AffProduct.objects.filter(user_id=current_user.id)
you need to define current_user = request.user beforehand
Could you share the relevant models.py file as well? You probably linked the user model with the ForeignKey with the Product model. If you did this, you need to give current_user, not current_user.id, django handles the matching itself.
Also, I guess you are using django form. If you are using it, I recommend you to use it because you can increase the readability of your code by writing less code.

Django method exists() not working, error "referenced before assignment"

after long time passed at searched a solution, i not advanced for a reason.
I try of make operate the functionality "if exists():" for "User.username" of the user, and so avoid the duplicate username in my webSite,but this is not work.
this is my code in views.py :
def edit_profil(request, pk=id):
error_name = reverse_lazy('profil_edit')
template_name="blog/edit_profil.html"
if request.method == "POST":
form = EditProfilForm(data=request.POST, instance=request.user)
if form.is_valid():
usernameDatas = form.cleaned_data['username']
if User.objects.filter(username=usernameDatas).exists():
messages.error(request, 'This is Username already exists !')
return redirect(error_name)
else:
user = form.save(commit=False)
user.email = form.cleaned_data['email']
user.username=usernameDatas
user.save()
return redirect('/blog/profil')
else:
form = EditProfilForm(instance=request.user)
return render(request, template_name, locals())
The error received is:
"local variable 'usernameDatas' referenced before assignment"
Where is my error ? thanks all.
.exists() is not the origin of the problem. This is a rather generic error in Python. It means that you use a variable before you assigned a value to it. Now in the .exists() line, only one local variable is used: usernameDatas. So it is likely that this variable is not assigned.
If we now look at possible scenario's where it is not valid, we see that this can happen if the form.is_valid() fails (returns False). The most straightforward way to handle this is by inlining the part:
def edit_profil(request, pk=id):
error_name = reverse_lazy('profil_edit')
template_name="blog/edit_profil.html"
if request.method == "POST":
form = EditProfilForm(data=request.POST, instance=request.user)
if form.is_valid():
usernameDatas = form.cleaned_data['username']
# inline relevant parts
if User.objects.filter(username=usernameDatas).exists():
messages.error(request, 'This is Username already exists !')
return redirect(error_name)
else:
user = form.save(commit=False)
user.email = form.cleaned_data['email']
user.username=usernameDatas
user.save()
return redirect('/blog/profil')
else:
form = EditProfilForm(instance=request.user)
return render(request, template_name, locals())
Note however that the above is an elegant way to tackle the problem. If you specify unique=True for the username field of the related Django model, then the form will automatically validate this. Furthermore you specify paths in the redirct(..) instead of the name of a view, which makes it senstive to URL changes. Finally using locals() is a severe anti-pattern: it is better to pass a dictionary with the variables you use.

Django Integrity Error Handling

I have created a website for user registration with first name, last name, phone no and so on.
I have successfully established a connection to MySQL database. I want help regarding IntegrityError handling in django,since I'm a newbie.
When 2 users input same phone number, django takes me to its debug page with whole lots of information. Instead I want to notify the user then and there that another user with same phone number already exists. Please provide any pointers on this.
Following is my views.py file in which I process the form:
from django.shortcuts import render
from formProcessing.forms import UserForm
def form(request):
#This is using regular Django forms
#print request.POST
#form = EmailForm(request.POST or None)
#This is using model forms
form = UserForm(request.POST or None)
if form.is_valid():
new_instance = form.save(commit=True)
new_instance.save()
context = {"form": form }
template = "form.html"
return render(request,template,context)
In your UserForm you can overwrite clean method of your number attribute, lets say that your attribute is called 'number'
class UserForm(ModelForm):
#your user form attributes and stuff
def clean_number(self, value):
user_number = value
number_occurrences = User.objects.filter(number=user_number).count()
if number_occurrences > 0:
raise forms.ValidationError("You number is already taken by other user")
return self.cleaned_data
Check django docs about form validation
If you dont wan't to overwrite clean method and do it whitin your view. you can. (Is not elegant)
def form(request):
#This is using regular Django forms
#print request.POST
#form = EmailForm(request.POST or None)
#This is using model forms
number = request.POST.get('telephone')
number_occurrences = User.objects.filter(number=user_number).count()
if number_occurrences > 0:
context = {'error':'Number already exist'}
return render(request,template,context)
form = UserForm(request.POST or None)
if form.is_valid():
new_instance = form.save(commit=True)
new_instance.save()
context = {"form": form }
template = "form.html"
return render(request,template,context)
Before you create an object, query the db for the existence of that phone number.
if form.is_valid():
ph_number = #"Phone number from form"
if User.objects.filter(phone_number = ph_number).first():
return HttpResponse("The number already exists.")
new_instance = form.save(commit=True)
new_instance.save()
The first() method returns the index 0 of the queryset. So, if there is element 0 in the queryset, the error message will be displayed to the user.
you can probably do something with field validation, although I donĀ“t know exactly what your error is, or how the model is designed.
Anyway, you could try to look up whether the value is unique (i.e., look if another record exists with the same number), before trying to save it; this might be the cleanest.
https://docs.djangoproject.com/en/1.7/ref/forms/validation/#cleaning-a-specific-field-attribute
so something like:
def clean_telephone(self):
n = User.objects.filter(telephone=self.cleaned_data['telephone']).count()
if n > 0:
raise forms.ValidationError("telephone number is already in database")
return data
Or you could try to save it and catch the unique error with a try/except clause. This uses less databases access attempts.

Why Django test with blank data post does not work?

I'd like to understand why this testing case does not work: I'm testing that my signup form in my view returns errors when I try to submit an empty form.
In tests.py:
class SignupViewTestCase(TestCase):
def test_signup_post_blank(self):
resp = self.client.post(reverse(signup), {}) # blank data dictionary
self.assertFormError(resp, form='signup_form', field='email',
errors='Ce champ est obligatoire') # French version of "This field is mandatory"
In views.py:
def signup(request):
signup_form = SignupForm(request.POST or None)
if signup_form.is_valid():
ema = signup_form.cleaned_data['email']
raw_pwd = signup_form.cleaned_data['password']
try:
BizProfile.create(ema, raw_pwd)
except IntegrityError:
signup_form.errors['__all__'] = signup_form.error_class([
ERR_USER_EXISTS])
else:
messages.success(request, SUC_ACC_CREA)
messages.info(request, INF_CONN)
return redirect(signin)
return render(request, 'sign_up.html', locals())
When testing manually in my browser, I can see there IS actually an error on the email field when I submit it without data.
But test result says:
AssertionError: The field 'email' on form 'signup_form' in context 0 contains no errors
Any idea of what is happening? Thanks.
Actually, the problem is related to the or None.
That's because an empty dictionary is false. In an "or" condition, Python always returns the second value if the first is false. That means your form is being instantiated just with "None", rather than an empty dictionary: which means it is not being bound at all. A non-bound form does not have any errors.
Changing your test is not a good solution, because a browser would never submit the "email" key without a value: fields without values are simply not send in the POST data, which is why an empty dictionary is the right way to test this. Instead of changing your test, you should use the canonical view pattern, and remove that broken shortcut.
if request.method == 'POST':
signup_form = SignupForm(request.POST)
if signup_form.is_valid():
...
else:
signup_form = SignupForm()
return...

Django query not working

Here's the thing. I have a model called User and an attribute counter that counts the number of page access. So, if a user already exists, I have to query up the db and for that user only to increase in counter. Otherwise, create a new user. I have an annoying error in the get method. How can I surpass it? if request.method == 'POST':
form = UserForm(request.POST)
if form.is_valid():
u = form.save()
try:
obj = User.objects.get(user=u.user)
obj.counter += 1
obj.ipaddress = request.META['REMOTE_ADDR']
obj.save()
except Statistic.DoesNotExist:
ip = request.META['REMOTE_ADDR']
obj = User(user=u.user, counter=1, ipaddress=ip)
obj.save()
return {'status': 'OK'}
else:
return {'errors': form.errors}
return {'status': 'NOT OK. GET method'} Here's the errorget() returned more than one User -- it returned 2! Lookup parameters were
Django has amazing documentation on their QuerySet API. https://docs.djangoproject.com/en/dev/ref/models/querysets/
get only returns exactly 1 queryset. If no queryset is found, or more then 1 queryset is returned, an error is raised.
To catch this particular error you have to specify except User.MultipleObjectsReturned,
This means there are multiple users matching the query in your database. get should be used to fetch only one. It seems you are already coding for this but I think you are catching the wrong exception type. Try changing
except Statistic.DoesNotExist:
To
from django.core.exceptions import DoesNotExist
except DoesNotExist:

Categories