I'm working on a ecom website project and I follow Dennis Ivy's course about cart functionality. I want to add to cart whether the person is logged in or not. I place my code down below, where products are added to the cart as a order when you're logged in and everything's fine but when user is not logged in nothing happen even though I created the device key inside cookies.
models:
class User(AbstractBaseUser):
email = models.EmailField(verbose_name='email',max_length=255, unique=True)
first_name = models.CharField(max_length=50, blank=True, null=True)
last_name = models.CharField(max_length=50, blank=True, null=True)
username = models.CharField(max_length=50, default=None, unique=False, blank=True)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
is_admin = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
timestamp = models.DateTimeField(auto_now_add=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['first_name','last_name']
objects = UserManager()
def __str__(self):
return self.email
def has_perm(self, perm, obj=None):
return self.is_admin
def has_module_perms(self, app_label):
return True
class Guest(models.Model):
name = models.CharField(max_length=200, null=True, blank=True)
email = models.CharField(max_length=200, null=True, blank=True)
device = models.CharField(max_length=200, null=True, blank=True)
def __str__(self):
if self.name:
name = self.name
else:
name = self.device
return str(name)
class Order(models.Model):
klient = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True)
gosc = models.ForeignKey(Guest, on_delete=models.SET_NULL, null=True, blank=True)
data_zamowienia = models.DateTimeField(auto_now_add=True)
dostarczona = models.BooleanField(default=False)
transaction_id = models.CharField(max_length=100, null=True)
produkt = models.ForeignKey(Product, on_delete=models.SET_NULL, null=True)
ilosc = models.IntegerField(default=0, null=True, blank=True)
data_dodania = models.DateTimeField(auto_now_add=True)
def __str__(self):
return str(self.id)
def order_set(self):
pass
views:
def updateItem(request):
data = json.loads(request.body)
productId = data['productId']
action = data['action']
product = Product.objects.get(id=productId)
try:
user = request.user
order, created = Order.objects.get_or_create(klient=user, produkt=product, dostarczona=False)
except:
device = request.COOKIES['device']
customer, created = Guest.objects.get_or_create(device=device)
order, created = Order.objects.get_or_create(gosc=customer, produkt=product, dostarczona=False)
if action == 'add':
order.ilosc = (order.ilosc + 1)
elif action == 'remove':
order.ilosc = (order.ilosc - 1)
order.save()
if order.ilosc <= 0:
order.delete()
return JsonResponse('Item was added', safe=False)
I just did a quick test with the following view.
def myview(request):
print(request.user)
return HttpResponse("hello")
In an unauthenticated session, request.user isn't empty or None by the looks of it.
System check identified no issues (0 silenced).
January 09, 2021 - 21:45:29
Django version 3.1.5, using settings 'config.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
AnonymousUser
[09/Jan/2021 21:45:33] "GET /test/ HTTP/1.1" 200 5
So if you're just doing a truthy check on request.user it's always going to be true.
You could perhaps do the following:
def myview(request):
if request.user != 'AnonymousUser':
# insert logged in user code here
else:
# insert your device related code here
Related
I'm trying to display user specific content in my django website and I am one step away from completing this task. In models.py I need the contact_email field to have its default value to be the email of the logged in user. I've tried many methods of doing this but nothing has worked yet.
models.py
class Account(AbstractUser):
email = models.EmailField(verbose_name='email', max_length=60, unique=True)
name = models.CharField(max_length=45, unique=False)
username = models.CharField(max_length=100, default='')
date_joined = models.DateTimeField(verbose_name='date joined', auto_now_add=True)
last_login = models.DateTimeField(verbose_name='last login', auto_now=True)
is_admin = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
is_employee = models.BooleanField(default=True, verbose_name='Are you using FilmLink as an employee?')
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['name', 'is_employee']
objects = MyAccountManager()
class Meta:
permissions = [
("post_jobs", "Can post jobs"),
]
def __str__(self):
return self.name
def has_perm(self, perm, obj=None):
return True
def has_perms(self, perm):
return True
def has_module_perms(self, app_label):
return True
#property
def is_staff(self):
return self.is_admin
class Job(models.Model):
company = models.CharField(max_length=40, null=True, verbose_name="Company/Employer")
description = models.TextField(null=True)
role = models.CharField(max_length=25)
area_of_filming = models.CharField(max_length=50, verbose_name="Area Of Filming", default="")
contact_email = models.EmailField(verbose_name='Contact Email', max_length=60, default='')#stuck on setting this default
created = models.DateTimeField(auto_now_add=True)
user = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, on_delete=models.CASCADE)
def __str__(self):
return self.company
views.py
#login_required(login_url='login')
def manage_jobs(request):
if request.user.is_employee:
return redirect('home')
else:
form = JobForm(request.POST)
if form.is_valid():
form.save()
jobs = Job.objects.filter(contact_email = request.user.email)
context = {"form":form, "jobs":jobs}
return render(request, 'employer/manage-jobs.html', context)
forms.py
class JobForm(ModelForm):
class Meta:
model = Job
fields = ('company', 'description', 'role', 'area_of_filming', 'contact_email')
I don't believe you can set a default that way.
What you should do instead is, when creating a Job object and saving it to database, provide the value of contact_email yourself.
You would then be able to later filter the Job entries based on contact_email field.
# Creating a Job object
job = Job()
job.column1 = value
job.contact_email = request.user.email
# In other view, where you need to filter
jobs = Job.objects.filter(contact_email=request.user.email)
A random thought:
if the only reason you want that contact_email field there is to be able to apply the filter to get all Job objects for that particular user, then you can just filter with user field too.
jobs = Job.objects.filter(user=request.user)
context = {"form":form, "jobs":jobs, 'contact_email': request.user.email}
return render(request, 'employer/manage-jobs.html', context)
I am working on a Django Project where I want to collect payment in Dollars from Applicants on the portal, and I don't know how to go about it. Though I have been following an online tutorial that shows how to do it but the result I am having is different with the recent error which says 'module' object is not callable.
Remember that I have tested my configured environment and also imported it into my views on top of the page.
Profile model code:
class Profile(models.Model):
applicant = models.OneToOneField(User, on_delete=models.CASCADE, null = True)
surname = models.CharField(max_length=10, null=True)
othernames = models.CharField(max_length=30, null=True)
gender = models.CharField(max_length=6, choices=GENDER, blank=True, null=True)
nation = models.CharField(max_length=255, choices=NATION, blank=True, null=True)
state = models.CharField(max_length=20, null=True)
address = models.CharField(max_length=200, null=True)
phone = models.CharField(max_length=16, null=True)
image = models.ImageField(default='avatar.jpg', upload_to ='profile_images')
def __str__(self):
return f'{self.applicant.username}-Profile'
Education/Referee Model code:
class Education(models.Model):
applicant = models.OneToOneField(User, on_delete=models.CASCADE, null = True)
qualification = models.CharField(max_length=60, choices=INSTITUTE, default=None, null=True)
instition = models.CharField(max_length=40, null=True)
reasons = models.CharField(max_length=100, null=True)
matnumber = models.CharField(max_length=255, null=True)
reference = models.CharField(max_length=100, null=True)
refphone = models.CharField(max_length=100, null=True)
last_updated = models.DateTimeField(auto_now_add=False, auto_now=True)
def __str__(self):
return f'{self.applicant}-Education'
Submitted Model code:
class Submitted(models.Model):
applicant = models.OneToOneField(User, on_delete=models.CASCADE, null=True)
application = models.UUIDField(primary_key = True, editable = False, default=uuid.uuid4)
confirm = models.BooleanField()
approved = models.CharField(max_length=20, null=True)
date = models.DateTimeField(auto_now_add=True)
def save(self, *args, **kwargs):
self.application == str(uuid.uuid4())
super().save(*args, **kwargs)
def __unicode__(self):
return self.applicant
def __str__(self):
return f'Application Number: {self.application}-{self.applicant}'
Scholarship Model code:
class Scholarship(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, null = True)
name = models.CharField(max_length=100, null = True)
description = models.CharField(max_length=200, null = True)
category = models.CharField(max_length=60, choices=INSTITUTE, default=None, null=True)
amount = models.FloatField()
date = models.DateTimeField(auto_now_add=True)
def __str__(self):
return f'WASU Scholarship: {self.name}-{self.name}'
My View for printing slip:
def AppSlip(request):
check_submited = Submitted.objects.get(applicant=request.user)
check_education = Education.objects.get(applicant = request.user)
candidate_edu = check_education.qualification
scholarship = Scholarship.objects.get(category=candidate_edu)
context = {
'candidate_edu':candidate_edu,
'scholarship':scholarship,
}
return render(request, 'user/slip.html', context)
My view for applicant to fill form for payment which I want their Profile captured automatically in the form:
def scholarship_detail(request, pk):
data = Scholarship.objects.get(id=pk)
if request.method=='POST':
form = PaymentForm(request.POST)
if form.is_valid():
user = Profile.objects.get(applicant=request.user)
name= user.surname
email = form.cleaned_data['email']
amount = form.cleaned_data['amount']
phone = form.cleaned_data['phone']
context = {'applicant':name, 'email':email, 'amount':amount, 'phone':phone}
return process_payment(request, context)
else:
form = PaymentForm()
ctx={
'form':form,
'product':data,
}
return render(request, 'user/scholarship.html', ctx)
My form code for Payment: How can query logged in user profile and fill into name, email, phone, amount from Scholarship Model into amount form filled.
class PaymentForm(forms.Form):
name = forms.CharField(label='Your name', max_length=100)
email = forms.EmailField()
phone=forms.CharField(max_length=15)
amount = forms.FloatField()
View code for processing Payment (Where I am suspecting the error). Though I have configured my env using django-dotenv with the Flutterwave Secret Key in it.
#login_required(login_url='user-login')
def process_payment(request, newContext={}):
auth_token= dotenv('SECRET_KEY')
hed = {'Authorization': 'Bearer ' + auth_token}
data = {
"tx_ref":''+str(math.floor(1000000 + random.random()*9000000)),
"amount":amount,
"currency":"KES",
"redirect_url":"http://localhost:8000/callback",
"payment_options":"card",
"meta":{
"consumer_id":23,
"consumer_mac":"92a3-912ba-1192a"
},
"customer":{
"email":email,
"phonenumber":phone,
"name":name
},
"customizations":{
"title":"WASU Scholarship 2022",
"description":"Best store in town",
"logo":"https://getbootstrap.com/docs/4.0/assets/brand/bootstrap-solid.svg"
}
}
url = ' https://api.flutterwave.com/v3/payments'
response = requests.post(url, json=data, headers=hed)
response=response.json()
link=response['data']['link']
return link
My payment Response View:
#require_http_methods(['GET', 'POST'])
def payment_response(request):
status=request.GET.get('status', None)
tx_ref=request.GET.get('tx_ref', None)
print(status)
print(tx_ref)
return HttpResponse('Finished')
Anticipating your prompt answers. Thanks
I have a User model, an ApplicantProfile model, and a CompanyProfielModel. A user can be of two types, an applicant or a company.
models.py
class User(AbstractBaseUser):
email = models.EmailField(max_length=255, unique=True)
name = models.CharField(max_length=255)
date_joined = models.DateTimeField(auto_now_add=True)
is_applicant = models.BooleanField(default=False)
is_company = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
is_admin = models.BooleanField(default=False)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['name']
objects = MyUserManager()
def __str__(self):
return self.email
def has_perm(self, perm, obj=None):
return True
def has_module_perms(self, app_label):
return True
class ApplicantProfile(models.Model):
GENDER_MALE = 0
GENDER_FEMALE = 1
GENDER_CHOICES = [(GENDER_MALE, 'Male'), (GENDER_FEMALE, 'Female')]
user = models.OneToOneField(User, null=True, on_delete=models.CASCADE)
image = models.ImageField(upload_to=image_directory_path, storage=image_storage, null=True, blank=True)
bio = models.TextField(max_length=500, null=True, blank=True)
address = models.TextField(max_length=200, null=True, blank=True)
birth_date = models.DateField(null=True, blank=True)
phone = PhoneNumberField(null=True, blank=True)
website = models.URLField(max_length=255, null=True, blank=True)
gender = models.IntegerField(choices=GENDER_CHOICES, null=True, blank=True)
interest = models.TextField(max_length=255, null=True, blank=True)
linkedin = models.CharField(max_length=255, null=True, blank=True)
github = models.CharField(max_length=255, null=True, blank=True)
twitter = models.CharField(max_length=255, null=True, blank=True)
facebook = models.CharField(max_length=255, null=True, blank=True)
def __str__(self):
return self.user.name
class CompanyProfile(models.Model):
user = models.OneToOneField(User, null=True, on_delete=models.CASCADE)
image = models.ImageField(upload_to=image_directory_path, storage=image_storage, null=True, blank=True)
about = models.TextField(max_length=500, null=True, blank=True)
location = models.CharField(max_length=100, null=True, blank=True)
start_date = models.DateField(null=True, blank=True)
website = models.URLField(max_length=255, null=True, blank=True)
logo = models.ImageField(upload_to=image_directory_path, storage=image_storage, null=True, blank=True)
def __str__(self):
return self.user.name
I have two URLs to create two different types of users. I can create applicants automatically right after a user registers from the applicant registration url, but I can't create companies from the company registration url.
views.py
def applicant_register(request):
if request.method == 'POST':
form = ApplicantRegistrationForm(request.POST)
if form.is_valid():
form.save()
email = form.cleaned_data.get('email')
raw_password = form.cleaned_data.get('password1')
user = authenticate(email=email, password=raw_password)
ApplicantProfile.objects.create(user=user)
messages.success(request, "Account created successfully.")
return redirect('applicant-feed')
form = ApplicantRegistrationForm()
context = {
"form": form
}
return render(request, 'user/applicant/applicant-register.html', context)
def company_register(request):
if request.method == 'POST':
form = CompanyRegistrationForm(request.POST)
if form.is_valid():
form.save()
email = form.cleaned_data.get('email')
raw_password = form.cleaned_data.get('password1')
user = authenticate(email=email, password=raw_password)
CompanyProfile.objects.create(user=user) # This line gives the error
messages.success(request, "Account created successfully.")
return redirect('company-feed')
form = CompanyRegistrationForm()
context = {
"form": form
}
return render(request, 'user/company/company-register.html', context)
Any help is appreciated.
Getting this error in the browser
According to error, looks like CompanyProfile is not a model class but something else. Is there a chance that you redefine it in views.py? Probably you also define a view with this name?
you don't need to use the form because you can create an account directly to any model like this function
def company_register(request):
if request.method == 'POST':
user = request.POST['user']
image = request.FILES['image']
about = request.POST['about']
location = request.POST['location']
start_date = request.POST['start_date']
website = request.POST['website']
logo = request.FILES['logo']
profile = CompanyProfile.objects.create(user=user, image=image, about=about, location=location, start_date=start_date, website=website, logo=logo)
profile.save()
return Response('Done')
else:
return Response('POST method only accepted')
I am using a custom User model. And I have another Customer model. I want the user field will only show the staff user no other type of user in the field will show in the registration form. In my case, it is showing all types of users whether it is staff or customer or a service user.
Models.py
class User(AbstractBaseUser, PermissionsMixin):
username = models.CharField(max_length=254, unique=True)
name = models.CharField(max_length=254, null=True)
email = models.EmailField(max_length=254, null=True)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
is_Customer = models.BooleanField(default=False)
is_Service_Provider = models.BooleanField(default=False)
last_login = models.DateTimeField(null=True, blank=True)
date_joined = models.DateTimeField(auto_now_add=True)
USERNAME_FIELD = 'username'
EMAIL_FIELD = 'email'
REQUIRED_FIELDS = []
objects = UserManager()
def get_absolute_url(self):
return "/users/%i/" % self.pk
def get_username(self):
return self.username
class Customer(models.Model):
user = models.OneToOneField('accounts.User', on_delete=models.SET_NULL, null=True)
email = models.EmailField(max_length=254, null=False)
date_Of_Birth = models.DateField(null=False)
country = models.ForeignKey('accounts.Country', null=True, on_delete=models.SET_NULL, related_name='Country')
state = models.ForeignKey('accounts.State', null=True, on_delete=models.SET_NULL, related_name='State')
city = models.ForeignKey('accounts.City', null=True, on_delete=models.SET_NULL, related_name='city')
address = models.CharField(max_length=254, null=False)
refernce_by_person_name = models.CharField(max_length=254, null=True)
refernce_by_person_contact_no = models.IntegerField(null=True)
phone_no = models.IntegerField(null=False)
alternate_no = models.IntegerField(null=False)
hobbies = models.CharField(max_length=254)
def __str__(self):
return self.user.username
views.py
def form(request):
forms = CustomerRegistrationForm()
if request.method == "POST":
forms = CustomerRegistrationForm(request.POST)
if forms.is_valid():
forms.save()
return redirect('/customer/show')
context = {
'forms' : forms,
}
return render(request,'customer/form.html', context)
forms.py
class CustomerRegistrationForm(forms.ModelForm):
class Meta:
model = Customer
fields = '__all__'
You can filter the staff users in the form like this.
class CustomerRegistrationForm(forms.ModelForm):
user = forms.ModelChoiceField(queryset=User.objects.filter(is_staff=True))
class Meta:
model = Customer
fields = ['user','email','date_of_birth',...]
I ran python manage.py migrate accounts zero then i faced an error,
I checked my models multiple times it seems everything is ok but...!?
This is the error:
django.db.utils.IntegrityError: (1062, "Duplicate entry '1' for key 'accounts_post_user_id_ecf3e197_uniq'")
User model:
class User(AbstractBaseUser):
id = models.BigAutoField(primary_key=True)
username = models.CharField(max_length=30, unique=True)
email = models.EmailField(max_length=191, unique=True)
email_verified = models.BooleanField(default=False)
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30, blank=True)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
is_admin = models.BooleanField(default=False)
is_verified = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
objects = UserManager()
USERNAME_FIELD = 'username'
EMAIL_FIELD = 'email'
REQUIRED_FIELDS = ['email', 'first_name', 'last_name']
def __str__(self):
return self.username
def has_perm(self, perm, obj=None):
return self.is_admin
def has_module_perms(self, app_label):
return self.is_admin
Post model:
class Post(models.Model):
id = models.BigAutoField(primary_key=True)
user = models.ForeignKey(User, on_delete=models.CASCADE)
channel = models.ForeignKey(Channel, on_delete=models.CASCADE, null=True, blank=True)
hashed_id = models.CharField(max_length=191)
text = models.TextField(max_length=270)
visits = models.IntegerField(default=0)
comment_status = models.BooleanField(default=True)
edited = models.BooleanField(default=False)
signature = models.CharField(max_length=191)
deleted_at = models.DateTimeField(null=True, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
There was 1 user with 2 posts.
I added unique=False to ForeignKey fields and it solved the problem.
I hope if this error occurs in your app this answer gives you a hand.