Django queryset has no attribute when using select related - python

I'm trying to using select_related to queryset, and it returns queryset has no attribute when using select related. I made two models, and one model has foreignkey column, it is 1:1.
models
class User(models.Model):
name = Charfield()
class Item(models.Model):
user = models.ForegnKey(User, on_delete=models.CASCADE, related_name='user_item_set', null=True)
When I try this queryset, it says queryset does not have select related.
users = User.objects.get(id=pk).select_related('user_item_set')

Looks like you misunderstood the usage of select_related().
Returns a QuerySet that will “follow” foreign-key relationships, selecting additional related-object data when it executes its query.
It can be used on Item model (the model which defines the ForegnKey field) and not User model.
What you need to use is prefetch_related(). Something like this:
users = User.objects.get(id=pk).prefetch_related('item_set')

Related

How to allow boolean True on just one model in table in Django?

I've got a model where I would like there to be able to have one set as the 'app default'.
In this model I added a field named is_app_default in order to help accommodate this.
class TreeLevel(models.Model):
id = models.BigAutoField(primary_key=True)
short_description = models.CharField(max_length=200)
long_description = models.TextField()
is_app_default = models.BooleanField(default=False)
class Meta:
verbose_name = "Tree Level"
verbose_name_plural = "Tree Levels"
class Layer(models.Model):
id = models.BigAutoField(primary_key=True)
tree_levels = models.ManyToManyField(TreeLevel)
description = models.TextField()
class Meta:
verbose_name = "Layer"
verbose_name_plural = "Layers"
The Layer model links to TreeLevel with an m2m. Ultimately I would like the is_app_default TreeLevel automatically added to every Layer m2m relationship - which is why there can only be one TreeLevel with is_app_default set as True.
My potential solution(s):
Users with admin may be creating new TreeLevel objects - so I need to make sure they aren't setting that Boolean in any new models. I think I can override the save() method on TreeLevel to check the DB to see if another with that boolean as True exists - if so? Don't save the 'new' one and return an error. But I think this hits the database - causing unnecessary queries potentially?
Then additionally, I would also need to override the save() method on Layer and add the 'default' TreeLevel to that many2many at that time.
Is there a good way to 'automatically' handle this with these relationships?
My ultimate goal:
Have a default TreeLevel that is automatically added to every Layer many to many relationship whenever a Layer is created.
Questions:
Would my proposed solution work?
I've tried looking into Djangos Unique Constraints, but I think those are more on a row level, as opposed to a Table level.

Django intermediary model

I dont understand Django Intermediary models at all. Let's say that i want to add one more additional field to User model, and store relationship between two users in another model(intermediary) like this:
class Contact(models.Model):
user_from = models.ForeignKey(User...)
user_to = models.ForeignKey(User...)
...
And the field i want to add is:
following = models.ManyToManyField('self',
through=Contact,
related_name='followers',
symetrical=False)
What really happen when i call user_object.followers.all() and what is the difference between user_object.following.all() are they both the same?

Convert join SQL query into django

I am new to django and trying out stuff with it.
How do I display selected fields from the joined table.
For example:
I have two models, X and Y. I am merging these two models based on the foreign key of model Y.
class X(models.Model):
name = models.CharField()
id = models.AutoField(primary_key=True)
class Y(models.Model):
owner_user = models.ForeignKey(X, models.DO_NOTHING,
db_column='id')
detail = models.CharField()
How do I write this query as a django code?
SELECT name, id, Body_details
FROM X, Y
WHERE X.id = Y.OwnerUserId;
You can use select_related
a = Y.objects.select_related('OwnerUserId').all()
for object in a:
print(object.OwneruserId.name, object.OwneruserId.id, object.body)
You can make use of select_related here.
result = Y.objects.select_related('owner_use')
All the work behind joining will automatically be done by this ORM using select_related. You can see previously asked questions similar to this one here.
You need to use the related_name of the ForeignKey field, which is y_set by default, to access the reverse relationship of model :
some_id = 1
instance = X.objects.get(id=some_id)
instance.y_set.all()

Fast filter on related fields in django

I have 2 models in my django project.
ModelA(models.Model):
id = models.AutoField(primary_key=True)
field1 = ...
~
fieldN = ...
ModelB(models.Model):
id = models.AutoField(primary_key=True)
a = models.ForeignKey(A, on_delete=models.CASCADE)
field1 = ...
~
fieldN = ...
Here I have one-to-mane relation A->B. Table A has around 30 different fields and 10.000+ rows and table B has around 15 and 10.000.000+ rows. I need to filter firstly by the several ModelA fields and then for each of the filtered ModelA row/object get related ModelB objects and filter them by several fields. After that I need to serialize them in JSON where all ModelB packed in one field as array.
Is it possible to perform this around the 1-3 second? If yes, what is the best approach?
I use PostgreSQL.
EDIT:
Now I am doing it like chain .filter() on simple ModelA fields and then iterate over resulted QuerySet and get set of ModelB for each ModelA instance,but i suspect, that the second part of this solution will slow down whole process, so I suppose there is a better way to do it.
It may be faster to do a query like this:
model_a_queryset = ModelA.objects.filter(field=whatever)
model_b_queryset = ModelB.objects.filter(a__in=model_a_queryset)
Because Django does lazy queryset evaulation, this will only result in one hit to the database.
As an aside, there is no need to define id = Autofield fields on your models. Django includes them by default.

Django: meta class order ignoring NULL

I need to sort queryset using Django model's meta class.
I've defined it like this:
class MyModel(models.Model):
order = models.IntegerField(blank=True, null=True)
class Meta:
ordering = ['order']
Some records have null as its "order" value.
If I get queryset, then the records that has null as order value are placed at beginning of result.
I just want to place such records at the end of queryset.
I've checked some articles for this purpose.
django order by isnull value?
Django : Order by position ignoring NULL
But I need it to be done using Django model's Meta class.
Is there any idea to do it via Meta class?
Regards
Philip

Categories