Mohaaron
Mohaaron

Reputation: 441

Django: How to inherit and query related field

I've been searching for an answer to this for a while. How can I add a field from one model to a related model and query the related models data.

Here is an example: One Person has many Jobs.

class Person(models.Model):
    PersonId = models.AutoField(primary_key=True)
    FirstName = models.CharField(max_length=200, default='')
    LastName = models.CharField(max_length=200, default='')

class Job(models.Model):
    JobId = models.AutoField(primary_key=True)
    JobName = models.CharField(max_length=200, default='')
    Person = models.ForeignKey(Person, db_column='PersonId')

    def _fullname(self):
        return self.Person.FirstName + " " + self.Person.LastName
    fullname = property(_fullname)

The code above does work!

jobs = Job.objects.select_related()
for job in jobs:
    print job.fullname

Now I think I have a different problem. Getting the Django Rest Framework to serialize these additional properties. Time for a new post.

Now what I want to be able to do is query jobs and get the related person data as well as have the person fields on the job. This way when I query jobs I can use job.FirstName. I basically want to make a shortcut to the Person fields from the Job. This is a bit like the Job is inheriting the fields of the Person.

An expected site effect of this would be when serializing the Job as json for a rest resource the result would include the Person field data.

I'm coming from a .Net C# background. Now since I'm using Python/Django I have no idea how to make this happen.

Upvotes: 1

Views: 914

Answers (3)

Issac Kelly
Issac Kelly

Reputation: 6359

Try this out, it sounds like what you want.

Then a Job IS A Person, which, is what you're asking for. This is not abstract inheritance, so there will be two tables in your DB.

$> # This will dump the sql that's generated.
$> ./manage.py sql this_app

Job.FirstName will work. Read up on model inheritance. You might evenautally need to use django-model-utils's ModelInheritance manager, which is quite nice.

class Person(models.Model):
    PersonId = models.AutoField(primary_key=True)
    FirstName = models.CharField(max_length=200, default='')
    LastName = models.CharField(max_length=200, default='')

class Job(Person):
    JobId = models.AutoField(primary_key=True)
    JobName = models.CharField(max_length=200, default='')

Upvotes: 0

Victor Miroshnikov
Victor Miroshnikov

Reputation: 594

Example of queryset which gets filtered list of Job objects:

joblist = Job.objects.filter(statement1,statement2...)

You can access to persons associated by ForeignKey with Job objects in this way

for j in joblist:    
    print j.Person.FirstName, j.Person.LastName

If you exactly need all related objects on every Job record you should use select_related queryset

joblist = Job.objects.select_related().filter(statement1,statement2...)

Serialization: You can use natural_keys, but it's limited with DB constraints. Or you can use Piston and define a Handler which will produce nested JSON.

Notice, you dont have to make AutoField for every model, it's specified by convention and can be reached at model_instance.id.

Also I recommend you to follow PEP8 conventions.

Upvotes: 1

darren
darren

Reputation: 19399

If you query your jobs with something like job = Job.objects.get(personid=1) you'll see that it pulls through the related fields too, it's voodoo behind the scenes. So essentially you can now do job.person.firstname, job.person.lastname etc...

Upvotes: 0

Related Questions