django admin page customization - python

This is what I did in my models.py folder
class Product(models.Model):
name = models.CharField(max_length=200, null=True)
price = models.FloatField()
digital = models.BooleanField(default=False, null=True, blank=False)
image = models.ImageField(null=True, blank=True)
def __str__ (self):
return self.name
But am getting this as my result in my django admin page
And I want to display the products by their name
PRODUCT
Product object (2)
Product object (1)
2 products

Make sure __str__ is a method of your Product class and not a function of your models file.
class Product(models.Model):
name = models.CharField(max_length=200, null=True)
price = models.FloatField()
digital = models.BooleanField(default=False, null=True, blank=False)
image = models.ImageField(null=True, blank=True)
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=False)
image = models.ImageField(null=True, blank=True)
def __str__ (self):
return self.name
def__Str__(self):
return self.name
it's return objects.name

Related

How can I solve this indentation problem in my Django project

I'm a beginner in Django.
I was trying to add a method inside the OrderItem class. But the visual studio code is showing an indentation error.
I'm not sure what is wrong here.
Anyone can help me, please?
Here is the code:
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class Customer(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, null=True, blank=True)
name = models.CharField(max_length=200, null=True)
email = models.CharField(max_length=200, null=True)
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 needs to be added
image = models.ImageField(null=True, blank=True)
def __str__(self):
return self.name
#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, null=True, blank=True)
transaction_id = models.CharField(max_length=200, null=True)
def __str__(self):
return str(self.id)
class OrderItem(models.Model):
product = models.ForeignKey(Product, on_delete=models.SET_NULL, null=True)
order = models.ForeignKey(Order, on_delete=models.SET_NULL, null=True)
quantity = models.IntegerField(default=1, null=True, blank=True)
date_added = models.DateTimeField(auto_now_add=True)
#property
def get_total(self):
return self.product.price * self.quantity
The indentation error is showing on the #property and get_total()
class OrderItem(models.Model):
product = models.ForeignKey(Product, on_delete=models.SET_NULL, null=True)
order = models.ForeignKey(Order, on_delete=models.SET_NULL, null=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
Pelase see the attached screenshot.
The #property decorator should be indented at the same level of the method and fields, so:
class OrderItem(models.Model):
product = models.ForeignKey(Product, on_delete=models.SET_NULL, null=True)
order = models.ForeignKey(Order, on_delete=models.SET_NULL, null=True)
quantity = models.IntegerField(default=1, blank=True)
date_added = models.DateTimeField(auto_now_add=True)
#property
def get_total(self):
return self.product.price * self.quantity
Likely you want the quantity to be by default 1. It is also not clear to me why that is a nullable field.
As a general rule-of-thumb please do not mix spaces and tabs. It might be better to always use spaces.

How to count reviews for a product in django?

I am building an ecommerce website with django. In my models I have a Product and review model. How should i connect the two for the number of reviews and average rating attribute?
This is my current models file
class Product(models.Model):
name = models.CharField(max_length=200, null=True, blank=True)
brand = models.CharField(max_length=200, null=True, blank=True)
image = models.ImageField(null=True, blank=True, default='placeholder.png')
description = models.TextField(null=True, blank=True)
rating = models.DecimalField(max_digits=7, decimal_places=2, null=True, blank=True)
price = models.DecimalField(max_digits=7, decimal_places=2, null=True, blank=True)
countInStock = models.IntegerField(null=True, blank=True, default=0)
id = models.UUIDField(default=uuid.uuid4, max_length=36, unique=True, primary_key=True, editable=False)
numReviews = [Count the number of reviews where product.id matches self.id]
averageRating = [Sum up the ratings in reviews for this product and divide them by their count]
def __str__(self):
return str(self.name)
class Review(models.Model):
product = models.ForeignKey(Product, on_delete=models.SET_NULL, null=True)
user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
rating = models.IntegerField(null=True, blank=True, default=0)
comment = models.TextField(null=True, blank=True)
createdAt = models.DateTimeField(auto_now_add=True)
id = models.UUIDField(default=uuid.uuid4, max_length=36, unique=True, primary_key=True, editable=False)
def __str__(self):
return f'{self.user} review for {self.product}'
As you can see the numReviews and average rating columns are meant to connect both tables. I have been trying to figure out how to do it correctly with no success.
Any help would be greatly appreciated
I would make them into model methods.. I don't think there will be any issues that the Review object is defined below the method
and for the Avg I used a Django command aggregate which forces the DB to do the work.
models.py
class Product(models.Model):
name = models.CharField(max_length=200, null=True, blank=True)
brand = models.CharField(max_length=200, null=True, blank=True)
image = models.ImageField(null=True, blank=True, default='placeholder.png')
description = models.TextField(null=True, blank=True)
rating = models.DecimalField(max_digits=7, decimal_places=2, null=True, blank=True)
price = models.DecimalField(max_digits=7, decimal_places=2, null=True, blank=True)
countInStock = models.IntegerField(null=True, blank=True, default=0)
id = models.UUIDField(default=uuid.uuid4, max_length=36, unique=True, primary_key=True, editable=False)
def __str__(self):
return str(self.name)
def num_of_reviews(self):
return Review.objects.filter(product=self).count()
def average_rating(self):
from django.db.models import Avg
return Review.objects.filter(product=self).aggregate(Avg('rating'))['rating__avg']
Use
obj = Product.objects.all().first()
obj.num_of_reviews()
obj.average_rating()
Edit
Reverse relationship per #NixonSparrow
def num_of_reviews(self):
return self.review_set.count()
def average_rating(self):
from django.db.models import Avg
return self.review_set.aggregate(Avg('rating'))['rating__avg']

How to filter Many to Many field in django admin page using a foreign key value?

I am trying to filter my many to many variation fields with respect to the product. means, I only want the variations related to the current product to show in the admin page. now its showing all the variations available for every product.
I added formfield_for_manytomany() function to my admin.py but how can I get the current product(id) in the cart or order to filter the variations?
most of the questions in stack overflow Is based on the current user, which is easy to get? but how should I get the specific product(id) that is opened in the admin panel.
admin.py
from django.contrib import admin
from .models import *
from products.models import Variation
class CartAdmin(admin.ModelAdmin):
list_display = ('cart_id', 'date_created')
class CartItemAdmin(admin.ModelAdmin):
list_display = ('user','cart', 'product', 'quantity','is_active')
def formfield_for_manytomany(self, db_field, request, **kwargs):
if db_field.name == "variation":
product = Products.objects.get(id='??') # how I get the current product in the cart or order
kwargs["queryset"] = Variation.objects.filter(product=product.id)
return super().formfield_for_manytomany(db_field, request, **kwargs)
admin.site.register(Cart, CartAdmin)
admin.site.register(CartItem, CartItemAdmin)
CartItem Model
class CartItem(models.Model):
user = models.ForeignKey(CustomUser, on_delete=models.CASCADE, null=True)
cart = models.ForeignKey(Cart, on_delete=models.CASCADE, null=True)
product = models.ForeignKey(Products, on_delete=models.CASCADE)
variation = models.ManyToManyField(Variation, blank=True)
quantity = models.IntegerField()
is_active = models.BooleanField(default=True)
created_date = models.DateTimeField(auto_now_add=True)
def item_total(self):
return self.product.price * self.quantity
def __str__(self):
return self.product.name
Product and Variation Model
class Products(models.Model):
name = models.CharField(max_length=50, unique=True)
slug = AutoSlugField(populate_from='name', max_length=100, unique=True)
isbn = models.CharField(max_length=20, unique=True, blank=True, null=True)
sub_category = models.ForeignKey(SubCategory, on_delete=models.CASCADE)
language = models.ForeignKey(Language, on_delete=models.SET_NULL, null=True)
author = models.CharField(max_length=100)
Publisher = models.CharField(max_length=100, blank=True, default=None)
release_date = models.DateField(blank=True, null=True, default=None)
price = models.IntegerField(default=None)
stock = models.IntegerField(default=None)
is_available = models.BooleanField(default=True)
cover_image = models.ImageField(upload_to='images/products')
image1 = models.ImageField(upload_to='images/products', blank=True, default=None, null=True)
image2 = models.ImageField(upload_to='images/products', blank=True, default=None, null=True)
image3 = models.ImageField(upload_to='images/products', blank=True, default=None, null=True)
description = models.TextField(max_length=2000, blank=True, default=None)
create_date = models.DateTimeField(auto_now_add=True)
modified_date = models.DateTimeField(auto_now=True)
number_of_pages = models.IntegerField(blank=True, null=True)
weight = models.IntegerField(blank=True, null=True)
width = models.IntegerField(blank=True, null=True)
height = models.IntegerField(blank=True, null=True)
spine_width = models.IntegerField(blank=True, null=True)
class Meta:
verbose_name = 'Product'
verbose_name_plural = 'Products'
def get_url(self):
return reverse('product-view', args=[self.slug])
def __str__(self):
return self.name
class Variation(models.Model):
product = models.ForeignKey(Products, on_delete=models.CASCADE)
variation_category = models.CharField(max_length=100, choices=variation_category_choice)
variation_value = models.CharField(max_length=100, choices=variation_value_choice)
is_available = models.BooleanField(default=True)
date_added = models.DateTimeField(auto_now_add=True)
objects = VariationManager()
def __str__(self):
return self.variation_value

how to create row in model based on data fetched from JSON request from third-party crawling with "best practice"

describe the problem:
I want to crawl data from dataforseo , and save them directly in model database through model.create() method with having multi model with multi relation with models
so for instance in model A have
ManyToMany relation with model B
ManyToMany relation with model C
ManyToMany relation with model D
and model B have relation with model C
so my question is how to save JSON response to all model mentioned above smoothly through model A create Method
response came from request:
[
{
"title":"title",
"url":"url",
"description":"description",
"pre_snippet":"pre_snippet",
"extended_snippet":"extended_snippet",
"images":"images",
"amp_version":"amp_version",
"rating":{
"rating_type":"rating_type",
"value":"value",
"votes_count":"votes_count",
"rating_max":"rating_max"
},
"price":{
"current":"current",
"regular":"regular",
"max_value":"max_value"
},
"highlighted":{
"name_highlighted":"name_highlighted"
}
},
{
"title":"title",
"url":"url",
"description":"description",
"pre_snippet":"pre_snippet",
"extended_snippet":"extended_snippet",
"images":"images",
"amp_version":"amp_version",
"rating":{
"rating_type":"rating_type",
"value":"value",
"votes_count":"votes_count",
"rating_max":"rating_max"
},
"price":{
"current":"current",
"regular":"regular",
"max_value":"max_value"
},
"highlighted":{
"name_highlighted":"name_highlighted"
}
}
]
Code:
view.py file
#api_view(['POST'])
#parser_classes((JSONParser,))
def crawl_data(request):
"""
A view that can accept POST requests with JSON content.
"""
Product.create(
title=request.data[title]
url=request.data[url]
describtion=request.data[describtion]
...
)
return Response({'received data': request.data})
models.py
class Highlighted(models.Model):
name_highlighted = models.CharField(max_length=100)
def __str__(self):
return str(self.name_highlighted)
class Rating(models.Model):
rating_type = models.CharField(max_length=500, null=True, blank=True) # make unique
value = models.CharField(max_length=500, null=True, blank=True)
votes_count = models.CharField(max_length=500, null=True, blank=True)
rating_max = models.CharField(max_length=500, null=True, blank=True)
def __str__(self):
return str(self.value)
class Price(models.Model):
current = models.CharField(max_length=500, null=True, blank=True, default="none")
regular = models.CharField(max_length=500, null=True, blank=True)
max_value = models.CharField(max_length=500, null=True, blank=True)
def __str__(self):
return str(self.current)
class Product(models.Model):
title = models.CharField(max_length=500, null=True, blank=True)
url = models.CharField(max_length=500, null=True, blank=True)
description = models.CharField(max_length=500, null=True, blank=True)
pre_snippet = models.CharField(max_length=500, null=True, blank=True)
extended_snippet = models.CharField(max_length=500, null=True, blank=True)
images = models.CharField(max_length=500, null=True, blank=True)
amp_version = models.CharField(max_length=500, null=True, blank=True)
rating = models.ManyToManyField(Rating, null=True, blank=True)
price = models.ManyToManyField(Price, null=True, blank=True)
highlighted = models.ManyToManyField(Highlighted)
def __str__(self):
return str(self.url)
any help appreciate it
you can do override create method by do the following in your models.py file :
try this out:
in product model you can override create model like so
class Product(models.Model):
title = models.CharField(max_length=500, null=True, blank=True)
url = models.CharField(max_length=500, null=True, blank=True)
description = models.CharField(max_length=500, null=True, blank=True)
pre_snippet = models.CharField(max_length=500, null=True, blank=True)
extended_snippet = models.CharField(max_length=500, null=True, blank=True)
images = models.CharField(max_length=500, null=True, blank=True)
amp_version = models.CharField(max_length=500, null=True, blank=True)
rating = models.ManyToManyField(Rating, null=True, blank=True)
price = models.ManyToManyField(Price, null=True, blank=True)
highlighted = models.ManyToManyField(Highlighted)
extended_people_also_search = models.ManyToManyField(ExtendedPeopleAlsoSearch)
def __str__(self):
return str(self.url)
#classmethod
def create(cls, **kwargs):
product = cls.objects.create(
title=kwargs['title'],
url=kwargs['url'],
description=kwargs['description'],
pre_snippet=kwargs['pre_snippet'],
extended_snippet=kwargs['extended_snippet'],
images=kwargs['images'],
amp_version=kwargs['amp_version'],
)
# add price dict
price, created = Price.objects.get_or_create(current=kwargs['price']["current"],
regular=kwargs['price']["regular"],
max_value=kwargs['price']["max_value"],
)
product.price.add(price)
# add rating dict
rating, created = Rating.objects.get_or_create(rating_type=kwargs['rating']["rating_type"],
value=kwargs['rating']["value"],
votes_count=kwargs['rating']["votes_count"],
rating_max=kwargs['rating']["rating_max"],
)
product.rating.add(rating)
return product
def __str__(self):
return str(self.url)
and in your views.py in function crawl you can just iterate through your JSON response and just add them to your model like below:
#api_view(['POST'])
#parser_classes((JSONParser,))
def crawl_data(request):
"""
A view that can accept POST requests with JSON content.
"""
for product_data in request.data:
product = Product.create(**product_data)
# DO SOMETHING WITH product
return Response({'received data': request.data})

how to add photo

I have a simple model, witch is used as a form .
class Test(models.Model):
name = models.CharField(max_length=100, unique=True, db_index=True)
location = models.CharField(max_length=300)
details = models.TextField()
def __unicode__(self):
return self.image.name
I would like to add the following class Album as a foreign key to Test :
class Album(models.Model):
title = models.CharField(max_length=60)
public = models.BooleanField(default=False)
def __unicode__(self):
return self.title
class Tag(models.Model):
tag = models.CharField(max_length=50)
def __unicode__(self):
return self.tag
class Image(models.Model):
title = models.CharField(max_length=60, blank=True, null=True)
image = models.FileField(upload_to="images/")
tags = models.ManyToManyField(Tag, blank=True)
albums = models.ManyToManyField(Album, blank=True)
created = models.DateTimeField(auto_now_add=True)
rating = models.IntegerField(default=50)
width = models.IntegerField(blank=True, null=True)
height = models.IntegerField(blank=True, null=True)
user = models.ForeignKey(User, null=True, blank=True)
def __unicode__(self):
return self.image.name
Questions:
How to add class Album as a foreigh key to class Test?
How to put this relation on the form? - e.g. user is selecting multiple images for uploads wich results in unique Album related to Test class.
Do you mean something like this for the foreign-key
class Test(models.Model):
name = models.CharField(max_length=100, unique=True, db_index=True)
location = models.CharField(max_length=300)
details = models.TextField()
album = models.ForeignKey(Album, null=True, blank=True)
def __unicode__(self):
return self.name

Categories

Resources