I know there's something similar answered here, but my question is not the same. I'm using multi-table inheritance to model 2 different types of entities, and both of them can create posts. My problem is when trying to create a view that shows all the posts together.
So I have my Entity model, and then my ETypeA and ETypeB models, which look like this:
class Entity(models.Model):
pass
class ETypeA(Entity):
# Here are some attributes
pass
class ETypeB(Entity):
# Here are some attributes
pass
As you can see, the Entity model it's just for having a common primary key between ETypeA and ETypeB. The reason for this is to have just one common Post model, like this:
class Post(models.Model):
transmitter = models.ForeignKey(Entity, on_delete=models.CASCADE)
text = models.CharField(max_length=500, null=False, blank=False)
The problem now is that when I create a view to show the posts I get only the id of the transmitter but I need the whole information. The way of doing it in SQL should be joining the results with ETypeA, then with ETypeB and make a union between the results (keeping some fields as nulls). Then I should be capable of sorting them by date. How can I do that with DRF views and serializers?
Related
I have a model Client which can be one of two types: PJ or PF. That means that a Client can have the fields of a PJ model or the fields of a PFmodel.
But I'm not sure how I can do it using the Django's models and admin app. I would like to give the user the option to select which type the Client is and then the appropriate fields will be shown to him/her.
Can someone help me with this problem? Should I use some kind of Design Pattern or how should I create my models?
Thanks in advance.
Model PF:
class PF(models.Model):
name = models.CharField(max_length=512)
card = models.IntegerField(unique=True)
Model PJ:
class PJ(models.Model):
ie = models.IntegerField(unique=True, null=True, blank=True)
Model Client:
class Client(models.Model):
type = models.SmallIntegerField(default=0) # 0=PF, 1=PJ
First I'd recommend to look at the commonality between these two models and use inheritance if you can. If a type field is inevitable, I'd recommend using CharField with choices instead.
If the two models are drastically different, I'd recommend separating these two models completely, and call them InternalClient, ExternalClient, however the name would make sense to the data model.
Say I have 3 models (Blog, News, Photos) and i want to get the latest 3 pieces of content regardless of which model they belong to.
With (psuedo) sql I could do something like:
SELECT *
FROM blog, news, photo,
WHERE is_published=True
ORDER by publication_date
LIMIT 3
I don't really want to use to use raw sql in Django as i want a query set returned, so is there a way I can make this type of query with Django?
Thanks,
If the 3 models are similar in some way (as they appear to be), the way I would probably do it is by creating a base model and then have the 3 other models inherit from that model.
class Publishable(models.Model):
is_published = models.BooleanField(default=False)
publication_date = models.DatetimeField()
... other fields ...
class Blog(Publishable):
...extra fields...
class News(Publishable):
...extra fields...
class Photos(Publishable):
...extra fields...
Then later on, you can do:
Publishable.objects.order_by('-publication_date')[:3]
If you still need the "type" associated with the retrieved models, check out the Inheritance Manager
You'll probably want to read about the pros and cons about Model Inheritance as well.
I have a model named Photo and a model named Video. They both inherit off a model named Item, which contains the a time_created field and item_by field. I know that you can order objects from these two different models by using Item.objects.all().order_by('time_created'). However, I'd like to order Photo by time and Video by rank. I would still like to group these two objects under one queryset, even if they are ordered differently, so that I could display it on one page (like a grid). How would I be able to do this?
Thanks!
I know you can accomplish something similar by overriding the child models Meta ordering property. However without seeing your model code (proxy, abstract etc.) I can't say for certain if this will work for you.
class Item(models.Model):
time_created = models.DateField()
rank = models.IntegerField()
class Photo(Item):
class Meta:
ordering = ['time_created']
class Video(Item):
class Meta:
ordering = ['rank']
say i have
class Visualizer(models.Model):
owner = models.ForeignKey(settings.AUTH_USER_MODEL, editable=False, null=True, blank=True )
title = models.CharField(max_length=255)
description = models.TextField()
feed = models.ForeignKey(Feed)
channels = models.ManyToManyField(Channel)
And in my project there can be any number of visualizers that can have extra attributes...
like one visualizer can have a 'base_color' extra attribute, and for another 'change_by_type' extra attribute... etc.. as:
#there can be 5 to 10 visualizer types VisualizerA, VisualizerB ...
class VisualizerA(models.Model):
#base visualizer attributes
base_color = models.CharField()
For now i am doing by adding an attributes text field to the base Visualizer model not adding any sub classes and keep the properties as json string. But i am having hard times with the forms... Is there a better way?
Is subclassing a choice? (But there can be 5 or 10 types of visualizer )
i need a way of doing this right...
Depending or your requirements "Django dynamic model fields" may be the solution. See post
Django dynamic model fields
In terms of of inheritance you can have Model inheritance with specialized Forms
Here is "Advanced Django Forms Usage" http://www.slideshare.net/pydanny/advanced-django-forms-usage
and/or Forms inheritance with common Model
see post http://pydanny.com/overloading-form-fields.html
Subclassing is imo best solution, in database You will have 1 table for all Visualizers with all fields from base class and 1 table for each child class with id column that will have same values as in base class and columns from child class fields. It's one to one relation under the hood, but when You save new instance of child model, django will automatically make corresponding field in base model.
More here: Django model interhitance
I have the following situation. I have three models, Post, User and Friends.
class User(models.Model):
name = models.CharField(max_length=100)
class Friend(models.Model):
user1 = models.ForeignKey(User,related_name='my_friends1')
user2 = models.ForeignKey(User,related_name='my_friends2')
class Post(models.Model):
subject = models.CharField(max_length=100)
user = models.ForeignKey(User)
Every time I bring users, I want to bring the number of his friends:
User.objects.filter(name__startswith='Joe').annotate(fc=Count('my_friends1'))
This works fine.
However, I want to make this work when I bring the users as nested objects of Post. I'm using there select_related to minimized DB calls, so I want to do something like:
Post.objects.filter(subject='sport').select_related('user').annotate(user__fc=Count('user__my_friends1'))
However, this creates field user__fc under post, and not field fc under post.user.
Is there a way to achieve this functionality?
You can make use of Prefetch class:
from django.db.models import Count, Prefetch
posts = Post.objects.all().prefetch_related(Prefetch('user', User.objects.annotate(fc=Count('my_friends1'))))
for post in posts:
print(post.subject)
print(post.user.fc)
NB : this does two database queries (Django does the join between Post and User in this case) :
'SELECT "myapp_post"."id", "myapp_post"."subject", "myapp_post"."user_id" FROM "myapp_post"
'SELECT "myapp_user"."id", "myapp_user"."password", "myapp_user"."last_login", "myapp_user"."is_superuser", "myapp_user"."username", "myapp_user"."first_name", "myapp_user"."last_name", "myapp_user"."email", "myapp_user"."is_staff", "myapp_user"."is_active", "myapp_user"."date_joined", COUNT("myapp_friend"."id") AS "fc" FROM "myapp_user" LEFT OUTER JOIN "myapp_friend" ON ("myapp_user"."id" = "myapp_friend"."user1_id") WHERE "myapp_user"."id" IN (3, 4) GROUP BY "myapp_user"."id", "myapp_user"."password", "myapp_user"."last_login", "myapp_user"."is_superuser", "myapp_user"."username", "myapp_user"."first_name", "myapp_user"."last_name", "myapp_user"."email", "myapp_user"."is_staff", "myapp_user"."is_active", "myapp_user"."date_joined"
You can define a custom manger for your models, as described here and then override its get_queryset() method to add the custom column to your model upon query.
In order to use this manager for a reverse relation, you should set the base manager as described in the docs.
Another approach would be something like this, which you specify the manager of the related model with a hard-coded attribute.