I have a set of models that contain content that is created and contributed by users.
Model User:
class User(models.Model):
first_name = models.CharField(max_length=30, blank=True)
last_name = models.CharField(max_length=150, blank=True)
is_active = models.BooleanField(default=True)
Model Tip:
class Tip(models.Model):
title = models.CharField(max_length=30, blank=True)
content = models.CharField(max_length=150, blank=True)
Model Example:
class Example(models.Model):
headline = models.CharField(max_length=30, blank=True)
content = models.CharField(max_length=150, blank=True)
Model Struggle:
class Struggle(models.Model):
headline = models.CharField(max_length=30, blank=True)
content = models.CharField(max_length=150, blank=True)
and model UserContribution
class UserContribution(models.Model):
id = models.AutoField(primary_key=True)
contributed_by = models.ForeignKey(
settings.AUTH_USER_MODEL,
verbose_name="User that contributed the object",
on_delete=models.CASCADE
)
contributed_at = models.DateTimeField(auto_now_add=True)
object_id = models.PositiveIntegerField(
help_text="Primary key of the model",
)
content_type = models.ForeignKey(
ContentType,
on_delete=models.CASCADE
)
I want to be able to select a set of users and list the contribution objects they have contributed (created or updated). For example,
[
{
"user_id": 1,
"first_name": "A",
"last_name": "B",
"tips": [
{
"id": 1,
"title": "abc",
"content": "bcd",
"contibuted_at": "2021-08-10"
},
{
"id": 2,
"title": "eabc",
"content": "abcd",
"contibuted_at": "2021-08-09"
}
],
"examples": [
{
"id": 1,
"headline": "abc",
"content": "bcd",
"contibuted_at": "2021-08-10"
},
{
"id": 2,
"headline": "eabc",
"content": "abcd",
"contibuted_at": "2021-08-09"
}
],
"struggles": [
{
"id": 1,
"headline": "abc",
"content": "bcd",
"contibuted_at": "2021-08-10"
},
{
"id": 2,
"headline": "eabc",
"content": "abcd",
"contibuted_at": "2021-08-02"
}
]
},
{
"user_id": 2,
"first_name": "C",
"last_name": "D",
"tips": [
{
"id": 1,
"title": "abc",
"content": "bcd",
"contibuted_at": "2021-09-09"
},
{
"id": 3,
"title": "eabc",
"content": "abcd",
"contibuted_at": "2021-09-02"
}
],
"examples": [
{
"id": 1,
"headline": "abc",
"content": "bcd",
"contibuted_at": "2021-09-10"
},
{
"id": 3,
"headline": "eabc",
"content": "abcd",
"contibuted_at": "2021-08-09"
}
],
"struggles": [
{
"id": 1,
"headline": "abc",
"content": "bcd",
"contibuted_at": "2021-09-10"
},
{
"id": 2,
"headline": "eabc",
"content": "abcd",
"contibuted_at": "2021-08-09"
}
]
}
]
Is there a specific way this can be achieved using Django's ORM, or do I have to use a raw SQL query? And what would the most efficient way be to achieve this in raw SQL?
I think you can get most of this by writing an admin class object for your models and create list_filter to access the content of child or sibling models. Assuming the UserContribution model is the 'parent' model. As example in your main app's admin.py create a admin model for UserContribution and register it: eg.
These filters should appear in your admin panel for the app and create querysets which you can access from the 'actions' you will create or you can just set up the display to show what your are looking for. The format of the items in '' is key to accessing the data fields depending on the model you create this admin function for. This example is for the UserContribution[UC] model so all of its model fields are accessed directly. To access a child model field (or related table) use: 'modelname__fieldname' separated with double underscore all lowercase as shown above. You can even access a child field from another child field via the common parent! For example in class TipAdmin(admin.ModelAdmin) you can write a filter to show the Tips of those who had a specific Struggle by accessing the parent eg
VCool! If the filters have too many options you can reformat them with built in dropdown filters that can be imported such as
viola!