This works, but is there a Django idiom that does it better?
my_books = Book.objects.filter(author__name=='me')
my_publishers = Publisher.objects.filter(pk__in=[b.publisher.id for b in my_books])
models = round_up_the_usual_suspects()
class Publisher(models.Model):
name = models.CharField(max_length=30)
class Author(models.Model):
name = models.CharField(max_length=30)
class Book(models.Model):
title = models.CharField(max_length=100)
author = models.ForeignKey(Author, related_name='books_authored')
publisher = models.ForeignKey(Publisher, related_name='books_published')
You can do
my_publishers = Publisher.objects.filter(book__author__name='me')
This gives you all the publishers for the book authored by me
Related
I have a model and I want to copy all of my data when copy function called and it make a copy of my books with new datetime I wrote this:
class Book(models.Model):
name = models.CharField(max_length=255)
created_date = models.DateTimeField(auto_now_add=True)
author = models.ForeignKey('Author', on_delete=models.CASCADE)
def copy(self):
new_book = Book()
new_book.name = self.name
new_book.created_date = models.DateTimeField(auto_now_add=True)
new_book.author = self.author
new_book.save()
class Author(models.Model):
name = models.CharField(max_length=255)
but author won't copied well
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
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
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.
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)