I am trying to create a shopping cart for my website, but in my function "add_to_cart" when I try to request the user profile model in the beginning of function it tells me
'User' object has no attribute 'profile'
add_to_cart is the first method in Checkout views.py under #get the user profile
Error
AttributeError at /checkout/add-to-cart/2/
'User' object has no attribute 'profile'
Request Method: GET
Request URL: http://127.0.0.1:8000/checkout/add-to-cart/2/
Django Version: 1.11
Exception Type: AttributeError
Exception Value:
'User' object has no attribute 'profile'
If I remove the related_name for user in Profile, then I receive this error:
Error from removal of related_name
Request Method: GET
Request URL: http://127.0.0.1:8000/checkout/add-to-cart/2/
Django Version: 1.11
Exception Type: AttributeError
Exception Value:
'Product' object has no attribute 'all'
Checkout views.py
from django.conf import settings
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.auth.decorators import login_required
from django.urls import reverse
from django.shortcuts import render, redirect, get_object_or_404
from users.models import User, Profile, userStripe
from portal.models import Product
#from manaland.helper import get_reference_code
from checkout.extras import generate_order_id
from checkout.models import OrderItem, Order
from django.views import generic
from django.views.generic import CreateView
import stripe
stripe.api_key = settings.STRIPE_SECRET_KEY
def add_to_cart(request, **kwargs):
#get the user Profile
user_Profile = get_object_or_404(Profile, user=request.user)
#filter products for id
product = Product.objects.filter(id=kwargs.get('item_id', "")).first()
#check if the user already owns the product
if product in request.user.profile.merchandise.all():
messages.info(request, "You already own this product")
return redirect(reverse('product_list'))
#create OrderItem of the selected product
order_item, status = OrderItem.objects.get_or_create(product=Product)
#create order associate with the user
user_order, status = Order.objects.get_or_create(owner=user_Profiles, is_ordered=False)
user_order.items.add(order_item)
if status:
#generate a reference code
user_order.ref_code = generate_order_id()
user_order.save()
#show confirmataion message and redirect to same page
messages.info(request, "item added to cart")
return redirect(reverse('product_list'))
def delete_from_cart(request, item_id, LoginRequiredMixin):
item_to_delete = OrderItem.objects.filter(pk=item_id)
if item_to_delete.exists():
item_to_delete[0].delete()
messages.info(request, "Item has been removed from shopping cart")
return redirect(reverse('shopping_cart:order_summary'))
def order_details(request, LoginRequiredMixin, **kwargs):
existing_order = get_user_pending_order(request)
context = {
'order': existing_order
}
return render(request, 'checkout/order_summary', context)
#class UserDetailView(LoginRequiredMixin, DetailView):
# model = User
# These next two lines tell the view to index lookups by username
# slug_field = 'username'
# slug_url_kwarg = 'username'
def checkout(request, LoginRequiredMixin):
existing_order = get_user_pending_order(request)
context = {
'order': existing_order
}
return render(request, 'checkout/checkout', context)
def update_transaction_records(request, order_id):
#get the order being processed
order_to_purchase = Order.objects.filter(pk=order_id).first()
#update the placed order
order_to_purchase.is_ordered=True
order_to_purchase.date_ordered=datetime.datetime.now()
order_to_purchase.save()
#get all items in the order
order_items = order_to_purchase.items.all()
order_items.update(is_ordered=True, date_ordered=datetime.datetime.now())
#add products to use profile
user_Profiles = get_object_or_404(Profile, user=request.user.user_profile)
#get the product from the items
order_products = [item.product for item in order_items]
user_Profiles.merchandise.add(*order_products)
user_Profiles.save()
#TODO Update payment records
#TODO email customer
messages.info(request, "Thank you! Your items have been added to your account")
return redirect(reverse('users:detail'))
def success(request, **kwargs):
return render(request, 'checkout/purchase_success.html', {})
Users models.py
from django.contrib.auth.models import AbstractUser
from django.core.urlresolvers import reverse
from django.db import models
from django.utils.encoding import python_2_unicode_compatible
from django.utils.translation import ugettext_lazy as _
from django.conf import settings
from allauth.account.signals import user_logged_in, user_signed_up
import stripe
stripe.api_key = settings.STRIPE_SECRET_KEY
from portal.models import Product
#from django.apps import apps
#Product1 = apps.get_model('portal', 'Product')
class User(AbstractUser):
# First Name and Last Name do not cover name patterns
# around the globe.
name = models.CharField(_('Name of User'), blank=True, max_length=255)
bio = models.CharField( blank=True, max_length=255)
image = models.ImageField(null=True, blank=True)
def __str__(self):
return self.username
def get_absolute_url(self):
return reverse('users:detail', kwargs={'username': self.username})
class Profile(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL, related_name='user_profile')
merchandise = models.OneToOneField(Product, blank=True, null=True)
description = models.CharField( blank=True, max_length=255)
image = models.ImageField(null=True, blank=True)
def __str__(self):
return self.user.username
Checkout urls.py
from django.conf import settings
from django.conf.urls.static import static
from django.conf.urls import url
from . import views
from manaland.views import ProductListView
from .views import (
add_to_cart,
delete_from_cart,
order_details,
checkout,
update_transaction_records,
success
)
#NOTE: https://github.com/codingforentrepreneurs/Guides/blob/master/all/common_url_regex.md
urlpatterns = [
#Shopping Cart
url(r'^add-to-cart/(?P<item_id>[-\w]+)/$', views.add_to_cart, name='add_to_cart'),
url(r'^order-summary/$', order_details, name='order_summary'),
url(r'^success/$', success, name='purchase_success'),
url(r'^item/(?P<item_id>[-\w]+)/delete/$', delete_from_cart, name='delete_item'),
url(r'^checkout/$', checkout, name='checkout'),
#url(r'^payment/(?P<order_id>[-\w]+)/update/$', process_payment, name='process_payment'),
url(r'^update-transaction/(?P<order_id>[-\w]+)/$', update_transaction_records, name='update_records'),
#url(r'^tip/create/$', views.TipCreate.as_view(), name='tip_create'),
]
if settings.DEBUG:
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
Your profile model is related to your User model via the user_profile related name, so the correct way to query it would be:
...
if product in request.user.user_profile.merchandise.all():
...
if for any reason you want to rename this relationship, then:
class Profile(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL, related_name='profile')
Then, your merchandise relationship is One to One, so it would return an object, not a collection, no need for all:
...
if product in request.user.user_profile.merchandise:
...
One improvement you can make here, is because merchandise is another object, this lookup will hit the database again just to see if merchandise exist. To save you a database hit, you can use the Profile auto-field merchandise_id, to read the information saved on the Profile table instead:
...
if product in request.user.user_profile.merchandise_id:
...
Every relationship (ForeignKey, ManyToMany and OneToOne) will create those auto-fields in the forwarding model, so it's easy to ask if the related object exist without having to invoke it.
I know you're having trouble getting all the concepts of the Django ORM in your head, so I recommend you read this documentation page throughly, it covers all the different relationships and concepts that are basic to a successful Django project.
Related
A newbie here in the world of Django. I am struggling with creating a hyperlink for a nested route.
The error I am getting is:
Could not resolve URL for hyperlinked relationship using view name "rest:campaign-detail". You may have failed to include the related model in your API, or incorrectly configured the `lookup_field` attribute on this field.
Some project setup notes
Using django rest framework
using DRF-extensions to create the routes
Using ModelViewSet
Expected end points:
/accounts/
/accounts/< pk >/
/accounts/< pk >/campaigns/
/accounts/< pk >/campaigns/< pk >/
/accounts/< pk >/campaigns/adgroup/
/accounts/< pk >/campaigns/adgroup/< pk >/
Set a namespace of rest in urls.py
Using HyperlinkedIdentityField to create the hyperlink. It only works with the parent object i.e.
url = serializers.HyperlinkedIdentityField(view_name='rest:account-detail')
However fails with any nested object i.e.
url = serializers.HyperlinkedIdentityField(view_name='rest:campaign-detail')
The model is quiet simple, an Account can have many Campaigns, and a campaign can have many AdGroups. See code below:
models.py
from django.db import models
from django.db.models import Q
from model_utils import Choices
ORDER_COLUMN_CHOICES = Choices(
('0', 'id'),
('1', 'keyword'),
('2', 'status'),
('3', 'match_type'),
)
# Account
class Account(models.Model):
account_name = models.CharField(max_length=128)
def __str__(self):
return self.account_name
# Campaign
class Campaign(models.Model):
class Status(models.TextChoices):
Enabled = "Enabled"
Paused = "Paused"
account = models.ForeignKey(
to=Account, on_delete=models.CASCADE, related_name='campaigns'
)
campaign_name = models.CharField(max_length=128)
status = models.CharField(max_length=21, choices=Status.choices, default=Status.Paused)
def __str__(self):
return self.campaign_name
# AdGroup
class AdGroup(models.Model):
class Status(models.TextChoices):
Enabled = "Enabled"
Paused = "Paused"
campaign = models.ForeignKey(
to=Campaign, on_delete=models.CASCADE, related_name='adgroups'
)
adgroup_name = models.CharField(max_length=128)
status = models.CharField(max_length=21, choices=Status.choices, default=Status.Enabled)
def __str__(self):
return self.adgroup_name
views.py
from rest_framework import viewsets
from .serializers import *
from . import models
from rest_framework_extensions.mixins import NestedViewSetMixin
class AccountViewSet(NestedViewSetMixin, viewsets.ModelViewSet):
serializer_class = AccountSerializer
queryset = models.Account.objects.all()
class CampaignViewSet(NestedViewSetMixin, viewsets.ModelViewSet):
serializer_class = CampaignSerializer
queryset = models.Campaign.objects.all()
class AdGroupViewSet(NestedViewSetMixin, viewsets.ModelViewSet):
serializer_class = AdGroupSerializer
queryset = models.AdGroup.objects.all()
serializers.py
from rest_framework import serializers
from . import models
class CampaignSerializer(serializers.ModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name="rest:campaign-detail")
class Meta:
model = models.Campaign
fields = '__all__'
class AccountSerializer(serializers.HyperlinkedModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='rest:account-detail')
class Meta:
model = models.Account
fields = '__all__'
class AdGroupSerializer(serializers.ModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='rest:adgroup-detail')
class Meta:
model = models.AdGroup
fields = '__all__'
I have 2 URL files. The project is named Vanilla and an app named rest where the DRF logic sits.
Vanilla urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('', include('rest.urls', namespace='rest')),
path('api-auth/', include('rest_framework.urls', namespace='rest_framework')),
path('admin/', admin.site.urls)
]
Rest urls.py
from django.urls import include, path
from . import views
from rest_framework_extensions.routers import ExtendedSimpleRouter
app_name = 'rest'
router = ExtendedSimpleRouter()
(
router.register(r'accounts',
views.AccountViewSet,
basename='account')
.register(r'campaigns',
views.CampaignViewSet,
basename='campaign',
parents_query_lookups=['account__id'])
.register(r'adgroups',
views.AdGroupViewSet,
basename='adgroup',
parents_query_lookups=['campaign__account', 'campaign'])
Thank You!
use hyperlinkedModelSerializer in all of your related serializer. that should work
Using the Stripe API to create a credit card checkout form on my website.
I am trying to test the following line in my view.py of the app checkout.
print (request.user.userStripe.stripe_id)
It could be the way my Users is set up.. I tried importing the models from the user app. I just don't understand why it can't see it.
I have two apps: users and checkout
I am the following error in the debug page
AttributeError at /checkout/
'User' object has no attribute 'userStripe'
Request Method: GET
Request URL: http://127.0.0.1:8000/checkout/
Django Version: 1.11
Exception Type: AttributeError
Exception Value:
'User' object has no attribute 'userStripe'
Exception Location: /home/dominic/Desktop/Projects/decentraland/website/manaland/manaland/env/lib/python3.4/site-packages/django/utils/functional.py in inner, line 239
Python Executable: /home/dominic/Desktop/Projects/decentraland/website/manaland/manaland/env/bin/python
Python Version: 3.4.3
Python Path:
['/home/dominic/Desktop/Projects/decentraland/website/manaland/manaland',
'/home/dominic/Desktop/Projects/decentraland/website/manaland/manaland/env/lib/python3.4',
'/home/dominic/Desktop/Projects/decentraland/website/manaland/manaland/env/lib/python3.4/plat-x86_64-linux-gnu',
'/home/dominic/Desktop/Projects/decentraland/website/manaland/manaland/env/lib/python3.4/lib-dynload',
'/usr/lib/python3.4',
'/usr/lib/python3.4/plat-x86_64-linux-gnu',
'/home/dominic/Desktop/Projects/decentraland/website/manaland/manaland/env/lib/python3.4/site-packages']
Server time: Mon, 2 Jul 2018 22:38:35 +0000
checkout.views.py
from django.conf import settings
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.auth.decorators import login_required
from django.shortcuts import render
from users.models import User, profile, userStripe
from django.views import generic
from django.views.generic import CreateView
#TODO UPDATE WITH LIVE VERISON FOR STRIPE API KEYS
import stripe
stripe.api_key = settings.STRIPE_SECRET_KEY
# Create your views here.
#login_required
def checkout(request):
publishKey = settings.STRIPE_PUBLISHABLE_KEY
print (request.user.userStripe.stripe_id)
if request.method == 'POST':
token = request.POST['stripeToken']
# Token is created using Checkout or Elements!
# Get the payment token ID submitted by the form:
try:
charge = stripe.Charge.create(
amount=999,
currency='usd',
description='Example charge',
source=token,
)
except stripe.error.CardError as e:
pass
context = {'publishKey': publishKey}
template = 'checkout/checkout.html'
return render(request, template, context)
users.models.py
from django.contrib.auth.models import AbstractUser
from django.core.urlresolvers import reverse
from django.db import models
from django.utils.encoding import python_2_unicode_compatible
from django.utils.translation import ugettext_lazy as _
from django.conf import settings
from allauth.account.signals import user_logged_in, user_signed_up
import stripe
stripe.api_key = settings.STRIPE_SECRET_KEY
#python_2_unicode_compatible
class User(AbstractUser):
# First Name and Last Name do not cover name patterns
# around the globe.
name = models.CharField(_('Name of User'), blank=True, max_length=255)
bio = models.CharField( blank=True, max_length=255)
image = models.ImageField(null=True, blank=True)
def __str__(self):
return self.username
def get_absolute_url(self):
return reverse('users:detail', kwargs={'username': self.username})
class profile(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL)
description = models.CharField( blank=True, max_length=255)
image = models.ImageField(null=True, blank=True)
def __str__(self):
return self.user.username
class userStripe(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL)
stripe_id = models.CharField(max_length=200, null=True, blank=True)
def __unicode__(self):
if self.stripe_id:
return str(self.stripe_id)
else:
return self.user.username
def stripeCallback(sender, request, user, **kwargs):
user_stripe_account, created = userStripe.objects.get_or_create(user=user)
if created:
print ('created for %s'%(user.username))
if user_stripe_account.stripe_id is None or user_stripe_account.stripe_id == '':
new_stripe_id = stripe.Customer.create(email=user.email)
user_stripe_account.stripe_id = new_stripe_id['id']
user_stripe_account.save()
def profileCallback(sender, request, user, **kwargs):
userProfile, is_created = profile.objects.get_or_create(user=user)
if is_created:
userProfile.name = user.username
userProfile.save()
user_logged_in.connect(stripeCallback)
user_signed_up.connect(profileCallback)
user_signed_up.connect(stripeCallback)
You should use lowercase model name, print(request.user.userstripe.stripe_id).
Better set related_name in your OneToOneField so you will know exactly how to access userStripe from user.
class userStripe(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL, related_name='user_stripe')
...
print(request.user.user_stripe.stripe_id)
Use request.user.userStripe.stripe_id.
You are using request.User. Instead you have to use: request.user.
you miss typing userStripe in print (request.user.userStripe.stripe_id)
try write userstripe :
print (request.user.userstripe.stripe_id)
it worked for me very nice
I got an error,
AttributeError at /app/api/get
Got AttributeError when attempting to get a value for field task_name on serializer TaskSerializer.
The serializer field might be named incorrectly and not match any attribute or key on the Color instance.
Original exception text was: 'Color' object has no attribute 'task_name'.
Now I wanna make a page that shows model's content in json format.
models.py is
from django.db import models
# Create your models here.
class Color(models.Model):
name = models.CharField(max_length=255)
background_color = models.CharField(max_length=255)
h1_color = models.CharField(max_length=255)
p_color = models.CharField(max_length=255)
def __str__(self):
return self.name
serializers.py is
from .models import Color
from rest_framework import serializers
class TaskSerializer(serializers.Serializer):
task_name = serializers.CharField(max_length=100)
status = serializers.SerializerMethodField('get_task_status')
def get_task_status(self, instance):
return instance.status.status
class Meta:
model = Color
fields = ('name',
'background_color',
'h1_color',
'p_color',
'task_name')
urls.py is
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^$', views.index, name='index'),
url(r'api/get',views.TaskGet.as_view(),name='task-get')
]
views.py is
from django.shortcuts import render
from .models import Color
from .forms import ColorForm
from .serializers import TaskSerializer
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
# Create your views here.
def index(request):
d = {
'colors': Color.objects.all(),
'form': ColorForm(),
}
return render(request, 'index.html', d)
class TaskGet(APIView):
def get(self, request, format=None):
obj = Color.objects.all()
serializers = TaskSerializer(obj, many=True)
return Response(serializers.data, status.HTTP_200_OK)
I wrote url(r'api/get',views.TaskGet.as_view(),name='task-get') in urls.py,so I really cannot understand why this error happens.I already run commands of migration of model. How can I fix this?
My ideal web page is like
You try get status by foreign key instance.status.status but in your model class Color i don't see any foreign keys or methods for it.
And for task_name did you want to see the model field name try to add source params
task_name = serializers.CharField(max_length=100, source='name')
# ^^^^^^^^^
are you sure you want serialize Task for model Color?
new edit
in your get_task_status the 'instanceis instance of serializer model, so if your modelColorhas no property or methodstatus` you will catch an error
I started to code a two-apps django project. ModelA belongs to appone and ModelB belongs to apptwo. My purpose is to create a ModelA instance everytime that the user creates a ModelB instance. And the value of a ModelA CharField (that is ckeditor widgeted) must be the source code of a ModelB admin view. I used a post_data signal to link a function of creation for that. The problem is that i use the id of each instance of ModelB in order to create the good content for each instance of ModelA. When I try to use a string of the url sending the id parameter, the content field has for value the source code of the debug page
(error 500, DoesNotExist at /admin/apptwo/modelb/my_view/ref=76, [76 is an example] ModelB matching query does not exist. Exception location : /home/me/Desktop/env/lib/python3.5/site-packages/django/db/models/query.py in get, line 385)
But when I try to visit the url "http://localhost:8000//admin/apptwo/modelb/my_view/ref=76", or when I hardcode the url, without a str(instance.id), the page exists and everything works perfectly.
I don't understand why.
Could anybody give me some help to solve this problem ?
Thanks in advance,
PS :
The first app has a model.py that contains the following code :
from django.db import models
from django.contrib.auth.models import User
from registre.models import *
class ModelA(models.Model):
content = models.CharField(max_length=255, null=True)
def __str__(self):
return "ModelA : " + str(self.id)
the admin.py of this first app also contains :
from django.contrib import admin
from appone.models import *
from apptwo.models import ModelB
from django.http import HttpResponse
from django.template.response import TemplateResponse
from django.conf.urls import url
from registre import views
from django.db.models.signals import post_save
from django.dispatch import receiver
import datetime
from django.contrib.auth.models import User
from django import forms
from ckeditor.widgets import CKEditorWidget
from django.template.loader import render_to_string
import requests
class ModelAAdminForm(forms.ModelForm):
content = forms.CharField(widget=CKEditorWidget())
class Meta:
model = ModelA
fields = '__all__'
class ModelAAdmin(admin.ModelAdmin):
form = ModelAAdminForm
def create_A(sender, instance, **kwargs):
string = "http://localhost:8000/admin/apptwo/modelb/my_view/ref=" + str(instance.id)
r = requests.get(string)
ModelA.objects.create(contenu=r.text.encode('utf-8'))
post_save.connect(create_A, sender=ModelB)
admin.site.register(ModelA, ModelAAdmin)
the second app (apptwo) has a models.py like this :
from django.db import models
from django.contrib.auth.models import User
class ModelB(models.Model):
owner = models.ForeignKey(User, null=True)
name = models.CharField(max_length=255, null=True)
def __str__(self):
return self.name
and an admin.py that contains :
from django.contrib import admin
from appone.models import *
from apptwo.models import *
import datetime
from django.conf.urls import url, include
from django.template.response import TemplateResponse
class ModelBAdmin(admin.ModelAdmin):
def get_queryset(self, request):
qs = super(ModelB, self).get_queryset(request)
if request.user.is_superuser:
return qs
return qs.filter(owner=request.user)
def save_model(self, request, obj, form, change):
obj.owner = request.user
obj.save()
def get_urls(self):
urls = super(ModelBAdmin, self).get_urls()
my_urls = [
url(r'^my_view/ref=(?P<id>\d+)$', self.my_view),
]
return my_urls + urls
def my_view(self, request, id):
context = dict(
self.admin_site.each_context(request),
selector = ModelB.objects.get(id=id),
)
return TemplateResponse(request, "myview.html", context)
admin.site.register(ModelB, ModelBAdmin)
and finally a template myview.html with :
<p>Test {{ selector.name }}</p>
I'm having issue with the get_or_create statement. It gets the record if there is one but isnt creating a record. I have defaults in all of my model fields.
My view.py
from django.contrib.auth.decorators import login_required
from django.shortcuts import render, HttpResponseRedirect, Http404, get_object_or_404
from django.contrib.auth import logout, login, authenticate
from django.contrib.auth.models import User
from django.contrib import messages
from django.core.urlresolvers import reverse
from django.utils.safestring import mark_safe
# Create your views here.
from .models import UserProfile
#login_required
def profile_view(request):
user = request.user
account = request.user
profile = UserProfile.objects.get_or_create(UserProfile, user=user)
context = {'profile': profile, 'account': account, }
template = 'profiles/profile.html'
return render(request, template, context)
The traceback im getting is:
ypeError at /profiles/
get_or_create() takes exactly 1 argument (3 given)
Request Method: GET
Request URL: http://127.0.0.1:8000/profiles/
Django Version: 1.6.5
Exception Type: TypeError
Exception Value:
get_or_create() takes exactly 1 argument (3 given)
The models.py im working on is:
class UserProfile(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL)
city = models.CharField(max_length=120, default="Add your city")
country = models.CharField(max_length=120, default="Add your country") #(max_length=2, choices=[(x[0], x[3]) for x in country.COUNTRIES])
zipcode = models.CharField(max_length=8, default="Add your zip/postcode")
birthyear = models.IntegerField(max_length=4, default="Add your birthyear")
timestamp = models.DateTimeField(auto_now_add=True, auto_now=False)
updated = models.DateTimeField(auto_now_add=False, auto_now=True)
def __unicode__(self):
return str(self.user.username)
class Meta:
ordering = ['-updated', '-timestamp']
You don't need to pass the model class to the method.
profile = UserProfile.objects.get_or_create(UserProfile, user=user)
should be
profile, created = UserProfile.objects.get_or_create(user=user)