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

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.

Related

Pass a variable to another function and render an html template at the same time in django

We want to access the same variable in every function inside our views.py. Since it is not constant, we cannot use it as a global variable.
Is it possible to pass a variable to another function while also rendering an HTML template? What are the alternatives if none exist?
This is our login function in views.py
def loginpage(request):
errorMessage = ''
# Applicant Login
if request.method=="POST":
if request.POST.get('username') and request.POST.get('pwd'):
try:
currentUser=Applicant.objects.get(username=request.POST['username'],pwd=request.POST['pwd'])
currentUser=Applicant.objects.get(username=request.POST['username'])
first = currentUser.firstname
middle = currentUser.middleinitial
last = currentUser.lastname
AppDashboard = ApplicantDashboardPageView(currentUser, request)
except Applicant.DoesNotExist as e:
errorMessage = 'Invalid username/password!'
return render(request, 'home.html')
The currentUser variable inside our login function is the variable we want to pass in this function
def ApplicantdashboardPageView(currentUser, request):
appPeriod = ApplicationPeriod.objects.all()
exam = ExaminationSchedule.objects.all()
posts = Post.objects.all().order_by('-created_on')
form = PostForm()
name=userNaCurrent
print('from storeCurrentUser', name)
if request.method == "GET":
try:
posts = Post.objects.all().order_by('-created_on')
form = PostForm()
#applicantID=currentUser.id
#applicantNotification = Applicant.objects.get(id=applicantID)
return render(request, 'applicantdashboard.html', context={'UserName' : name, 'posts':posts, 'appPeriod':appPeriod, 'exam':exam})
except ObjectDoesNotExist:
return render(request, 'applicantdashboard.html', context={'UserName' : name, 'posts':posts,})
return render(request, 'applicantdashboard.html', context={'UserName' : name, 'posts':posts, 'appPeriod':appPeriod, 'exam':exam})
I am new to Django so please bear with me if my question seem too basic. Thank you
Store raw user password is a very big flaw in security. Please read more about Django Authentication system https://docs.djangoproject.com/en/4.1/topics/auth/
Basically, to store critical confidential information like passwords you need to at least, encrypt it. But for passwords you don't need to see the raw value of it, isn't it? Therefore, you just need to hash it and compare it every time you need to authenticate the user. Read more here Best way to store password in database
Django Auth system will also help to solve the issue by injecting the current user into a "global" request object so that you can access it everywhere.
You can do the same by keeping those 2 methods in a class and accessing variables by creating objects for it.

Only Want a user to 'like' a comment once. My code is not working

I have Post model, that has a field likes_total on it. I only want a user to be able to like a post once, but the code for this in the view is not working. here is the code:
views.py
def like(request, post_id, group_id):
group = get_object_or_404(Group, pk= group_id)
post = get_object_or_404(Post, pk= post_id)
likers = []
if request.method == 'POST':
if request.user in likers:
return render(request, 'groups/detail.html', {'group':group, 'error': "you have already liked this post"} )
else:
post.likes_total += 1
post.save()
likers.append(request.user)
return redirect('/groups/' + str(group_id) )
# post.save()
else:
return render(request, 'groups/detail.html', {'group':group})
this code seems right to me, cant tell what the problem is.. any help would be really appreciated!
Every time your function is called you set likers to be empty. Instead it should be an attribute of the post.
Your likers list isn't persisted anywhere and it's always initialized to an empty list, so the request.user will never be in the list.
You should edit your model so that each of your Post objects have a list of users that liked it, and then you can persist, update and check that list to ensure that each user likes each post once at most.
You define a list named likers in the like function. That means that each time someone calls the like function, you construct a new and empty list.
You could construct the list outside the function, but this will not help either. In fact the only data that you can consider persistent (the data that you can insert/modify/delete such that the next call sees this differences) is in the database.
As a result you should let the database store the people who like the post, by for example adding a ManyToManyField to the Post model that refers to the users that liked to post. So you should edit the model:
class Post(Model):
likers = ManyToManyField(User)
# some other fields
likes_total = IntegerField()
Now we can add the user that likes the post to the many-to-many relation:
def like(request, post_id, group_id):
group = get_object_or_404(Group, pk= group_id)
post = get_object_or_404(Post, pk= post_id)
if request.method == 'POST':
if request.user in post.likers.all():
return render(request, 'groups/detail.html', {'group':group, 'error': "you have already liked this post"} )
else:
post.likes_total += 1
post.likers.add(request.user)
post.save()
return redirect('/groups/' + str(group_id) )
else:
return render(request, 'groups/detail.html', {'group':group})
Another improvement that you can make is using reverse to generate urls, instead of constructing URLs yourself.

How to Append to Array Field in Python Django

I am making an E commerce site, I want to store Cart elements in an integer Array Field. I am using PostGreSql as my database.
I have created model for cart by extending Django User model. Here is my models
class UserCart(models.Model):
user=models.OneToOneField(User,on_delete=models.CASCADE)
user_product=models.IntegerField(blank=True, null=True)
cart_products = ArrayField(
models.IntegerField(blank=True),
default = list
)
User.profile = property(lambda u:UserCart.objects.get_or_create(user=u)[0])
Below is my Form.py. I have created only basic form
from django import forms
from .models import UserCart
from django.db import models
from django.contrib.postgres.fields import ArrayField
class UserCartForm (forms.ModelForm):
class Meta:
model= UserCart
fields = ('user_product',)
I have searched alot on internet but was unable to find the relevant answer.I want that whenever user clicks on Add to Cart button, that product_id gets stored in cart_products array.I read somewhere that ArrayFields behave as list in Django, so here is my views.py
#login_required
def user_cart(request):
if request.method=='POST':
form=UserCartForm(request.POST , instance=request.user.profile)
if form.is_valid():
post = form.save(commit=False)
post.cart_products.append(99)
post.save()
return HttpResponseRedirect('/user_login/loggedin')
else:
HttpResponse("Error")
else:
user=request.user
profile=user.profile
form= UserCartForm(instance=profile)
args={}
args.update(csrf(request))
args['form']=form
return render_to_response('cartapi.html' ,args)
Its giving me Error that
AttributeError at /cart/ac/
'NoneType' object has no attribute 'append'
Request Method: POST
Request URL: http://localhost:8000/cart/ac/
Django Version: 1.11.2
Exception Type: AttributeError
Exception Value:
'NoneType' object has no attribute 'append'
Exception Location: C:\Users\Muhammad
Jawad\AppData\Local\Programs\Python\Python36-32\mysite\cart\views.py in
user_cart, line 19
Python Executable: C:\Users\Muhammad
Jawad\AppData\Local\Programs\Python\Python36-32\python.exe
And if i save cart_products this way
post.cart_products=99
Then it throws this error
column "cart_products" is of type int4range but expression is of type integer
LINE 1: ...er_id" = 1, "user_cart" = 3000, "cart_products" = 99 WHERE "...
^
HINT: You will need to rewrite or cast the expression.
Request Method: POST
Request URL: http://localhost:8000/cart/ac/
Django Version: 1.11.2
Exception Type: ProgrammingError
Exception Value:
column "cart_products" is of type int4range but expression is of type integer
LINE 1: ...er_id" = 1, "user_cart" = 3000, "cart_products" = 99 WHERE "...
^
HINT: You will need to rewrite or cast the expression.
Kindly Help me in this matter.Summarizing my Question:
How can i get user_product as id and save it in cart_products
change yor views like this
views.py
#login_required
def user_cart(request):
if request.method=='POST':
form=UserCartForm(request.POST , instance=request.user.profile)
if form.is_valid():
post = form.save(commit=False)
if post.cart_products:
post.cart_products.append(99)
else:
post.cart_products = [99]
post.save()
return HttpResponseRedirect('/user_login/loggedin')
else:
HttpResponse("Error")
else:
user=request.user
profile=user.profile
form= UserCartForm(instance=profile)
args={}
args.update(csrf(request))
args['form']=form
return render_to_response('cartapi.html' ,args)
Your database is messed up. Drop it and remigrate (or craft a custom migration if you have data to preserve: basically, you just have to expand existing ranges into the full array).
See https://docs.djangoproject.com/en/2.1/_modules/django/contrib/postgres/fields/ranges/#IntegerRangeField
The int4range is the db type associated with the IntegerRangeField. This indicates either problem with your migrations (try running ./manage.py makemigrations) or that your database is out-of-sync with your DB (try running ./manage.py migrate).
It's hard to say what exactly the problem is without looking at your migrations and the current table definition in the database, but this should get you started.
keyword_from_user="My name is John Doe"
I have Django 3.1.7 and this method has worked for me.
models.py
class Keys(models.Model):
keys = ArrayField(models.CharField(max_length=50, blank=True),size=5,blank=True)
docfile = models.FileField(upload_to='documents/%Y/%m/%d', blank=True, null=True)
views.py create object
new_document_object = Keys.objects.create(keys= keyword_from_user.split(), docfile =file)
views.py create object
new_document_object = Keys.objects.create(keys= keyword_from_user.split(), docfile =file)
views.py update object
keys = Keys.objects.get(id=id_from_user)
keys.keys=user_data['keyword_update_list']
keys.save()
You can save your cart_products into a python list then modify that list using the append method. Thereafter, you can save the new value of the list into the ArrayField
#login_required
def user_cart(request):
if request.method=='POST':
form=UserCartForm(request.POST , instance=request.user.profile)
if form.is_valid():
post = form.save(commit=False)
# copy the existing cart_products to a temp variable
temp_cart = post.cart_products
# append your new product code to the temp_cart
temp_cart.append(99)
# save the new value of temp_cart to the cart_products field
post.cart_products = temp_cart
# save the post
post.save()
return HttpResponseRedirect('/user_login/loggedin')
else:
HttpResponse("Error")
else:
user=request.user
profile=user.profile
form= UserCartForm(instance=profile)
args={}
args.update(csrf(request))
args['form']=form
return render_to_response('cartapi.html' ,args)

How to get models current values from a view to another?

I have a website where I would like to display the product name the user purchased after he was redirected from the checkout to the thank you page.
The problem is that I don't get how I could send a data from a view to another without creating a form in the template.
here is two example of views from checkout_payment to checkout_confirmation pages:
def checkout_payment(request):
customer_id = request.user.profile.stripe_id
if request.method == 'POST':
try:
gig = Gig.objects.get(id=request.POST.get('gig_id'))
except Gig.DoesNotExist:
return redirect(reverse('purchase_error_detail'))
return redirect(reverse('purchase_confirmation_detail'))
def checkout_confirmation(request):
#how can I get the purchased gig datas ?
return render(request, 'purchase/confirmation.html', {})
models.py Gig contains : user, title, price fields.
urls.py : name='purchase_confirmation_detail'
Is there a way to get the last purchased datas avoiding using a form or the urls to get the product informations ?
Easy and fast way: Sessions
If all you need is a list of strings or a single string, you can just use sessions. You can read about them in detail in the docs. Just save the names in some key, display them and clear them.
Better, more future proof solution but slightly more complicated: Models
When you are selling something, it is desirable to keep around some record of what the user bought. This can be helpful when system fails (trust me, it will) or to keep a record of everything.
It can be something as simple as:
class Transaction(models.Model):
gig = models.ForeignKey(Gig)
user = models.ForeignKey(User)
Now you refactor your view in 2 ways:
Only the user in the transaction should be able to see the content on it.
Add the pk of the Gig to the url you redirected to.
Your source view should use a redirect like:
def checkout_payment(request):
customer_id = request.user.profile.stripe_id
if request.method == 'POST':
try:
gig = Gig.objects.get(id=request.POST.get('gig_id'))
except Gig.DoesNotExist:
return redirect(reverse('purchase_error_detail'))
new_transaction = Transaction.objects.create(user=request.user, gig=gig)
return redirect(reverse('purchase_confirmation_detail', kwargs={'pk': new_transaction.pk}))
And your destination view will be something like:
def checkout_confirmation(request, *args, **kwargs):
new_transaction = Transaction.objects.get(kwargs.get('pk'))
if request.user != new_transaction.user:
return HttpResponseForbidden() # You can raise Http404 here too to hide the resource, like github does
return render(request, 'purchase/confirmation.html', {'gig': transaction.gig})
Now you have access to everything you need to display.

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.

Categories