Storing constants in tuple vs table - sql

What is the best practice for when to store constant values in a table vs a tuple. For example, is it better to do this:
class ModelA(models.Model):
SOME_VALUES = (
(0, 'A1'),
(1, 'A2'),
(2, 'A3'),
)
fieldA = models.IntegerField(choices=SOME_VALUES)
or have another model for the constant values:
class ConstantValue(models.Model):
text = model.CharField(max_length=2)
class ModelA(models.Model):
fieldA = models.OneToOneField(ConstantValue)
and a fixture would populate ConstantValue.
I have combination of the above in my code, but I'd like some consistency.
And what about many-to-many relationships? I have a model with constants as above and another model that points to the constant model with a ManyToManyField relationship. It's similar to the Django tutorial's pizza example. But I suppose I could have this:
class Topping(models.Model):
TOPPINGS = (
(0, 'Tomato'),
(1, 'Peppers'),
...
)
topping = models.IntegerField(choices=TOPPINGS)
class Pizza(models.Model):
topping = models.ForeignKey(Topping)

i have a very basic answer:
Whenever your Domain is probaply changing, use another (domain_) table (or other class) like a pizzaname; if you dont see a chance for changing - like gender (m/f/dont know) keep it short, altough the gender (of an entry) may change, the range wont (or most likely wont)

Related

How do I get tuples of primary keys of models related to each other using the django orm?

Assuming I have four models, where two models define types and two models are instances of these types, which have a 1-to-n relationship:
class SuperTypeA(Model):
pass
class InstanceofA(Model):
definition = ForeignKey(SuperTypeA, null=False)
class SubTypeB(Model):
supertype = ForeignKey(SuperTypeA, null=False)
class InstanceofB(Model):
definition = ForeignKey(SubTypeB, null=False)
related = ForeignKey(InstanceofA, null=False)
In plain English, a SuperTypeA has n SubTypeB, and n InstanceofA. A SubTypeB has n InstanceofB. A InstanceofA has n InstanceofB.
I would like to get the tuples of the primary keys of SuperTypeA, SubTypeB, InstanceofB given some constraints on InstanceofA. In SQL:
SELECT SuperTypeA.id, SubTypeB.id, InstanceofB.id
FROM SuperTypeA, SubTypeB, InstanceofB, InstanceofA
WHERE InstanceofA.id IN (1, 2, 3, 4)
How do I do that using the Django ORM, without using raw queries?
I think what you want to do is this: InstanceofB.objects.all().values_list('definition', 'related')
You can change the all method for the filter one if you want to set some kind of condition.

How do I filter Django models to only include models that appear in a child (with a ForeignKey) table?

I have these two Django models:
class Animals(models.Model):
id = models.AutoField(primary_key=True)
name = models.TextField(unique=True)
class Meta:
db_table = 'animals'
class AnimalSounds(models.Model):
id = models.AutoField(primary_key=True)
animal = models.ForeignKey(Animal, on_delete=models.PROTECT)
sound = models.TextField(unique=True)
class Meta:
db_table = 'animal_sounds'
Now my SQL query would look something like this:
SELECT * FROM animals WHERE animals.id IN (
SELECT animal_id FROM animal_sounds
)
How would I do this using Django models? Something like this conceptually:
Animals.objects.filter(id__in=AnimalSounds.objects.all('ids'))
You can check if there is at least one AnimalSound related with:
Animal.objects.filter(animalsounds__isnull=False).distinct()
This will perform a query like:
SELECT DISTINCT animal.*
FROM animal AS ani
JOIN animalsounds AS ans ON ans.animal_id = ani.id
Or you can use your approach with:
Animals.objects.filter(
id__in=AnimalSounds.objects.values('animal_id', flat=True)
)
But I prefer the former since it is more declarative and shorter.
EDIT: If you want to select all Animals that have a related AnimalSounds object where sound is 'woof', you can write it like:
# animals that produce woof (and perhaps other sounds)
Animal.objects.filter(animalsounds__sound='woof').distinct()

What is better performance between ManyToMany and a model with two forigen keys?

The case is I have a model User which is the teacher and student and I differ between them using a flag type, Now Teachers may have many students and vice versa so..
Which is better as a performance
Case 1:
class UserAccount(AbstractUser):
type = models.PositiveSmallIntegerField(choices=TYPES, default=1)
grp = models.ManyToMany("self",blank=True)
Case 2:
class UserAccount(AbstractUser):
type = models.PositiveSmallIntegerField(choices=TYPES, default=1)
class Group(models.Model):
teacher = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='students')
student = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='teachers')
For sure I can handle this based on the type in the form.. etc, but
Now I can't determine which is better as a performance and code modularity

Flattened list from manytomany

What is the nicests (quickest) way to create a full outer join on 2 models related by a manytomany field.
for example a book and an author (normally in this case you would use a foreignkey), but suppose a book can have 2 authors (to get my case).
for example:
class Author(models.Model):
books = models.ManyToManyField(Book,related_name='book_author')
class Book(models.Model):
title = models.CharField()
and now i want to create a list with: (preferably a queryset)
author1 , book1
author1, book2
author2, book1
author2, book3
author3, book4
probably because of the time at fridays, but need a bit of help with this...
I want to offer the flat result to an api (DRF), so would be nice to get a queryset of this join.
You are trying to access the auto-generated through model between the Author and Book (Book_authors). You should be able to get that result like this
>>> Book.authors.through.objects.select_related('book', 'author')
<QuerySet [<Book_authors: Book_authors object>, ...>
To get the primary keys only, you can use values_list
>>> Book.authors.through.objects.values_list('book', 'author')
<QuerySet [(1, 1), (1, 2), (1, 3)]>

Django annotate code

Just stumbled upon some guy code
He have models like this
class Country(models.Model):
name = models.CharField(max_length=100)
class TourDate(models.Model):
artist = models.ForeignKey("Artist")
date = models.DateField()
country = models.ForeignKey("Country")
And is querying like this
ireland = Country.objects.get(name="Ireland")
artists = Artist.objects.all().extra(select = {
"tourdate_count" : """
SELECT COUNT(*)
FROM sandbox_tourdate
JOIN sandbox_country on sandbox_tourdate.country_id = sandbox_country.id
WHERE sandbox_tourdate.artist_id = sandbox_artist.id
AND sandbox_tourdate.country_id = %d """ % ireland.pk,
}).order_by("-tourdate_count",)
My question is why He have underscores like sandbox_tourdate but it isn't in model field
Is that created automatically like some sort of pseudo-field?
sandbox_tourdate isn't the name of the field, it's the name of the table. Django's naming convention is to use appname_modelname as the table name, although this can be overridden. In this case, I guess the app is called 'sandbox'.
I don't really know why that person has used a raw query though, that is quite easily expressed in Django's ORM syntax.