Foreign key with multiple models? - django

I am creating ecommerce website. There are multiple categories. For example, phones, computers and others. I created a model for each of them. In OrderItems I want to foreign key each of them. So, I want to use multiple models in ForeignKey.
models.py
class Telefon(models.Model):
name = models.CharField(max_length=200)
category = models.CharField(max_length=300, choices=TELEFON, default="xiaomi")
price = models.FloatField()
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 TV(models.Model):
name = models.CharField(max_length=200)
category = models.CharField(max_length=300, choices=TELEFON, default="xiaomi")
price = models.FloatField()
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
Product={'Telefon', 'TV'}
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
So, how can I use multiple models in Foreign Key field in my OrderItems model.

Related

Django Admin, show inline based on slug

Have the following models
class FootballWebsite(models.Model):
"""Football service website."""
url = models.URLField, unique=True)
#football service
id = models.CharField(primary_key=True,
#is this domain blocked
blocked = models.BooleanField(default=False)
#is it online or offline
online = models.BooleanField(default=False)
updated = models.DateTimeField(auto_now=True, auto_now_add=True)
sub_categories = models.ForeignKey(SubCategory, default=1)
referral = models.TextField(blank=True)
mirror = models.ForeignKey('FootballWebsite', blank=True, null=True)
rank = models.PositiveIntegerField(default=0, blank=True, null=True)
screenshot = models.BooleanField(default=False)
class Meta:
"""Meta class."""
app_label = 'ahmia'
def __unicode__(self):
return u'%s' % (self.url)
"""The datetime when the football service was last seen online"""
try:
return self.footballwebsitestatus_set.filter(online=True).latest('time').time
except FootballWebsiteStatus.DoesNotExist:
return None
class FootballWebsiteDescription(models.Model):
"""Football service website description."""
about = models.ForeignKey(Footballebsite)
title = models.TextField(blank=True, null=True)
keywords = models.TextField(blank=True, null=True)
description = models.TextField(blank=True, null=True)
relation = models.URLField(blank=True, null=True)
subject = models.TextField(blank=True, null=True)
type = models.TextField(blank=True, null=True)
updated = models.DateTimeField(auto_now=True, auto_now_add=True)
language = models.TextField(null=True, blank=True)
contactInformation = models.TextField(null=True, blank=True)
officialInfo = models.BooleanField(default=False)
slug = AutoSlugField(populate_from=['title'], allow_duplicates=True, null=True)
class Meta:
"""Meta class."""
app_label = 'ahmia'
def __unicode__(self):
return unicode(self.about.url)
def save(self, *args, **kwargs):
self.slug = slugify(self.title)
super(FootballebsiteDescription, self).save(*args, **kwargs)
def __unicode__(self):
return u'%s' % (self.title)
I have a huge amount of links, and i would like to bulk assign them into a category or mark them as blocked based on identical title slug.
Managed to at least get a list of title_slugs with the code below, but the following step, i would like to get an inline list with all sites that have an identical title_slug and bulk assign those all in their a category
class FootballWebsiteInline(admin.TabularInline):
model = FootballWebsite
class FootballWebsiteDescriptionAdmin(admin.ModelAdmin):
list_display = ['show_slug']
def show_slug(self, obj):
return format_html("<a href='{url}'>{url}</a>", url=obj.slug)
inlines = [
FootballWebsiteInline,
]
Above code obviously doesn' t work, since the title slug which can appear many times is not a primary key.
Is it possible to get an inline list based on the title slug in this case which is not a primary key at all, or am i going about this the wrong way?
When possible at all, some further tweaking would be to group the identical title slugs

Django Rest Framework how to serialize a many to many relational Model?

I am doing a project in Django Rest Framework. Now I am trying to serialize many to many relations, but I don't know how this works. Here is my models' code:
Model for files
def user_directory_path(instance, filename):
return 'user_{0}/{1}'.format(instance.user.id, filename)
class Document(models.Model):
name = models.CharField(max_length=250, blank=True, null=True)
document = models.FileField(upload_to=user_directory_path)
def __str__(self):
return self.name
Model for Expenses and loans
class Expenses(models.Model):
name = models.CharField(max_length=250, blank=True, null=True)
amount = models.DecimalField(default=0.0, decimal_places=2, max_digits=10)
date = models.DateField(auto_now=True)
additional_files = models.ManyToManyField(Document, blank=True, related_name="expenses") # Upload multiple files
def __str__(self):
return self.name
class Loans(models.Model):
name = models.CharField(max_length=250, blank=True, null=True)
amount = models.DecimalField(default=0.0, decimal_places=2, max_digits=10)
loan_from = models.CharField(max_length=250, blank=True, null=True)
date = models.DateField(auto_now=True)
additional_files = models.ManyToManyField(Document, blank=True, related_name="loans") # Upload multiple files
def __str__(self):
return self.name
My question:
Just want to know how to serialize these additional_files in the Expenses and Loans.
It will be much better if give resources and explanations of how that works.
For List endpoint you could make something like that:
serializers.py
class ListDocumentSerializer(serializers.Serializer):
# Document fields
class ListLoansSerializer(serializers.Serializer):
name = serializers.CharField()
additional_files = ListDocumentSerializer(many=True)
# other loans model fields
views.py
class ListLoansApi(APIView):
permission_classes = []
def get(self, request):
loans = Loans.objects.prefetch_related('additional_files') # prefetch_related for ORM optimization with M2M
loans_data = ListDoctorSerializer(loans, many=True).data
return Response(loans_data)

Unable to Understand the below statements of models in Django

I am naive in Django, I have done a sample E-commerce application that is present online. I am unable to understand the highlighted statements, I searched online but unable to understand the statements.
Can someone please explain me like below
productitems = self.name_set.all()
From where this name_set.all() came ?????????
orderItems = self.orderitem_set.all()
likewise from where orderitem_set.all() ?????????
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.DecimalField(max_digits=7,decimal_places=2)
digital = models.BooleanField(default=False,null=True,blank=False)
image = models.ImageField(null=True,blank=True)
#image
def __str__(self):
return self.name
#property
def imageURL(self):
try:
url = self.image.url
except:
url = ''
return url
#property
def get_product_total(self):
**productitems = **self.name_set.all()****
total = sum([item.get_total for item in productitems])
return total
print('total:',total)
class Order(models.Model):
customer = models.ForeignKey(Customer,on_delete=models.SET_NULL,blank=True,null=True)
date_ordered=models.DateTimeField(auto_now_add=True)
complete = models.BooleanField(default=False,null=True,blank=False)
transaction_id = models.CharField(max_length=200, null=True)
def __str__(self):
return str(self.id)
#property
def shipping(self):
shipping = False
orderItems = **self.orderitem_set.all()**
for i in orderItems:
if i.product.digital == False:
shipping = True
return shipping
#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,blank=True,null=True)
order = models.ForeignKey(Order, on_delete=models.SET_NULL, blank=True, null=True)
quantity=models.IntegerField(default=0,blank=True,null=True)
date_added=models.DateTimeField(auto_now_add=True)
def __str__(self):
return str(self.product)
#property
def get_total(self):
print(self.product.price)
# print("self.product.price:",self.product.price)
# print("self.quantity:", self.quantity)
total = self.product.price * self.quantity
return total
class ShippingAddress(models.Model):
customer = models.ForeignKey(Customer,on_delete=models.SET_NULL,blank=True,null=True)
order = models.ForeignKey(Order, on_delete=models.SET_NULL, 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)
date_added = models.DateTimeField(auto_now_add=True)
def __str__(self):
return str(self.address)
Those are reverse foreign key lookups. The {field_name}_set pattern is what Django uses by default if you don't define a different term yourself.
The Django documentation explains it more here https://docs.djangoproject.com/en/3.1/ref/models/fields/#django.db.models.ForeignKey.related_name
and here https://docs.djangoproject.com/en/3.1/topics/db/queries/#following-relationships-backward
An example from the docs is:
>>> b = Blog.objects.get(id=1)
>>> b.entry_set.all() # Returns all Entry objects related to Blog.
Instead of using the default you can set the related lookup to a custom value when defining the ForeignKey field on the model, using the related_name argument. I do this often myself, there are usually more fitting terms for the project than the default.

Django: Names are not showing in drop-down list

I need to show a list of countries for users to select from the ship's country field. But it's showing the Country object(1), Country object(2)... instead of showing names of countries
I've created classes for Ship and Country with the Ship class having a foreign key of country.
class Ship(models.Model):
# Fields
name = models.CharField(max_length=255)
slug = extension_fields.AutoSlugField(populate_from='name', blank=True)
created = models.DateTimeField(auto_now_add=True, editable=False)
callsign = models.CharField(max_length=50)
last_updated = models.DateTimeField(auto_now=True, editable=False)
weight = models.DecimalField(max_digits=20, decimal_places=4)
# RelationShip Fields
shipflag = models.ForeignKey(
'manifest.Country', on_delete=models.SET_NULL,
related_name="Ships", null=True
)
class Meta:
ordering = ('-created',)
def __unicode__(self):
return u'%s' % self.slug
def get_absolute_url(self):
return reverse('manifest_Ship_detail', args=(self.slug,))
def get_update_url(self):
return reverse('manifest_Ship_update', args=(self.slug,))
class Country(models.Model):
# Fields
name = models.CharField(max_length=255)
slug = extension_fields.AutoSlugField(populate_from='name', blank=True)
created = models.DateTimeField(auto_now_add=True, editable=False)
last_updated = models.DateTimeField(auto_now=True, editable=False)
code = models.CharField(max_length=5)
# RelationShip Fields
continent = models.ForeignKey(
'manifest.Continent',
on_delete=models.CASCADE, related_name="Countrys",
)
class Meta:
ordering = ('-created',)
def __unicode__(self):
return u'%s' % self.slug
def get_absolute_url(self):
return reverse('manifest_Country_detail', args=(self.slug,))
def get_update_url(self):
return reverse('manifest_Country_update', args=(self.slug,))
In the 'create new ship' form at the country dropdown combo I expect to see a list of countries like United States, Mexico, Canada... but instead am seeing countries as objects like this object(1), Country object(2)...
add this method to your models. ;)
def __str__(self):
return self.name

Django Cart - multiple configuration options for a product

I want to create a Django web-application where users can add items to a cart.
Without the models Colour and Size this works so far.
My Problem is, that i can not figure out how to implement the configuration-options (for example) Colour and Size the right way.
I added both "Options" with a Many-to-One relationship. I now can add multiple colours and sizes for a Product, but do not know how to save the choosen "Option" in an CartEntry
This is what i got so far:
from django.db import models
from django.contrib.auth.models import User
class Product(models.Model):
name = models.CharField(max_length=256)
price = models.DecimalField(max_digits=6, decimal_places=2)
def __str__(self):
return str(self.name)
class Colour(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE, related_name="rel_colour")
option = models.CharField(max_length=24)
price = models.DecimalField(max_digits=6, decimal_places=2)
def __str__(self):
return str(self.colour)
class Size(models.Model):
product =models.ForeignKey(Product, on_delete=models.CASCADE, related_name="rel_size")
option = models.CharField(max_length=24)
price = models.DecimalField(max_digits=6, decimal_places=2)
def __str__(self):
return str(self.size)
class Cart(models.Model):
user = models.ForeignKey(User, null=True, blank=True, on_delete=models.CASCADE)
products = models.ManyToManyField(Product, blank=True)
updated = models.DateTimeField(auto_now=True)
timestamp = models.DateTimeField(auto_now_add=True)
def __str__(self):
return str(self.id) + ' - ' + str(self.user)
class CartEntry(models.Model):
product = models.ForeignKey(Product, null=True, on_delete=models.CASCADE)
cart = models.ForeignKey(Cart, null=True, on_delete=models.CASCADE)
quantity = models.PositiveIntegerField()
def __str__(self):
return str(self.quantity) + ', ' + str(self.product.name)
Maybe i can not user relations for CartEntry here?
why not do like this:
from django.db import models
from django.contrib.auth.models import User
class Product(models.Model):
name = models.CharField(max_length=256)
colour = models.ForeignKey(Colour, on_delete=models.CASCADE)
size = models.ForeignKey(Size, on_delete=models.CASCADE)
price = models.DecimalField(max_digits=6, decimal_places=2)
def __str__(self):
return str(self.name)
class Colour(models.Model):
name = models.CharField(max_length=24)
def __str__(self):
return str(self.name)
class Size(models.Model):
name = models.CharField(max_length=24)
def __str__(self):
return str(self.name)
so every product has different colour and size. or if you want make a Product as a "parent" you can add 1 more model like let say VariantProduct
class Product(models.Model):
name = models.CharField(max_length=256)
def __str__(self):
return str(self.name)
class VariantProduct(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE)
name = models.CharField(max_length=256)
colour = models.ForeignKey(Colour, on_delete=models.CASCADE)
size = models.ForeignKey(Size, on_delete=models.CASCADE)
price = models.DecimalField(max_digits=6, decimal_places=2)
def __str__(self):
return str(self.name)