Since Django is mapping each model to a table. I am not able to create packages in my code. Where I can wrap sections of the class to make it more logical and increase the coupling.
For example
class Employee(models.Model):
#personal information
first_name = models.CharField(max_length=20)
middle_initial = models.CharField(max_length=1)
last_name = models.CharField(max_length=20)
dob = models.DateField()
#job contract information
full_time = models.BooleanField()
hours_per_day = models.PositiveSmallIntegerField()
#.. and more
What I am trying to do is this
employee.job.is_full_time
employee.job.get_hours_per_day
# and more
However this means that I have to create a new model and connect it with the employee model using OneToOneField. I don't want to do that .. joins in the database are expensive. Is there anyway to create something like this ?
class Employee(models.Model):
class PersonalInformation:
first_name = models.CharField(max_length=20)
middle_initial = models.CharField(max_length=1)
last_name = models.CharField(max_length=20)
dob = models.DateField()
class Job:
full_time = models.BooleanField()
hours_per_day = models.PositiveSmallIntegerField()
#.. and more
The main key to the answer is to create a model that contain multiple classes which are going to be mapped to one table in the database.
There is no way to do that with just Django. Django models represent flat, relational databases. Extending the model framework to provide functionality beyond what its backend is capable of is unnecessary, and therefore not implemented in the default framework.
There are third-party packages that provide what you want, but as far as I know these packages use database backends that are capable of using such data structures.
Personally I would go with your first example, a flat, single model that represents all my Employee data. Prevent any disambiguity in your field names, and there will be no cost for using a flat model over a nested model.
And remember: premature optimization is a lot more expensive than an join statement.
Related
A friend recommended that I read the book two scoops Django and I was amazed at the recommendations he makes for a robust and well-designed Django project. This reading created a doubt in me and it is where I put the business logic, I give an example. Suppose I have two models:
models.py
class Sparks(models.Model):
flavor = models.CharField(max_length=100)
quantity = models.IntegerField(default=0)
class Frozen(models.Model):
flavor = models.CharField(max_length=100)
has_cone = models.BooleanField()
quantity_sparks = models.IntegerField(default=0)
Let's suppose that every time I add a frozen, if it has sparks, I have to subtract it from the Sparks model and check that there is an available quantity. In the book they recommend putting this logic in models.py or forms.py. If create some model required modify data from another model where should I do it?
Your data model is lacking, that's the likely source of uneasiness.
class Flavor(models.Model):
name = models.CharField(max_length=100)
class Sparks(model.Model):
flavor = models.ForeignKeyField(Flavor, on_delete=models.CASCADE)
quantity = models.IntegerField(default=0)
class Frozen(model.Model):
# This maybe should be a OneToOne, can't tell from your description.
sparks = models.ForeignKeyField(Sparks)
has_cone = models.BooleanField()
Then you'd do
frozen_instance = Frozen.objects.get()
frozen.sparks.quantity # This has replaced frozen_instance.quantity_sparks
I hope this is not a duplicate question. I am trying to setup models in django.
In model 1 I have one kind items (parts), these can together form item type 2 (car).
I get the prices for all of these from outside interface to a model prices.
How can I setup the relationship between price - > part and price - > car.
I do not know when I get the prices if the ident belongs to car och part.
class parts(models.Model):
ident = models.CharField("IDENT", max_length = 12, unique = True, primary_key = True)
name = models.CharField(max_length=30)
class car(models.Model):
ident = models.CharField("IDENT", max_length = 12, unique = True)
start_date = models.DateField()
end_date = models.DateField()
parts= models.ManyToManyField(parts)
class Prices(models.Model):
ident= models.CharField(max_length=12)
price = models.DecimalField(max_digits=10, decimal_places= 4)
date = models.DateField()
def __unicode__(self):
return self.ident
class Meta:
unique_together = (("ident", "date"),)
I would imagine you would not store price in your model since you need this to be 100% real time. So you have;
car models.py
from parts.models import parts
name = models.CharField(max_length=100)
parts = models.ManyToManyField(parts)
Hopefully you're not trying to develop like a full scale autozone type deal, but if it's simply a car model object that is comprised of many parts than this is the basic setup you would want. having the many to many relationship to parts allows one car to have many parts. parts can belong to many cars. You don't have to specify a manytomany relationship in the parts model as the two way communication will already be handled in your cars model.
As far as price is concerned you could have a price database field in your parts model, but once again if this needs to be real time, you probably want to request that price via an api and display it directly in your webpage.
I've searched around for a while, but can't seem to find an existing question for this (although it could be an issue of not knowing terminology).
I'm new to Django, and have been attempting to take a design which should be very expandable over time, and make it work with Django's ORM. Essentially, it's a series of many-to-many relationships using a shared junction table.
The design is a generic game crafting system, which says "if you meet [require], you can create [reward] using [cost] as materials." This allows items to be sold from any number of shops using the same system, and is generic enough to support a wide range of mechanics - I've seen it used successfully in the past.
Django doesn't support multiple M2M relationships sharing the same junction table (apparently since it has no way to work out the reverse relationship), so I seem to have these options:
Let it create its own junction tables, which ends up being six or more, or
Use foreign keys to the junction table in place of a built-in MTM relationship.
The first option is a bit of a mess, since I know I'll eventually have to add additional fields into the junction tables. The second option works pretty well. Unfortunately, because there is no foreign key from the junction table BACK to each of the other tables, I'm constantly fighting the admin system to get it to do what I want.
Here are the affected models:
class Craft(models.Model):
name = models.CharField(max_length=30)
description = models.CharField(max_length=300, blank=True)
cost = models.ForeignKey('Container', related_name="craft_cost")
reward = models.ForeignKey('Container', related_name="craft_reward")
require = models.ForeignKey('Container', related_name="craft_require")
class ShopContent(models.Model):
shopId = models.ForeignKey(Shop)
cost = models.ForeignKey('Container', related_name="shop_cost")
reward = models.ForeignKey('Container', related_name="shop_reward")
require = models.ForeignKey('Container', related_name="shop_require")
description = models.CharField(max_length=300)
class Container(models.Model):
name = models.CharField(max_length=30)
class ContainerContent(models.Model):
containerId = models.ForeignKey(Container, verbose_name="Container")
itemId = models.ForeignKey(Item, verbose_name="Item")
itemMin = models.PositiveSmallIntegerField(verbose_name=u"min amount")
itemMax = models.PositiveSmallIntegerField(verbose_name=u"max amount")
weight = models.PositiveSmallIntegerField(null=True, blank=True)
optionGroup = models.PositiveSmallIntegerField(null=True, blank=True,
verbose_name=u"option group")
Is there a simpler, likely obvious way to get this working? I'm attempting to allow inline editing of ContainerContent information from each related column on the Craft edit interface.
It sounds like you have a sort of "Transaction" that has a name, description, and type, and defines a cost, reward, and requirement. You should define that as a single model, not multiple ones (ShopContent, Craft, etc.).
class Transaction(models.Model):
TYPE_CHOICES = (('Craft', 0),
('Purchase', 1),
)
name = models.CharField(max_length=30)
description = models.CharField(max_length=300, blank=True)
cost = models.ForeignKey('Container')
reward = models.ForeignKey('Container')
require = models.ForeignKey('Container')
type = models.IntegerField(choices = TYPE_CHOICES)
Now Shop etc. can have a single ManyToManyField to Transaction.
Whether or not you use this particular model, the cost, reward and require relationships should all be in one place -- as above, or in OneToOne relationships with Craft, ShopContent etc. As you guessed, you shouldn't have a whole bunch of complex Many-To-Many through tables that are all really the same.
You mention at the bottom of your post that you're
attempting to allow inline editing of ContainerContent information from each related column on the Craft edit interface.
If you're modeling several levels of relationship, and using the admin app, you'll need to either apply some sort of nested inline patch, or use some sort of linking scheme like the one I use in my recent question, How do I add a link from the Django admin page of one object to the admin page of a related object?
I am smelling something is too complicated here, but I might be wrong. As a start,
is this any better? (ContainerContent will be figured out later)
class Cost(models.Model):
name = models.CharField(max_length=30)
class Reward(models.Model):
name = models.CharField(max_length=30)
class Require(models.Model):
name = models.CharField(max_length=30)
class Craft(models.Model):
name = models.CharField(max_length=30)
description = models.CharField(max_length=300, blank=True)
cost = models.ForeignKey(Cost)
reward = models.ForeignKey(Reward)
require = models.ForeignKey(Require)
class Shop(models.Model):
name = models.CharField(max_length=30)
crafts = models.ManyToMany(Craft, blank=True)
I am building a football predictions app whilst learning django and have the following models:
class Team(models.Model):
Name = models.CharField(max_length=30)
class Fixture(models.Model):
HomeTeam = models.ForeignKey(Team, related_name='HomeTeamRef')
AwayTeam = models.ForeignKey(Team, related_name='AwayTeamRef')
HomeTeamScore = models.IntegerField(null=True, blank=True)
AwayTeamScore = models.IntegerField(null=True, blank=True)
Date = models.DateField()
class Player(models.Model):
User = models.ForeignKey(User)
DefaultHomeScore = models.IntegerField()
DefaultAwayScore = models.IntegerField()
class Prediction(models.Model):
Fixture = models.ForeignKey(Fixture)
HomeTeamScore = models.IntegerField()
AwayTeamScore = models.IntegerField()
Date = models.DateTimeField()
Player = models.ForeignKey(Player)
I have many fixture objects populated and have been using model formsets based on the Prediction model to render a view which allows the user to enter scores.
The problem is that they must choose which fixture the prediction relates to. I would like to pre-populate this so they get a list of fixtures and just enter the hometeamscore and awayteamscore. This involves pre-poulating the Prediction.Fixture field and Prediction.Player field but I am unsure on how to go about this?
Any help is much appreciated.
Edit: The problems seems to be how to pass multiple instances of Fixture into a Prediction model formset, I have seen examples of passing one but would like to do this all in one go.
I also would like the user to be able to make one Prediction per Fixture.
I think this is what you are looking for:
https://docs.djangoproject.com/en/1.7/topics/forms/formsets/#using-initial-data-with-a-formset
Your code would look something like this:
initial_data = []
for fixture in fixtures:
initial_data.append({'Player':player,'Fixture':fixture})
formset = MyPredictionFormset(initial=initial_data)
P.S. Not to be pedantic, but your field names are not PEP 8 compliant. They should be lowercase with underscores, but it's your call. (http://www.python.org/dev/peps/pep-0008/)
I've previously asked questions for this project, regarding the Django Admin, Inlines, Generics, etc. Thanks again to the people who contributed answers to those. For background, those questions are here:
Django - Designing Model Relationships - Admin interface and Inline
Django Generic Relations with Django Admin
However, I think I should probably review my model again, to make sure it's actually "correct". So the focus here is on database design, I guess.
We have a Django app with several objects - Users (who have a User Profile), Hospitals, Departments, Institutions (i.e. Education Institutions) - all of whom have multiple addresses (or no addresses). It's quite likely many of these will have multiple addresses.
It's also possible that multiple object may have the same address, but this is rare, and I'm happy to have duplication for those instances where it occurs.
Currently, the model is:
class Address(models.Model):
street_address = models.CharField(max_length=50)
suburb = models.CharField(max_length=20)
state = models.CharField(max_length=3, choices=AUSTRALIAN_STATES_CHOICES)
...
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey()
...
class Hospital(models.Model):
name = models.CharField(max_length=20)
address = generic.GenericRelation(Address)
...
class UserProfile(models.Model):
user = models.ForeignKey(User, unique=True)
address = generic.GenericRelation(Address)
...
Firstly - am I doing it right, with the FK field on each object that has address(es)?
Secondly, is there a better alternative to using Generic Relations for this case, where different objects all have addresses? In the other post, somebody mentioned using abstract classes - I thought of that, but there seems to be quite a bit of duplication there, since the addresses model is basically identical for all.
Also, we'll be heavily using the Django admin, so it has to work with that, preferrably also with address as inlines.(That's where I was hitting an issue - because I was using generic relationships, the Django admin was expecting something in the content_type and object_id fields, and was erroring out when those were empty, instead of giving some kind of lookup).
Cheers,
Victor
I think what you've done is more complicated than using some kind of subclassing (the base class can either be abstract or not).
class Addressable(models.Model):
... # common attributes to all addressable objects
class Hospital(Addressable):
name = models.CharField(max_length=20)
...
class UserProfile(models.Model):
user = models.ForeignKey(User, unique=True)
class Address(models.Model):
street_address = models.CharField(max_length=50)
suburb = models.CharField(max_length=20)
state = models.CharField(max_length=3, choices=AUSTRALIAN_STATES_CHOICES)
...
owner = models.ForeignKey(Addressable)
You should consider making the base class (Addressable) abstract, if you don't want a seperate table for it in your database.