I was wondering what is the best way to include objects from another model that are related on a foreignkey?
Example:
class First(models.Model):
name = models.CharField(max_length=255)
class Second(models.Model):
first = models.ForeignKey(First)
second = models.CharField(max_length=255)
How would I create a resource for the first model that includes all the related objects in the second one? - I know how to do it for foreignkeys in the first one, but not sure about how to go about this.
Cheers,
Ben
Put this on the resource that wants reverse relation
anyfieldnameyouwant = fields.ToManyfield(FooResource, 'relatedname', full = True)
In this case:
class FirstResource(ModelResource):
second = fields.ToManyField(SecondResource, 'second_set', full = True)
Related
I have these models
class Tree(models.Model):
field = models.TextField()
class TaskProgress(models.Model):
base_task = models.ForeignKey(BaseTask, on_delete=models.CASCADE)
tree = models.ForeignKey(Tree, on_delete=models.CASCADE)
class BaseTask(models.Model):
trees=models.ManyToManyField(Tree, through='TaskProgress')
class TaskType1(BaseTask):
child1_field = models.TextField()
class TaskType2(BaseTask):
child2_field = models.TextField()
how to get all taskprogress when related to TaskType2 ,
TaskProgress.objects.filter(???)
I added extra field on BaseTask class
TASK_TYPE =[('I','Irrigation'),('C','Care'),('A','Assessment'),('O','Other')]
class BaseTask(models.Model):
trees=models.ManyToManyField(Tree, through='TaskProgress')
worker = models.ManyToManyField(User)
task_type = models.CharField(max_length=1,choices=TASK_TYPE,null=True)
And the filter will be like this
TaskProgress.objects.filter(base_task__task = "I")
I do not think what you are asking is possible, if the models are designed like described. The base_task ForeignKey is specifically pointing at a BaseTask. Even though TaskType1 and TaskType2 inherit from BaseTask, they have no relation in the database. They only look similar.
Option 1: Look into Generic Relations in Django. Basically it allows you to have a ForeignKey relation with more than one type of model. I would not recommend it though. Generic relations are a mess if you don't know want you are doing.
Option 2: Rethink your layout. Maybe you can move the relation to the two TaskTypes instead and adress them via related_name.
class TaskProgress(models.Model):
# base_task = models.ForeignKey(BaseTask, on_delete=models.CASCADE)
tree = models.ForeignKey(Tree, on_delete=models.CASCADE)
class TaskType1(BaseTask):
task_progress = models.OneToOneField(TaskProgress, related_name='task_type_1'
child1_field = models.TextField()
class TaskType2(BaseTask):
task_progress = models.OneToOneField(TaskProgress, related_name='task_type_2'
child2_field = models.TextField()
This way you create a one-to-one-relation between the TaskProgress and the TaskType. You should be able to query one or the other by checking whether a relation exists, e.g. all TaskProgress instances with a relation to a TaskType1 instance.
# Query all TaskProgress instances, that have a TaskType1
TaskProgress.objects.filter(task_type_1__isnull=False)
I'm trying to find a solution that will return the objects with a specific id.
I have these models:
class ModelB(models.Model):
customid = models.CharField(max_length=32)
<-- data -->
class ModelA(models.Model):
b = models.ForeignKey(ModelB, blank=True, null=True, related_name="Bs")
and I have this code in my views:
a = ModelA.objects.filter(ModelB__customid = Bobject_id)
I want to be able to find all of the A objects with a given B object.
Any ideas?
a_objects = ModelA.objects.filter(b__customid=Bobject_id)
Check out the documentation for creating queries that span relationships
Assuming you have an instance of ModelB, the easiest way is to follow the reverse relationship from there:
a_objects = b_object.Bs.all()
This uses the explicit related_name you have set: without that, it would have been b_object.modela_set.all(). Note that your related_name should really be "As", not "Bs", since it refers to the A objects that are related to that B.
class Blog(models.Model):
name = models.CharField(max_length=100)
class Entry(models.Model):
blog = models.ForeignKey(Blog)
headline = models.CharField(max_length=255)
Is the following query correct?
a = Blog.objects.get(id__exact=14)
b = Entry.objects.filter(blog = a)
I comprehend that that any of the following methods are more elegant and even recommended.
Entry.objects.filter(blog__id__exact=3) # Explicit form
Entry.objects.filter(blog__id=3) # __exact is implied
Entry.objects.filter(blog__pk=3) # __pk implies __id__exact
In other words, can I pass an object (model instance) as an argument value?
Please also provide some guidance on where can find explicit documentation on this?
Yes, according to the django docs; you can use the instance of a row to do a filter.
Queries over related objects
Alternative:
a = Blog.objects.get(pk=3)
b = a.blog_set.all()
I'm new to Django and I'd like to understand how to use managers. I've read the documentation but need a little help putting it into practice.
I've got models as follows:
class Place(models.Model):
id = models.IntegerField(primary_key=True)
name = models.CharField(max_length=300)
class PlaceRef(models.Model):
place = models.ForeignKey(Place)
entry = models.ForeignKey(Entry)
value = models.FloatField()
units = models.CharField(max_length=30)
If I had a particular Place, should I use a Manager to add up the value of all the PlaceRefs associated with it? (assuming for the sake of simplicity that all the units are the same...)
place = Place.objects.get(id=id)
value = PlaceRef.objects... # what to do here?
No need for a new manager here. There's already an automatic manager that deals with the relationship between Place and PlaceRef - it's accessed via place.placeref_set.
But to add up the values, you need to use aggregation - specifically, the aggregate method.
from django.db.models import Sum
value = place.placeref_set.aggregate(Sum('value'))
Now value is a dictionary with a single value containing the sum of all the values in the associated PlaceRefs.
You can also add this as an attribute of place
class Place(models.Model):
id = models.IntegerField(primary_key=True)
name = models.CharField(max_length=300)
#property
def placeref_total(self):
do your calculation here as suggested in Daniel's answer
value = self.placeref_set.aggregate(Sum('value'))
return value
then you can refer to it in your code:
myplace = Place.objects.get(id=x)
myplace.placeref_total
If you don't use the #property decorator, then refer to it as:
myplace.placeref_total()
I have the following two models
class Author(Model):
name = CharField()
class Publication(Model):
title = CharField()
And I use an intermediary table to keep track of the list of authors. The ordering of authors matter; and that's why I don't use Django's ManyToManyField.
class PubAuthor(Model):
author = models.ForeignKey(Author)
pubentry = models.ForeignKey(Publication)
position = models.IntegerField(max_length=3)
The problem is, given a publication, what's the most efficient way to get all authors for the publication?
I can use pubentry.pubauthor_set.select_related().order_by('position'), but then it this will generate one query each time I access the author's name.
I've found out the answer.
In publications:
def authors(self):
return Author.objects.all().filter(
pubauthor__pubentry__id=self.id).order_by('pubauthor__position')