In order to list my variations_value i render data into context but when i pass the object to the frontend it's recognised as a queryset but i can't use data from it
Model
variation_category_choice = (
('color', 'color',),
('size', 'size',),
)
class Variation(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE)
variation_category = models.CharField(max_length=100, choices=variation_category_choice)
variation_value = models.CharField(max_length=100)
is_active = models.BooleanField(default=True)
created_date = models.DateTimeField(auto_now=True)
def __unicode__(self):
return self.product
View
def product_detail(request, category_slug, product_slug):
try:
single_product = Product.objects.get(category__slug=category_slug, slug=product_slug)
in_cart = CartItem.objects.filter(cart__cart_id=_cart_id(request), product=single_product).exists()
variations = Variation.objects.filter(product=single_product)
except Exception as e:
raise e
context = {
'single_product': single_product,
'in_cart': in_cart,
'variations': variations
}
return render(request, 'store/product_detail.html', context)
HTML
<h1>{{variations.variation_value}}</h1>
Related
I am using django-yasg to create an api documentation. But no parameters are showing in the documentation to create post request. Following are my codes:
After that in swagger api, no parameters are showing for post request to create the event
model.py
class Events(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
category = models.ForeignKey(EventCategory, on_delete=models.CASCADE)
name = models.CharField(max_length=250, null=True)
posted_at = models.DateTimeField(null=True, auto_now=True)
location = models.CharField(max_length=100, null=True)
banner = models.ImageField(default='avatar.jpg', upload_to='Banner_Images')
start_date = models.DateField(
auto_now=False, auto_now_add=False, blank=True, null=True)
end_date = models.DateField(
auto_now=False, auto_now_add=False, blank=True, null=True)
description = models.TextField(max_length=2000, null=True)
completed = models.BooleanField(default=False)
def __str__(self):
return f'{self.name}'
class Meta:
verbose_name_plural = "Events"
serializers.py
class EventSerializer(serializers.ModelSerializer):
user = UserSerializer(read_only=True, many=False)
category = EventCategorySerializer(read_only=True, many=False)
class Meta:
model = Events
fields = '__all__'
views.py
#api_view(['POST'])
#permission_classes([IsAuthenticated])
#user_is_organization
#swagger_auto_schema(
request_body=EventSerializer
)
def registerEvent(request):
"""
To Register an events, you must be an organization
"""
data = request.data
print("==================")
print(data)
print("==================")
try:
Event = Events.objects.create(
user = request.user,
category=EventCategory.objects.get(category=data['category']),
name=data['name'],
location=data['location'],
start_date=data['start_date'],
end_date=data['end_date'],
description=data['description'],
completed=data['completed'],
)
serializer = EventSerializer(Event, many=False)
Event = Events.objects.get(id=serializer.data['id'])
Event.banner = request.FILES.get('banner')
Event.save()
serializer = EventSerializer(Event, many=False)
return Response(serializer.data)
except:
message = {'detail': 'Event with this content already exists'}
return Response(message, status=status.HTTP_400_BAD_REQUEST)
I got it running with following changes in views.py
#swagger_auto_schema(
methods=['post'],
request_body=openapi.Schema(
type=openapi.TYPE_OBJECT,
required=['category','name', 'location', 'start_date', 'end_date', 'description', 'completed', 'banner'],
properties={
'category':openapi.Schema(type=openapi.TYPE_STRING),
'name':openapi.Schema(type=openapi.TYPE_STRING),
'location':openapi.Schema(type=openapi.TYPE_STRING),
'start_date':openapi.Schema(type=openapi.TYPE_STRING, default="yyyy-mm-dd"),
'end_date':openapi.Schema(type=openapi.TYPE_STRING, default='yyyy-mm-dd'),
'description':openapi.Schema(type=openapi.TYPE_STRING),
'completed':openapi.Schema(type=openapi.TYPE_BOOLEAN, default=False),
'banner': openapi.Schema(type=openapi.TYPE_FILE),
},
),
operation_description='Create an events'
)
#api_view(['POST'])
#permission_classes([IsAuthenticated])
#user_is_organization
def registerEvent(request):
"""
To Register an events, you must be an organization
"""
data = request.data
print("==================")
print(data)
print(type(data))
category=EventCategory.objects.get(category=data['category']),
print(category)
print(type(data["start_date"]))
print("==================")
try:
Event = Events.objects.create(
user = request.user,
category=EventCategory.objects.get(category=data['category']),
name=data['name'],
location=data['location'],
start_date=data['start_date'],
end_date=data['end_date'],
description=data['description'],
completed=data['completed'],
)
print("****************************")
serializer = EventSerializer(Event, many=False)
Event = Events.objects.get(id=serializer.data['id'])
Event.banner = request.FILES.get('banner')
Event.save()
serializer = EventSerializer(Event, many=False)
return Response(serializer.data)
except ValidationError as e:
return Response({"ValidationError" : e}, status = status.HTTP_400_BAD_REQUEST)
except Exception as e:
message = {'error': e}
return Response(message, status=status.HTTP_400_BAD_REQUEST)
can you modify your swagger_auto_schema decorator like this?
#swagger_auto_schema(
methods=['post',],
request_body=EventSerializer )
All you need to do is place the #swagger_auto_schema on the top. To help it display the parameters create a serializer for it. This way, you only have to change the serializer in the future keeping everything in one place.
API view
#swagger_auto_schema(request_body=serializers.RequestSerializer, method='post')
#api_view(http_method_names=['POST'])
def special_get(request):
data = JSONParser().parse(request)
unique_id = data.get("unique_id", "")
...
Serializer.py
class RequestSerializer(serializers.Serializer):
unique_id = serializers.CharField(max_length=50, allow_null=False, allow_blank=True)
sentence_list = serializers.ListField(
child=serializers.CharField(allow_blank=False, trim_whitespace=True)
)
I'm creating an ebay style website that auctions off items. I have a form that takes in the values for the listing required by the model. The form renders well but when I submit the form I get the error:
<class 'TypeError'> views.py 80 ("l = Listing(title=title, description=description, url=url, user=user_id, category=category)")
forms.py
class NewListingForm(forms.Form):
title = forms.CharField(max_length=200)
description = forms.CharField(max_length=500)
url = forms.URLField()
bid = forms.DecimalField(decimal_places=2, max_digits=10)
category = forms.ModelChoiceField(queryset=Category.objects.all())
views.py
** added around line that's throwing the error
def newListing(request):
try:
if request.method == "POST":
newListingForm = NewListingForm(request.POST)
if newListingForm.is_valid():
title = newListingForm.cleaned_data['title']
description = newListingForm.cleaned_data['description']
url = newListingForm.cleaned_data['url']
bid = newListingForm.cleaned_data['bid']
category = newListingForm.cleaned_data['category']
current_user = request.user
user_id = current_user.id
**l = Listing(title=title, description=description, url=url, user=user_id, category=category)**
l.save()
b = Bid(price=bid, bid_count=0)
b.listing.add(l)
b.save()
return HttpResponseRedirect(reverse("index"))
else:
newListingForm = NewListingForm()
return render(request, "auctions/newListing.html", {
'form': newListingForm
})
except Exception as exc:
exc_type, exc_obj, exc_tb = sys.exc_info()
fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
print(exc_type, fname, exc_tb.tb_lineno)
newListingForm = NewListingForm()
return render(request, 'auctions/newListing.html', {
'form': newListingForm
})
models.py
class Listing(models.Model):
title = models.CharField(max_length=200)
description = models.CharField(max_length=500)
url = models.URLField()
user = models.ForeignKey('User', on_delete=models.CASCADE, name='author')
category = models.ForeignKey('Category', on_delete=models.CASCADE, name='category', default="")
def __str__(self):
return f'{self.id}: {self.title}'
class Bid(models.Model):
price = models.DecimalField(decimal_places=2, max_digits=10)
bid_count = models.IntegerField()
listing = models.ForeignKey('Listing', on_delete=models.CASCADE, name='listing', default="")
def __str__(self):
return f'{self.slug} ({self.price})'
User is a keyword, so I was getting an error from that.
I'm trying to create a new listing but I get this error:
(ValueError at /new
Cannot assign "'Work'": "Listing.category" must be a "Category" instance.)
Models.py
class Category(models.Model):
category = models.CharField(max_length=64)
def __str__(self):
return self.category
class Listing(models.Model):
title = models.CharField(max_length=64, default="")
starting_bid = models.CharField(max_length=64, default="$")
description = models.TextField(default="")
image_url = models.CharField(max_length=200, default="")
date = models.DateTimeField(default=timezone.now)
category = models.ForeignKey(Category, on_delete=models.CASCADE)
def __str__(self):
return self.title
views.py
def new_listing(request):
if request.method == "POST":
title = request.POST["title"]
starting_bid = request.POST["starting_bid"]
image_url = request.POST["image_url"]
category = request.POST["category"]
description = request.POST["description"]
ins = Listing(title=title, starting_bid=starting_bid, image_url=image_url, category=category, description=description)
ins.save()
categories = Category.objects.filter()
return render(request, "auctions/new_listing.html", { "categories": categories })
To set a value to the ForeignKey you need an object.
(ValueError at /new Cannot assign "'Work'": "Listing.category" must be
a "Category" instance.)
You can use instead an attribute with _id at the end or use the Category object.
category_id=category
# Get category object
Category.objects.get(name=category)
views.py:
def new_listing(request):
if request.method == "POST":
query = request.POST
title = query.get("title")
starting_bid = query.get("starting_bid")
image_url = query.get("image_url")
category = query.get("category")
description = query.get("description")
category_obj = Category.objects.get(name=category)
"""
ins = Listing(
title=title, starting_bid=starting_bid,
image_url=image_url, category_id=category,
description=description
)
"""
# OR
ins = Listing(
title=title, starting_bid=starting_bid,
image_url=image_url, category=category_obj,
description=description
)
ins.save()
categories = Category.objects.all()
return render(request, "auctions/new_listing.html", { "categories": categories })
Behind the scenes, Django appends "_id" to the field name to
create its database column name, see Django ForeignKey
Also I recommend you to Working with forms.
Hi I'm trying to develop an e-commerce website using Django. I have two models and views on separate folders, one is an order model and view, another is the checkout model and view. The order view creates a new order everytime an item is added to the cart. And the checkout view creates a new billing address. I want to associate the billing address that is created to the order when the checkout form is submitted. But for some reason, it's not happening. It throws an error:
MultipleObjectsReturned at /checkout/
get() returned more than one Order -- it returned 2!
What is the problem?
My orders.models.py:
from django.db import models
from shopping_cart.models import Cart
from django.contrib.auth import get_user_model
from accounts2.models import BillingAddress
STATUS_CHOICES = (
("Started", "Started"),
("Abandoned", "Abandoned"),
("Finished", "Finished"),
)
User = get_user_model()
class Order(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, blank=True, null=True)
order_id = models.CharField(max_length=120, default='ABC', unique=True)
cart = models.ForeignKey(Cart, on_delete=models.CASCADE)
status = models.CharField(max_length=120, choices=STATUS_CHOICES, default="Started")
sub_total = models.DecimalField(default=10.99, max_digits=1000, decimal_places=2)
tax_total = models.DecimalField(default=0.00, max_digits=1000, decimal_places=2)
final_total = models.DecimalField(default=10.99, max_digits=1000, decimal_places=2)
timestamp = models.DateTimeField(auto_now_add=True, auto_now=False)
billing_address = models.ForeignKey(BillingAddress, on_delete=models.SET_NULL, blank= True, null=True)
My orders.views.py:
#login_required
def order(request):
try:
the_id = request.session['cart_id']
cart = Cart.objects.get(id=the_id)
except:
the_id = None
return redirect(reverse("myshop-home"))
try:
new_order = Order.objects.get(cart=cart)
except Order.DoesNotExist:
new_order = Order(cart=cart)
new_order.cart = cart
new_order.user = request.user
new_order.order_id = id_generator()
new_order.save()
except:
return redirect(reverse("cart"))
if new_order.status == "Finished":
#cart.delete()
del request.session['cart_id']
del request.session['items_total']
return redirect(reverse("cart"))
context = {"address_form": address_form, "cart": cart}
template = "orders/checkout.html"
return render(request, template, context)
My accounts.models.py:
class BillingAddress(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete= models.CASCADE)
street_address = models.CharField(max_length=100)
apartment_address = models.CharField(max_length=100)
country = CountryField(multiple=False)
zip = models.CharField(max_length=100)
class Meta:
verbose_name_plural = "Billing Addresses"
My accounts.views.py:
class CheckoutView(LoginRequiredMixin, View):
def get(self, *args, **kwargs):
the_id = self.request.session['cart_id']
cart = Cart.objects.get(id=the_id)
form = CheckoutForm()
context = {"form": form, "cart": cart}
return render(self.request, "orders/checkout.html", context)
def post(self, *args, **kwargs):
form = CheckoutForm(self.request.POST or None)
try:
order = Order.objects.get(user = self.request.user)
if form.is_valid():
street_address = form.cleaned_data.get('street_address')
apartment_address = form.cleaned_data.get('apartment_address')
country = form.cleaned_data.get('country')
zip = form.cleaned_data.get('zip')
# same_shipping_address = form.cleaned_data.get('same_billing_address')
# save_info = form.cleaned_data.get('save_info')
payment_option = form.cleaned_data.get('payment_option')
billing_address = BillingAddress(
user = self.request.user,
street_address = street_address,
apartment_address = apartment_address,
country = country,
zip = zip
)
billing_address.save()
order.billing_address = billing_address
order.save()
return redirect('checkout')
messages.warning(self.request, "Failed checkout")
return redirect('checkout')
except ObjectDoesNotExist:
messages.warning(self.request, "You do not have an active order")
return redirect('/')
Use Order.objects.filter(user=user).last() to get the newest row or try to remember order's id when creating an order and filter with Order.objects.get(id=id)
It's a sort of cms type application
I have an article model and some specializations in models.py
class Article(models.Model):
foo = models.CharField(max_length=50)
bar = models.CharField(max_length=100,blank=True)
DISPLAY_CHOICES = (
('N', 'None'),
('C','Carousel'),
('M','Marketing'),
('F','Featurette')
)
display = models.CharField(max_length=1, choices = DISPLAY_CHOICES)
def __unicode__(self):
return self.title
class Artist(Article):
website = models.URLField(max_length=200,blank=True)
class Venue(Article):
location = models.CharField(max_length=150)
map_link = models.URLField(max_length=200,blank=True)
class Event(Article):
time = models.DateTimeField()
venue = models.ForeignKey(Venue)
performers = models.ManyToManyField(Artist)
I want to render these in different ways depending on the value of article.display but when I call
articles.objects.all()
I still need the extra attributes form the subclasses so I wrote
#views.py
def castToSubClass(article):
try:
return Artist.objects.get(article_ptr_id = article.id)
except:
try:
return Event.objects.get(article_ptr_id = article.id)
except:
try:
return Venue.objects.get(article_ptr_id = article.id)
except:
return article
def index(request):
carousel = [castToSubClass(article) for article in Article.objects.filter(display='C']
marketing = [castToSubClass(article) for article in Article.objects.filter(display='M'[:3]]
featurettes = [castToSubClass(article) for article in Article.objects.filter(display='F']
return render_to_response('frontpage.html',
{
'carousel': carousel,
'marketing':marketing,
'featurettes': featurettes
})
to turn them all in the appropriate subclass object, this apart from seeming clunky seems to mean I'm hitting the database twice for every (or nearly every) item in the queryset.
Is there a way to do this in the initial calls to the manager instead?
Thanks.
Use one model to store everything, and add a field to distinguish the article type, so that you can render different look for every type combine with display in the template(Like tumblr do).
class Article(models.Model):
foo = models.CharField(max_length=50)
bar = models.CharField(max_length=100,blank=True)
DISPLAY_CHOICES = (
('N', 'None'),
('C','Carousel'),
('M','Marketing'),
('F','Featurette')
)
display = models.CharField(max_length=1, choices = DISPLAY_CHOICES)
ARTICLE_TYPE_CHOICES = (
('artist', 'Artist'),
('venue', 'Venue'),
('event', 'Event'),
)
type = models.CharField(max_length=32, choices = ARTICLE_TYPE_CHOICES)
website = models.URLField(max_length=200,blank=True, null=True)
location = models.CharField(max_length=150, blank=True, null=True)
map_link = models.URLField(max_length=200,blank=True, null=True)
time = models.DateTimeField(null=True)
venue = models.ForeignKey('self', null=True)
performers = models.ManyToManyField('self', null=True)
def __unicode__(self):
return self.title
#views.py
def index(request):
carousel = Article.objects.filter(display='C')
marketing = Article.objects.filter(display='M')
featurettes = Article.objects.filter(display='F')
return render_to_response('frontpage.html',{'carousel': carousel, 'marketing':marketing, 'featurettes': featurettes})