Django polymorphism in model - django

i want to set diffirent sports to diffirent players
like below. is there anyway to do this?
Example Model :
class Player(models.Model):
id = models.AutoField(primary_key=True)
sportType = models.CharField(max_length=15)
sportObj = generic.GenericForeignKey('content_type')
class Icehockey(models.Model):
id = models.AutoField(primary_key=True)
stick_brand = models.CharField(max_length=50)
skate_number = models.IntegerField()
class Basketball(models.Model):
id = models.AutoField(primary_key=True)
ball_brand = models.CharField(max_length=50)
uniform_color= models.CharField(max_length=10)
class Football(models.Model):
id = models.AutoField(primary_key=True)
shoeNumber = models.IntegerField()
uniform_size = models.CharField(max_length=10)
Example Usage:
player1 = Player.objects.get(id=1).sportObj // returns <Icehockey object>
player2 = Player.objects.get(id=2).sportObj // returns <Basketball object>
player3 = Player.objects.get(id=3).sportObj // returns <Football object>
player4 = Player.objects.get(id=4).sportObj // returns <Football object>
edit :
there is a document on Django Website about How content types works if anyone needs it.

The example you have provided with looks OK to me, I have modified the models a bit to make them usable.
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
class Player(models.Model):
SPORT_CHOICES = (
('I', 'Icehockey'),
('B', 'Basketball'),
('F', 'Football'),
)
sportType = models.CharField(max_length=15,choices=SPORT_CHOICES)
sportObj = GenericForeignKey('content_type', 'object_id')
object_id = models.PositiveIntegerField()
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
class Icehockey(models.Model):
stick_brand = models.CharField(max_length=50)
skate_number = models.IntegerField()
class Basketball(models.Model):
ball_brand = models.CharField(max_length=50)
uniform_color= models.CharField(max_length=10)
class Football(models.Model):
shoeNumber = models.IntegerField()
uniform_size = models.CharField(max_length=10)

Related

How to use left join orm?

My model
class Ad_company(models.Model):
idx = models.AutoField(primary_key=True)
subject = models.CharField(max_length=255)
memo = models.CharField(max_length=255)
content = models.TextField()
is_display = models.CharField(max_length=1)
writer = models.CharField(max_length=255)
write_date = models.DateTimeField()
update_date = models.DateTimeField()
delete_date = models.DateTimeField()
deadline_date = models.DateTimeField()
reply = models.IntegerField(blank=True)
hits = models.IntegerField(blank=True)
ad_apply = models.IntegerField(blank=True)
ad_category1 = models.CharField(max_length=255)
ad_category2 = models.CharField(max_length=255)
ad_place = models.CharField(max_length=255)
ad_age = models.CharField(max_length=255)
ad_sex = models.CharField(max_length=255)
ad_budget = models.BigIntegerField()
ad_length = models.CharField(max_length=255)
is_done = models.CharField(max_length=1)
is_pay = models.CharField(max_length=1)
ad_service = models.CharField(max_length=255)
ad_object = models.CharField(max_length=255)
is_file = models.CharField(max_length=1)
ad_require = models.CharField(max_length=255)
class Meta:
managed = False
db_table = 'ad_write_company'
class Ad_company_apply(models.Model):
idx = models.AutoField(primary_key=True)
parent_idx = models.IntegerField()
username = models.CharField(max_length=255)
content = models.TextField()
date = models.DateTimeField(default=datetime.now, blank=True)
budget = models.BigIntegerField()
term = models.IntegerField()
is_done = models.CharField(max_length=1)
SELECT * FROM ad_write_company INNER JOIN ad_write_company_apply ON ad_write_company.idx = ad_write_company_apply.parent_idx where ad_write_company_apply.is_done = 1 and ad_write_company_apply.username = 'asdffdsa'
This is my query. but I can not make join query with orm.
Sorry for question is too short.
And Is my query right?
I not sure of that. Thanks for answer.
or do you guys have other good idea?
I would advise to work with a ForeignKey from Ad_company_apply to Ad_company. This makes it easier to generate queries in Django and will guarantee referential integrity.
It thus makes sense to rewrite the Ad_company_apply model to:
class Ad_company_apply(models.Model):
# …
parent_idx = models.ForeignKey(
Ad_company,
db_column='parent_idx',
on_delete=models.CASCADE
)
# …
In that case, you can .filter(…) [Django-doc] with:
Ad_Company.objects.filter(ad_company_appy__isdone=1, ad_company_appy__username='asdffdsa')
Note: Models in Django are written in PascalCase, not snake_case,
so you might want to rename the model from Ad_company to AdCompany.

I want to list all elements from abstract class Product and its categories (Smartphones, Tv ) etc

class ProductSerizer(serializers.ModelSerializer):
category = serializers.PrimaryKeyRelatedField(queryset=Category.objects)
title_of_product = serializers.CharField(required=True)
slug = serializers.SlugField(required=True)
image_of_product = serializers.ImageField(required=True)
description_of_product = serializers.CharField(required=True)
price_of_product = serializers.DecimalField(max_digits=12, decimal_places=2, required=True)
class Product(models.Model):
class Meta:
abstract = True
category = models.ForeignKey(Category, verbose_name="category", on_delete=models.CASCADE)
title_of_product = models.CharField(max_length=225,verbose_name="Title",null=True)
slug = models.SlugField(unique=True)
image_of_product = models.ImageField(verbose_name="Image", null=True)
description_of_product = models.TextField(verbose_name = "Descripwtion", null = True)
price_of_product = models.DecimalField(max_digits=10,decimal_places=2, verbose_name="Price", null=True)
and I want to list all elements from categories, but I cannot serialize this class. How should I do ?
Take a look at this thread, which talks about abtract models and how to serialize them

How do I combine my Django models so that I am not repeating myself?

I realize that the 3 models that I use right now have a ton of shared fields. I was wondering what the best way to condense these models would be. I've read some articles on metaclasses and model inheritance but wanted to see what the "best" way to do this would be.
models.py
class Car(models.Model):
created = models.DateTimeField(auto_now_add=True)
make = models.CharField(max_length=100)
model = models.CharField(max_length=100)
year = models.IntegerField(default=2021, validators=[MinValueValidator(1886), MaxValueValidator(datetime.now().year)])
seats = models.PositiveSmallIntegerField()
color = models.CharField(max_length=100)
VIN = models.CharField(max_length=17, validators=[MinLengthValidator(11)])
current_mileage = models.PositiveSmallIntegerField()
service_interval = models.CharField(max_length=50)
next_service = models.CharField(max_length=50)
class Truck(models.Model):
created = models.DateTimeField(auto_now_add=True)
make = models.CharField(max_length=100)
model = models.CharField(max_length=100)
year = models.IntegerField(default=datetime.now().year, validators=[MinValueValidator(1886), MaxValueValidator(datetime.now().year)])
seats = models.PositiveSmallIntegerField()
bed_length = models.CharField(max_length=100)
color = models.CharField(max_length=100)
VIN = models.CharField(max_length=17, validators=[MinLengthValidator(11)])
current_mileage = models.PositiveSmallIntegerField()
service_interval = models.CharField(max_length=50)
next_service = models.CharField(max_length=50)
class Boat(models.Model):
created = models.DateTimeField(auto_now_add=True)
make = models.CharField(max_length=100)
model = models.CharField(max_length=100)
year = models.PositiveSmallIntegerField(default=datetime.now().year, validators=[MaxValueValidator(datetime.now().year)])
length = models.CharField(max_length=100)
width = models.CharField(max_length=100)
HIN = models.CharField(max_length=14, validators=[MinLengthValidator(12)], blank=True)
current_hours = models.PositiveSmallIntegerField()
service_interval = models.CharField(max_length=50)
next_service = models.CharField(max_length=50)
I can notice that some fields are similar but aren't the same, for example year are not the same for all. Due to that I propose to you the following.
class TimeStampedModel(models.Model):
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
class Meta:
abstract = True
class Vehicule(TimeStampedModel):
make = models.CharField(max_length=100)
model = models.CharField(max_length=100)
service_interval = models.CharField(max_length=50)
next_service = models.CharField(max_length=50)
class Meta:
abstract = True
class WheeledVehicle(Vehicule):
seats = models.PositiveSmallIntegerField()
color = models.CharField(max_length=100)
VIN = models.CharField(max_length=17, validators=[MinLengthValidator(11)])
current_mileage = models.PositiveSmallIntegerField()
class Meta:
abstract = True
class Car(WheeledVehicle):
year = models.IntegerField(default=2021, validators=[MinValueValidator(1886), MaxValueValidator(datetime.now().year)])
class Truck(WheeledVehicle):
year = models.IntegerField(default=datetime.now().year, validators=[MinValueValidator(1886), MaxValueValidator(datetime.now().year)])
bed_length = models.CharField(max_length=100)
class Boat(Vehicule):
year = models.PositiveSmallIntegerField(default=datetime.now().year, validators=[MaxValueValidator(datetime.now().year)])
length = models.CharField(max_length=100)
width = models.CharField(max_length=100)
HIN = models.CharField(max_length=14, validators=[MinLengthValidator(12)], blank=True)
current_hours = models.PositiveSmallIntegerField()
And if you want to go further, I suggest you to add created_by and modified_by fields to audit.
class TimeStampedModel(models.Model):
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
class Meta:
abstract = True
class TimeStampedAuthModel(TimeStampedModel):
created_by = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, on_delete=models.SET_NULL,
related_name="%(app_label)s_%(class)s_created_by")
modified_by = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, on_delete=models.SET_NULL,
related_name="%(app_label)s_%(class)s_modified_by")
class Meta:
abstract = True
class Vehicule(TimeStampedAuthModel):
make = models.CharField(max_length=100)
model = models.CharField(max_length=100)
service_interval = models.CharField(max_length=50)
next_service = models.CharField(max_length=50)
class Meta:
abstract = True
class WheeledVehicle(Vehicule):
seats = models.PositiveSmallIntegerField()
color = models.CharField(max_length=100)
VIN = models.CharField(max_length=17, validators=[MinLengthValidator(11)])
current_mileage = models.PositiveSmallIntegerField()
class Meta:
abstract = True
class Car(WheeledVehicle):
year = models.IntegerField(default=2021, validators=[MinValueValidator(1886), MaxValueValidator(datetime.now().year)])
class Truck(WheeledVehicle):
year = models.IntegerField(default=datetime.now().year, validators=[MinValueValidator(1886), MaxValueValidator(datetime.now().year)])
bed_length = models.CharField(max_length=100)
class Boat(Vehicule):
year = models.PositiveSmallIntegerField(default=datetime.now().year, validators=[MaxValueValidator(datetime.now().year)])
length = models.CharField(max_length=100)
width = models.CharField(max_length=100)
HIN = models.CharField(max_length=14, validators=[MinLengthValidator(12)], blank=True)
current_hours = models.PositiveSmallIntegerField()
You can use model inheritance or model Mixins
model inheritance with abstract base model:
class AbstractVehicle(models.Model):
created = models.DateTimeField(auto_now_add=True)
make = models.CharField(max_length=100)
model = models.CharField(max_length=100)
year = models.IntegerField(default=2021, validators=[MinValueValidator(1886), MaxValueValidator(datetime.now().year)])
class Meta:
abstract = True
class Car(AbstractVehicle):
seats = models.PositiveSmallIntegerField()
color = models.CharField(max_length=100)
VIN = models.CharField(max_length=17, validators=[MinLengthValidator(11)])
current_mileage = models.PositiveSmallIntegerField()
service_interval = models.CharField(max_length=50)
next_service = models.CharField(max_length=50)
class Truck(AbstractVehicle):
seats = models.PositiveSmallIntegerField()
bed_length = models.CharField(max_length=100)
color = models.CharField(max_length=100)
VIN = models.CharField(max_length=17, validators=[MinLengthValidator(11)])
current_mileage = models.PositiveSmallIntegerField()
service_interval = models.CharField(max_length=50)
next_service = models.CharField(max_length=50)
class Boat(AbstractVehicle):
length = models.CharField(max_length=100)
width = models.CharField(max_length=100)
HIN = models.CharField(max_length=14, validators=[MinLengthValidator(12)], blank=True)
current_hours = models.PositiveSmallIntegerField()
service_interval = models.CharField(max_length=50)
next_service = models.CharField(max_length=50)
model mixins:
class VehicleMixin(object):
created = models.DateTimeField(auto_now_add=True)
make = models.CharField(max_length=100)
model = models.CharField(max_length=100)
year = models.IntegerField(default=2021, validators=[MinValueValidator(1886), MaxValueValidator(datetime.now().year)])
class Car(VehicleMixin, models.Model):
seats = models.PositiveSmallIntegerField()
color = models.CharField(max_length=100)
VIN = models.CharField(max_length=17, validators=[MinLengthValidator(11)])
current_mileage = models.PositiveSmallIntegerField()
service_interval = models.CharField(max_length=50)
next_service = models.CharField(max_length=50)
class Truck(VehicleMixin, models.Model):
seats = models.PositiveSmallIntegerField()
bed_length = models.CharField(max_length=100)
color = models.CharField(max_length=100)
VIN = models.CharField(max_length=17, validators=[MinLengthValidator(11)])
current_mileage = models.PositiveSmallIntegerField()
service_interval = models.CharField(max_length=50)
next_service = models.CharField(max_length=50)
class Boat(VehicleMixin, models.Model):
length = models.CharField(max_length=100)
width = models.CharField(max_length=100)
HIN = models.CharField(max_length=14, validators=[MinLengthValidator(12)], blank=True)
current_hours = models.PositiveSmallIntegerField()
service_interval = models.CharField(max_length=50)
next_service = models.CharField(max_length=50)
Both of these solutions will leave you with the same tables as your code. Also these are just simple examples. You may be able to improve them further. For Example you could add even more mixins or abstract base classes that contain the other fields.
You can combine the model by creating Vehicle and VehicleType in vehicle model you keep all common vehicle fields, in VehicleType keep the car, truck,boat etc with foreign-key reference to Vehicle model.
class VehicleType(models.Model):
name = models.CharField(max_length=100, unique=True)
created = models.DateTimeField(auto_now_add=True)
class Vehicle(models.Model):
vehicle_type = models.Foreinkey(VehicleType, on_delete=model.CASCADE)
created = models.DateTimeField(auto_now_add=True)
make = models.CharField(max_length=100)
model = models.CharField(max_length=100)
year = models.IntegerField(default=datetime.now().year, validators=[MinValueValidator(1886), MaxValueValidator(datetime.now().year)])
seats = models.PositiveSmallIntegerField()
bed_length = models.CharField(max_length=100)
color = models.CharField(max_length=100)
VIN = models.CharField(max_length=17, validators=[MinLengthValidator(11)])
current_mileage = models.PositiveSmallIntegerField()
service_interval = models.CharField(max_length=50)
next_service = models.CharField(max_length=50)

hi want to show the names from other classes to the Basic class

but when i run it i shows errors that it cant find the muscel_id i Muscel class, how can i show only the names. i ma trying to build a workout plan using django
class Days(models.Model):
day_name = models.CharField(max_length=60)
class Muscel(models.Model):
Muscel_name = models.CharField(max_length=60)
class Exercise(models.Model):
exercise_name = models.CharField(max_length=70)
class Basic(models.Model):
dagen_basic = models.ForeignKey(Days, related_name='days_basic', on_delete=models.CASCADE)
muskel = models.ForeignKey(Muscel.Muscel_name, related_name='muskel_basic',
on_delete=models.CASCADE)
exercise_name = models.ForeignKey(Exercise.exercise_name, related_name='exercise_name_basic',
on_delete=models.CASCADE)
reps = models.CharField(max_length=20)
sets = models.IntegerField()
try this:
class Muscel(models.Model):
muscel_name = models.CharField(max_length=60)
def __str__(self):
return self.muscel_name
add str on your Muscel model,
class Basic(models.Model):
......
muskel = models.ForeignKey(Muscel, related_name='muskel_basic',
on_delete=models.CASCADE)
exercise_name = models.ForeignKey(Exercise, related_name='exercise_name_basic',
on_delete=models.CASCADE)
......
remove .Muscel_name on ForeignKey

Django DRY Models

In general, how can I keep my models DRY when I have to repeat several attributes multiple times?
For example:
class Event(models.Model):
title = models.CharField(max_length=255)
postal_code = models.CharField(max_length=5)
city = models.CharField(max_length=50)
street = models.CharField(max_length=50)
street_nr = models.CharField(max_length=5)
class Person(models.Model):
name = models.CharField(max_length=50)
postal_code = models.CharField(max_length=5)
city = models.CharField(max_length=50)
street = models.CharField(max_length=50)
street_nr = models.CharField(max_length=5)
Normalize your database structure, you could normalize Address even further
class Adress(models.Model):
postal_code = models.CharField(max_length=5)
city = models.CharField(max_length=50)
street = models.CharField(max_length=50)
street_nr = models.CharField(max_length=5)
class Event(models.Model):
title = models.CharField(max_length=255)
address = models.ForeignKey(Adress, on_delete=models.CASCADE)
class Person(models.Model):
name = models.CharField(max_length=50)
address = models.ForeignKey(Adress, on_delete=models.CASCADE)
Just add refs:
class AdressData(models.Model):
postal_code = models.CharField(max_length=5)
city = models.CharField(max_length=50)
street = models.CharField(max_length=50)
street_nr = models.CharField(max_length=5)
class Event(models.Model):
title = models.CharField(max_length=255)
address_data = models.ForeignKey('AdressData')
class Person(models.Model):
name = models.CharField(max_length=50)
address_data = models.ForeignKey('AdressData')
Django models can use Python's object inheritance to share common data; with a provision. These are referred to as abstract models.
To refactor your code using an abstract models I would write it like so:
class BaseAddressModel(models.Model):
postal_code = models.CharField(max_length=5)
city = models.CharField(max_length=50)
street = models.CharField(max_length=50)
street_nr = models.CharField(max_length=5)
class Meta:
abstract = True
class Event(BaseAddressModel):
title = models.CharField(max_length=255)
class Person(BaseAddressModel):
name = models.CharField(max_length=50)
Previous answers might serve your purpose better, but this is an option.