Friday, February 24, 2017

Re: Models/Foreign Keys best practice

Hi Melvyn,

This worked perfectly, and definitely helped with my own understanding, thank you!

For the sake of formatting I've included my interpretation of your suggestion:

# models.py
from django.db import models
from django.utils import timezone


class Performance(models.Model):
    performance_name = models.CharField(max_length=200)
    link = models.CharField(max_length=200)

    def __unicode__(self):
        return self.performance_name


class Ensemble(models.Model):
    ensemble = models.CharField(max_length=200)

    def __unicode__(self):
        return self.ensemble


class Role(models.Model):
    role = models.CharField(max_length=200)

    def __unicode__(self):
        return self.role


class Venue(models.Model):
    venue = models.CharField(max_length=200)

    def __unicode__(self):
        return self.venue


class Event(models.Model):  # previously called "Date"
    performance = models.ForeignKey(Performance)
    ensemble = models.ForeignKey(Ensemble)
    role = models.ForeignKey(Role)
    venue = models.ForeignKey(Venue)
    start_datetime = models.DateTimeField('Start Date', default=timezone.now)
    end_datetime = models.DateTimeField('End Date', default=timezone.now)

Thanks again!

Rich


On Wednesday, February 22, 2017 at 6:38:26 PM UTC, Richard Jackson wrote:
Hi Melvyn - great reply, thank you so much for taking the time to help! I've got to head out now but will reply tomorrow - just wanted to leave an initial thank you note!

Rich



On Wednesday, February 22, 2017 at 5:01:36 PM UTC, Melvyn Sopacua wrote:

Hi Richard,

 

good questions and your initial data model defines your application challenges. It is by far the most important step in application design, so it's important to get it "as right as possible".

 

On Wednesday 22 February 2017 06:25:24 Richard Jackson wrote:

 

> The app lists performances, who's performing, what my role is with

> them (i.e. conductor, pianist etc.), the venue and the start

> date/time of these performances.

 

I come up with these separate entities:

- Performance (or "Show" or "Series")

- Ensemble

- Role within Ensemble

- Venue

- Event: performance using a certain Ensemble, playing a Role at a certain date

 

Date is a bad class name to use for a variety of reasons, but also doesn't cover the load. Event does.

 

Now you can see the links clearly:

- Role: Ensemble

- Event: Ensemble, Role, Performance

 

The questions to answer is: Within each ensemble can you switch roles? If so, they don't need to be linked and Event will link them

 

In fact, it's probably best not to link them, as you can always enforce this in logic.

 

A more general remark:

While you're free to use the class name as the field name, most of us will use "name", "title" or "designation" if you're Borg minded, for the field name. So Role.role becomes Role.name.

 

Results:

 

> class Performance(models.Model):

> """First attempt at a thing!"""

> performance_name = models.CharField(max_length=200)

> link = models.CharField(max_length=200)

>

> def __unicode__(self):

> return self.performance_name

>

>

> class Ensemble(models.Model):

> performance = models.ForeignKey(Performance)

 

No key here

 

> ensemble = models.CharField(max_length=200)

>

> def __unicode__(self):

> return self.ensemble

>

>

> class Role(models.Model):

> performance = models.ForeignKey(Performance)

 

No key here

 

> role = models.CharField(max_length=200)

>

> def __unicode__(self):

> return self.role

>

>

> class Venue(models.Model):

> performance = models.ForeignKey(Performance)

 

No key here. This is just the place. It should be possible to do two different performances at the same venue, without having to create two venues.

 

> venue = models.CharField(max_length=200)

>

> def __unicode__(self):

> return self.venue

>

>

> class Date(models.Model):

 

Event

 

> performance = models.ForeignKey(Performance)

ensemble = models.ForeignKey(Ensemble)

role = models.ForeignKey(Role)

venue = models.ForeignKey(Venue)

 

> start_date = models.DateTimeField('Start Date',

> default=timezone.now)

 

I would use "start" or start_time since it's not just a date.

 

> end_date = models.DateTimeField('End Date',

> default=timezone.now)

 

I would use duration = models.DurationField()

 

 

Now, if you look at "Event", it contains foreign keys to models that only have a charfield. So, it makes sense to simply make those CharFields.

But...a Venue, has an address. An Ensemble has members and you may get different but fixed wages for each role. These are reasons to use Foreign Keys. Otherwise, just use a CharField.

 

If you don't need to record anything special about roles, there's also the middle ground using a field's choices. You use choices instead of a Foreign Key if they hardly ever change and don't need to be managed in the Admin.

 

Hope this helps.

--

Melvyn Sopacua

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscribe@googlegroups.com.
To post to this group, send email to django-users@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/53171909-a5c7-4e33-82f4-b91566b475ce%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

No comments:

Post a Comment