I have an update form, whem i press updated for the form to update the user profile it I get the error "'UserProfile' object has no attribute 'id'"
my models is:
from django.db import models
from django.db.models.signals import post_save
from django.dispatch import receiver
class UserProfile(models.Model):
user = models.OneToOneField(User, related_name="custom_user_profile", primary_key=True)
organization = models.CharField(max_length=100, default='', blank=True)
address_line_1 = models.CharField(max_length=100, default='', blank=True)
address_line_2 = models.CharField(max_length=100, default='', blank=True)
city = models.CharField(max_length=100, default='', blank=True)
state = models.CharField(max_length=100, default='', blank=True)
post_code = models.CharField(max_length=100, default='', blank=True)
country = models.CharField(max_length=100, default='', blank=True)
def __unicode__(self):
return self.user.username
#receiver(post_save, sender=User)
def create_profile(sender, instance, created, **kwargs):
if created:
profile, new = UserProfile.objects.get_or_create(user=instance)
and my views is:
from django.shortcuts import render_to_response
from django.shortcuts import HttpResponseRedirect
from django.template import RequestContext
from django.core.context_processors import csrf
from django.contrib.auth.decorators import login_required
from user_profile.models import UserProfile
from django.contrib.auth.models import User
from forms import UserProfileForm
from django.shortcuts import redirect
#login_required
def update_profile(request):
userProfile = UserProfile.objects.get(user=request.user)
form = UserProfileForm(initial={
'organization':userProfile.organization,
'address_line_1':userProfile.address_line_1,
'address_line_2':userProfile.address_line_2,
'city':userProfile.city,
'state':userProfile.state,
'post_code':userProfile.post_code,
'country':userProfile.country,
})
return render_to_response('user_profile/update_profile.html', {'form':form}, RequestContext(request))
#login_required
def profile(request, profile_id):
if profile_id == "0":
if request.user.is_authenticated:
userProfile = UserProfile.objects.get(user=request.user)
else:
userProfile = UserProfile.objects.get(pk=profile_id)
return render_to_response('user_profile/profile.html', {'userProfile':userProfile}, RequestContext(request))
#login_required
def send_update_profile(request):
if request.method == 'POST':
form = UserProfileForm(request.POST)
if form.is_valid():
userProfile = UserProfile.objects.get(user=request.user)
organization = form.cleaned_data['organization']
userProfile.organization = organization
address_line_1 = form.cleaned_data['address_line_1']
userProfile.address_line_1 = address_line_1
address_line_2 = form.cleaned_data['address_line_2']
userProfile.address_line_2 = address_line_2
city = form.cleaned_data['city']
userProfile.city = city
state = form.cleaned_data['state']
userProfile.state = state
post_code = form.cleaned_data['post_code']
userProfile.post_code = post_code
country = form.cleaned_data['country']
userProfile.country = country
userProfile.save()
return redirect('/user/profile/' + str(userProfile.id))
else:
form = UserProfileForm()
return redirect('/user/send_update_profile/')
I can not work out why. One thing is that in admin.py, if i try to add 'id' as list display. An error occurs saying that there is no id in the user profile I am creating. Though, i thought an id field is automatically created when a model is created.
Any suggestions?
Django gives each model an automatic primary key field named id, unless you specify a primary key yourself. In your case, your model does not have an id field, because you have made user the primary key.
class UserProfile(models.Model):
user = models.OneToOneField(User, related_name="custom_user_profile", primary_key=True)
You could change the code to use the userProfile.user_id. Another option is to use the pk shortcut to access the primary key.
return redirect('/user/profile/' + str(userProfile.pk))
Related
I am following a Django youtube E-comerce tutorial by Dennis Ivy. I follow the tutorial line by line. from the initial i use to run the program and view all the output but alone the way i start getting this error message "RelatedObjectDoesNotExist: User has no customer". Am confuse because i keep repeating the video to see where i was wrong but could not trace it. please what is the solution? I realise the last time i tried, it open on its own using 'internet explorer' it display. when i open in 'chrome', it show the same erro. but when i deleted a customer from database it start showing the same erro again in 'internet explorer'. I dont want to give up on the tutorial cos i need it. please someone should assist me. Thanks
from multiprocessing import context
from django.shortcuts import render
from .models import *
from django.contrib.auth.models import User
from django.http import JsonResponse
import json
# Create your views here.
def store(request):
if request.user.is_authenticated:
customer = request.user.customer
order, created=Order.objects.get_or_create(customer=customer, complete =False)
items =order.orderitem_set.all()
cartItems=order.get_cart_items
else:
items=[]
order = {'get_cart_total':0, 'get_cart_items':0}
cartItems=order['get_cart_items']
products = Product.objects.all()
context = {
'products':products,
'cartItems':cartItems,
}
return render(request, 'store/store.html', context)
def cart(request):
if request.user.is_authenticated:
customer = request.user.customer
order, created=Order.objects.get_or_create(customer=customer, complete =False)
items =order.orderitem_set.all()
cartItems=order.get_cart_items
else:
items=[]
order = {'get_cart_total':0, 'get_cart_items':0}
cartItems=order['get_cart_items']
context = {
'items':items,
'order':order,
'cartItems':cartItems,
}
return render(request, 'store/cart.html', context)
def checkout(request):
if request.user.is_authenticated:
customer = request.user.customer
order, created=Order.objects.get_or_create(customer=customer, complete =False)
# order, created=Order.objects.get_or_create(complete =False)
items =order.orderitem_set.all()
else:
items=[]
order = {'get_cart_total':0, 'get_cart_items':0}
cartItems=order['get_cart_items']
context = {
'items':items,
'order':order,
'cartItems':cartItems
}
return render(request, 'store/checkout.html', context)
def updateItem(request):
data = json.loads(request.data)
productId = data['productId']
action = data['action']
print('Action:', action)
print('productId:', productId)
customer=request.user.customer
product=Product.objects.get(id=productId)
order, created=Order.objects.get_or_create(complete =False)
orderItem, created=OrderItem.objects.get_or_create(order=order, product=product)
if action =='add':
orderItem.quantity =(orderItem.quantity +1)
elif action =='remove':
orderItem.quantity =(orderItem.quantity -1)
orderItem.save()
if orderItem.quantity <=0:
orderItem.delete()
return JsonResponse('Item was added', safe =False)
this is the models.py
import email
from django.db import models
from django.db.models.fields.related import OneToOneField
from django.contrib.auth.models import User
from numpy import product
# Create your models here.
class Customer(models.Model):
user=models.OneToOneField(User, null=True, blank=True, on_delete=models.CASCADE)
name = models.CharField(max_length=200, null=True)
email=models.CharField(max_length=200)
def __str__(self):
return self.name
class Product(models.Model):
name = models.CharField(max_length=200, null=True)
price = models.FloatField()
digital=models.BooleanField(default=False, null=True, blank=True)
image = models.ImageField(null=True, blank=True)
def __str__(self):
return self.name
#this is to avoid erro in the template when we delete image
#property
def imageURL(self):
try:
url=self.image.url
except:
url=''
return url
class Order(models.Model):
customer=models.ForeignKey(Customer, on_delete=models.SET_NULL, null=True, blank=True)
date_ordered=models.DateTimeField(auto_now_add=True)
complete = models.BooleanField(default=False)
transaction_id = models.CharField(max_length=200, null=True)
def __str__(self):
return str(self.id)
#property
def get_cart_total(self):
orderitems = self.orderitem_set.all()
total = sum([item.get_total for item in orderitems])
return total
#property
def get_cart_items(self):
orderitems = self.orderitem_set.all()
total = sum([item.quantity for item in orderitems])
return total
class OrderItem(models.Model):
product=models.ForeignKey(Product, on_delete=models.SET_NULL, null=True, blank=True)
order=models.ForeignKey(Order, on_delete=models.SET_NULL, null=True, blank=True)
quantity = models.IntegerField(default=0, null=True, blank=True)
date_added=models.DateTimeField(auto_now_add=True)
#property
def get_total(self):
total = self.product.price * self.quantity
return total
class ShippingAddress(models.Model):
customer=models.ForeignKey(Customer, on_delete=models.SET_NULL, null=True, blank=True)
order=models.ForeignKey(Order, on_delete=models.SET_NULL, null=True, blank=True)
address= models.CharField(max_length=200, null=True)
city = models.CharField(max_length=200, null=True)
state = models.CharField(max_length=200, null=True)
zipcode = models.CharField(max_length=200, null=True)
date_added=models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.address
this is the urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.store, name = 'store'),
path('cart/', views.cart, name = 'cart'),
path('checkout', views.checkout, name = 'checkout'),
path('update_item/', views.updateItem, name='update_item')
]
Ways to solve it
You can either add the code below inside step 1 or 2 which you need to run in the shell(inside your app folder)
Create in your app folder this file , create_customers.py
Open the app folder in terminal and run the command below
python manage.py shell
then paste the code below into shell
from django.contrib.auth.models import User
from store.models import Customer
for user in User.objects.all():
Customer.objects.create(user=user, name=user.username, email=user.email)
you can use the request.user to query the customer
customer = Customer.objects.get(user__id = request.user.id)
I have a model form to list an item and I am trying to get the form to fill in the user id from the user that is submitting the form. Currently, the form is submitted successfully but it always uses the first user in the database's id for every item.
models.py
class Item(models.Model):
id = models.UUIDField( primary_key=True, default=uuid.uuid4, editable=False )
creator = models.ForeignKey( get_user_model(), on_delete=models.CASCADE, default=2)
item_name = models.CharField(max_length=40)
price = models.DecimalField(max_digits = 6, decimal_places=2)
description = models.CharField(max_length= 500)
main_image = models.ImageField(upload_to=path_and_rename , max_length=255, null=True, blank=True)
image_2 = models.ImageField(upload_to='items/', blank=True)
image_3= models.ImageField(upload_to='items/', blank=True)
image_4= models.ImageField(upload_to='items/', blank=True)
image_5= models.ImageField(upload_to='items/', blank=True)
quantity = models.IntegerField(default=1, validators=[ MaxValueValidator(100),MinValueValidator(1)])
created_on = models.DateTimeField(auto_now_add=True)
updated_on = models.DateTimeField(auto_now=True)
def __str__(self):
return self.item_name
def get_absolute_url(self):
return reverse("item_detail_view", args=[str(self.id)])
forms.py
from django.forms import ModelForm, forms
from .models import Item
class List_Item_Form(ModelForm):
forms.ModelChoiceField(queryset=Item.objects.filter(user=user))
class Meta:
model = Item
def __init__(self, *args, **kwargs):
user = kwargs.pop("user", None)
super().__init__(*args, **kwargs)
views.py
class AddListing( generic.CreateView):
template_name = 'store/add_listing.html'
fields = ('item_name','price','description','main_image','quantity')
model = Item
def form_valid(self, form):
self.object = form.save(commit=False)
self.object.user = self.request.user
self.object.save()
return super().form_valid(form)
It can be done using function based view too because there we get current user more easily.
Try this:
models.py
from django.db import models
from django.contrib.auth.models import User
class Item(models.Model):
creator = models.ForeignKey(User, on_delete=models.CASCADE)
item_name = models.CharField(max_length=40)
price = models.DecimalField(max_digits=6, decimal_places=2)
description = models.CharField(max_length=500)
main_image = models.ImageField(
upload_to=path_and_rename, max_length=255, null=True, blank=True)
image_2 = models.ImageField(upload_to='items/', blank=True)
image_3 = models.ImageField(upload_to='items/', blank=True)
image_4 = models.ImageField(upload_to='items/', blank=True)
image_5 = models.ImageField(upload_to='items/', blank=True)
quantity = models.PositiveIntegerField(default=1)
created_on = models.DateTimeField(auto_now_add=True)
updated_on = models.DateTimeField(auto_now=True)
def __str__(self):
return self.item_name
admin.py
from django.contrib import admin
from home.models import Item
#admin.register(Item)
class ItemRegister(admin.ModelAdmin):
lis_display = ['id', 'creator', 'item_name', 'price', 'description']
urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.list, name='home'),
path('success/', views.success, name='success')
]
forms.py
from django.forms import ModelForm, forms
from .models import Item
class ListItemForm(ModelForm):
class Meta:
model = Item
fields = ['item_name', 'price', 'main_image'
'description', 'quantity']
views.py
from django.http import HttpResponseRedirect
from django.shortcuts import render
from .models import Item
from .forms import ListItemForm
def list(request):
if request.method == 'POST':
form = ListItemForm(request.POST)
if form.is_valid():
itemName = form.cleaned_data['item_name']
price = form.cleaned_data['price']
desc = form.cleaned_data['description']
quan = form.cleaned_data['quantity']
main_img = form.cleaned_data['main_image']
current_user = request.user
model_instance = Item(creator=current_user, item_name=itemName, price=price,
description=desc, quantity=quan, main_image=main_img)
model_instance.save()
return HttpResponseRedirect('/success/')
else:
form = ListItemForm()
return render(request, 'store/add_listing.html', {'form': form})
def success(request):
return render(request, 'store/success.html')
Rest of the fields of models you can customize very easily in the view.
I have a custom user model and has created a profile model from it as well. so when user sign up a profile instance is created in the profile model as well. Now I have another similar model which is the address model. I tried configuring it in the same way but the address instance isn't getting created. Is it possible to do that? This is just for an understanding, whether similar model like profile can be created.
this is my model.
class Profile(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
summary = models.TextField(max_length=250, blank=True, null=True)
birth_date = models.DateField(null=True,blank=True, auto_now_add=False, auto_now=False)
country = CountryField(blank_label='(select country)')
profile_pic = models.ImageField(upload_to='pimage/', default='pimage/default.png')
def __str__(self):
return f'{self.user.username} Profile'
class Address(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
product = models.ForeignKey(Product, on_delete=models.CASCADE, blank=True, null=True)
address = models.CharField(max_length=200, null=True)
city = models.CharField(max_length=200, null=True)
state = models.CharField(max_length=200, null=True)
zipcode = models.CharField(max_length=200, null=True)
mobile = models.CharField(max_length=12, null=True)
def __str__(self):
return f'{self.user.username} Address'
views
#login_required
def address_add(request):
if request.POST:
a_form = AddressForm(request.POST, instance=request.user.address)
if a_form.is_valid():
a_form.save()
messages.success(request, f'Address Saved')
return redirect('user_address')
else:
a_form = AddressForm(instance=request.user.address)
context = {'a_form':a_form,}
return render(request, 'áccounts/user_address.html', context)
You can override save() method of User model to create an Address instance automatically:
from django.db import models
class User(models.Model):
# Your user model fields
def save(self, *args, **kwargs):
if self._state.adding:
# Create your Address instance here
pass
super(User, self).save(*args, **kwargs)
If you want to know how you can extend the Django user model here is a link that can help you.
Even though you can define some signal to create your Address instance after an User instance has been created.
from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.dispatch import receiver
class Address(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
bio = models.TextField(max_length=500, blank=True)
location = models.CharField(max_length=30, blank=True)
birth_date = models.DateField(null=True, blank=True)
#receiver(post_save, sender=User)
def create_user_address(sender, instance, created, **kwargs):
if created:
Address.objects.create(user=instance)
#receiver(post_save, sender=User)
def save_user_address(sender, instance, **kwargs):
instance.address.save()
I'm new to django i unable to display current login user full details by username. when i will try with Exam.objects.get(username=username) i will get error query not exist and i will try with Exam.objects.all() it will display username only.Please tell me how can i display current login user profile details
models.py
---------
from django.db import models
from django.template.defaultfilters import slugify
from django.contrib.auth.models import User
class Exam(models.Model):
user = models.OneToOneField(User)
username=models.CharField(max_length=25,default='')
phone = models.IntegerField(default=0)
location = models.CharField(max_length=40, blank=True)
email = models.EmailField(blank=True)
date_of_birth = models.DateField(null=True, blank=True)
gender = models.CharField(max_length=10, blank=True)
photo = models.ImageField(upload_to='media/photos/', null=True,
blank=True)
slug = models.SlugField(unique=True,default="")
def __str__(self):
return self.username
def save(self, *args, **kwargs):
self.slug = slugify(self.username)
super(Exam, self).save(*args, **kwargs)
forms.py
--------
from django import forms
from testapp.models import Exam
from django.contrib.auth.models import User
from django.core import validators
class ExamForm(forms.ModelForm):
password = forms.CharField(max_length=32, widget=forms.PasswordInput)
rpassword=forms.CharField(label='Re Enter
Password',widget=forms.PasswordInput)
first_name = forms.CharField(max_length=40, required=True)
last_name = forms.CharField(max_length=40, required=True)
phone = forms.IntegerField()
date_of_birth=forms.DateTimeField(help_text='DD/MM/YYYY
H:M',input_formats=['%d/%m/%Y %H:%M'])
gender = forms.CharField(max_length=10, required=True)
location = forms.CharField(max_length=40, required=True)
photo = forms.ImageField(help_text="Upload image: ", required=False)
class Meta:
model = Exam
fields = ('username','password','rpassword','first_name','last_name',
'email','date_of_birth','gender','photo','location','phone')
views.py
--------
def maas(request,maas_username_slug):
context_dict = {}
mass = request.user.Exam
# maas = Exam.objects.get(slug=maas_username_slug)
context_dict['maas_username'] = maas.username
context_dict['maas_username_slug'] = maas_username_slug
context_dict['maas_phone'] = maas.phone
context_dict['maas_firstname'] = maas.firstname
context_dict['maas_lastname'] = maas.lastname
context_dict['maas_location'] = maas.location
context_dict['date_of_birth'] = maas.date_of_birth
context_dict['maas_gender'] = maas.gender
context_dict['photo'] = maas.photo
context_dict['maas'] = maas
return render(request, 'testapp/profile.html', {'context_dict':
context_dict})
urls.py
-------
urlpatterns = [
url(r'(?P<maas_username_slug>\w+)/$', views.maas,
name='profile'),
]
profile.html
------------
{%extends 'testApp/base.html'%}
{%block body_block%}
<h1>Profile page:</h1>
<h1>{{maas_lastname}}</h1>
<h1>{{maas_username}}</h1>
{%endblock%}
I am getting the error:
AttributeError: 'User' object has no attribute 'zipcode'
I get this error when the user fills out a form to sell an item.
Here are my views:
def get_entry(request):
if request.method == 'POST':
f = SellForm(request.POST)
if f.is_valid():
form=f.save(commit=False)
form.author = request.user
form.zipcode = request.user.zipcode
form.pubdate = datetime.datetime.now
form.save()
else:
f = SellForm()
return render(request, 'sell.html', {'form': f})
Here are my models:
from django.db import models
from django.contrib.auth.models import User
from django.utils.translation import ugettext as _
from userena.models import UserenaBaseProfile
from django.conf import settings
class MyProfile(UserenaBaseProfile):
user = models.OneToOneField(User,
unique=True,
verbose_name=_('user'),
related_name='my_profile')
city = models.TextField(null=True, blank=True)
state = models.TextField(null=True, blank=True)
zipcode = models.IntegerField(_('zipcode'),
max_length=5, null=True, blank=True)
coverpic = models.ImageField(upload_to="/site_media/media/covers/", null=True, blank=True)
class Entry(models.Model):
headline= models.CharField(max_length=200,)
body_text = models.TextField()
author=models.ForeignKey(settings.AUTH_USER_MODEL, related_name='entryauthors')
pub_date=models.IntegerField(max_length=8)
zipcode =models.ForeignKey(settings.AUTH_USER_MODEL, related_name='entryzipcodes')
price1 = models.TextField()
price2 = models.TextField()
item_picture = models.ImageField(upload_to="/site_media/media/items/", null=True, blank=True)
Here is my form:
class SellForm(ModelForm):
class Meta:
model = Entry
fields = ['headline', 'body_text', 'author', 'pub_date', 'zipcode', 'price1', 'price2', 'item_picture']
Am I doing anything wrong with the models?
As you are aware, and even reiterate in your comment, zipcode is an attribute of MyProfile, not of User. So why are you trying to access it on the user? You need to follow the relationship to the profile:
form.zipcode = request.user.my_profile.zipcode
(Note that "form" is a very bad name for the variable there: what you have is an instance of Entry, so perhaps you should name it accordingly.)