Django filter exclude with ReverseManager - django

I have a model Tenant and a model SocialMediaContextTenant that has a foreign key to the Tenant model.
class SocialMediaContextTenant(AbstractSocialMediaContext):
tenant = models.ForeignKey('campaigns.Tenant')
secret = models.CharField(...)
I would like filter all tenants where a connected SocialMediaContextTenant has the secret field set.
So far I have this query
Tenant.objects
.exclude(socialmediacontexttenant__secret='')
.values_list('id', flat=True)
But the exclude filter does not seem to work, since I still get results with an empty secret field

Looks like secret field has null value, not empty string. To exclude these records use __isnull lookup:
Tenant.objects.exclude(socialmediacontexttenant__secret='').exclude(socialmediacontexttenant__secret__isnull=True)

Related

How to get all id from model in django [duplicate]

I have a table called user_info. I want to get names of all the users. So the table has a field called name. So in sql I do something like
SELECT distinct(name) from user_info
But I am not able to figure out how to do the same in django. Usually if I already have certain value known, then I can do something like below.
user_info.objects.filter(name='Alex')
And then get the information for that particular user.
But in this case for the given table, I want to get all the name values using django ORM just like I do in sql.
Here is my django model
class user_info(models.Model):
name = models.CharField(max_length=255)
priority = models.CharField(max_length=1)
org = models.CharField(max_length=20)
How can I do this in django?
You can use values_list.
user_info.objects.values_list('name', flat=True).distinct()
Note, in Python classes are usually defined in InitialCaps: your model should be UserInfo.
You can use values_list() as given in Daniel's answer, which will provide you your data in a list containing the values in the field. Or you can also use, values() like this:
user_info.object.values('name')
which will return you a queryset containing a dictionary. values_list() and values() are used to select the columns in a table.
Adding on to the accepted answer, if the field is a foreign key the id values(numerical) are returned in the queryset. Hence if you are expecting other kinds of values defined in the model of which the foreign key is part then you have to modify the query like this:
`Post.objects.values_list('author__username')`
Post is a model class having author as a foreign key field which in turn has its username field:
Here, "author" field was appended with double undersocre followed by the field "name", otherwise primary key of the model will be returned in queryset. I assume this was #Carlo's doubt in accepted answer.

Foregin key field name is followed by _id

In a model, when a foreign key field is created then Django apparently create another field with the same field name followed by _id.
for example if I have
class Post(models.Model):
user = models.ForeignKey(User,on_delete=models.CASCADE,default=None)
dated = models.DateTimeField(auto_now=True)
...
Then I will have the following fields available:
id,user,user_id,dated
I am not sure why this field (user_id) was added?
Later I wanted to override my queryset in a class view
so I was confused which one to use (user field or user_id field)
:
def get_queryset(self):
queryset = super().get_queryset()
return queryset.filter(user_id=self.request.user.id)
Or
def get_queryset(self):
queryset = super().get_queryset()
return queryset.filter(user=self.request.user.id)
I tried both and both worked just fine
My question is:
1) What is the purpose of creating this additional field ?
2) What is the difference between the original foreign key field (user in my case) and user_id field?
3) Will both fields user and user_id available in the database? what is the point of that?
4) Is the content of user and user_id identical in each record? if so ,then what the purpose of this additional field that was created automatically by django?
Thanks a lot
Django only creates one column in the database for the foreign key.
The difference between the field and the _id attribute it generates is that accessing the field performs a query for the full set of columns from the related table in order to construct the complete related object. If you want the full object, use the field (and probably also use select_related() in the initial query to save you from doing N+1 queries).
On the other hand, if all you need is the DB-level value of the foreign key, which is usually the primary key of the related object (and often that is what you want), the _id attribute shortcut is there for you and already has the data, because that's what was actually in the foreign key column.
In other words, suppose I have models like this:
class ModelA(models.Model):
name = models.TextField()
class ModelB(models.Model):
name = models.TextField()
a_instance = models.ForeignKey(ModelA)
If you query for a ModelB, like ModelB.objects.get(pk=12), you'll get a query like this:
SELECT id, name, a_instance_id
FROM your_app.modelb
WHERE id = 12;
Notice a_instance_id is the name of the column -- it's just a foreign key, all it stores is a pointer to the primary key of a ModelA instance. If you just need that primary key, accessing the a_instance_id attribute has it already without needing to do another query. If you access the a_instance field, though, you get to do another query:
SELECT id, name
FROM your_app.modela
WHERE id = (whatever the value of that foreign key was);

Django handling Foreign Keys of tables in VIEWS in postgres; QuerySet always empty

Is Django or maybe POSTGRESQL losing information about primary keys and foreign keys when you create a view which relates to a view which relates to a table, which has primary and foreign keys?
I have a View-A (all 3 fields are Foreign Keys) and that view gets 2 fields from a View-B. The View-B gets its fields from a table-C. table-C has primary key and foreign key.
So when i access View-A with my django model, how do i treat those fields? I know they are foreign keys, but any kind of filter results in a empty Queryset.
if i use something like
myview = viewA.objects.using(db).all() # getting all the data
myview2= viewA.objects.using(db).all()[:5] # getting 5 objects
.
class viewA(models.Model):
class Meta:
db_table = "viewA"
x = models.ForeignKey(x, primary_key=True)
y = models.ForeignKey(y)
z = models.ForeignKey(z)
The problem is that i can not filter!
response=viewA.objects.using(db).filter(y_id=1) ERROR:= FieldError
Behind all those FK, there are integer/bigint fields.
Edit:
Since this are INNER JOINS i would like to access not only the fields from ViewA, but also from ViewB. x,y,z are from type ViewB. Maybe use select_related()?
So any clues if Django or postgres lose information about keys in views which relate to other views?
See my two comments; however, to answer your specific "query".
If you go to the docs, and see this paragraph:
https://docs.djangoproject.com/en/dev/ref/models/fields/#database-representation
You will note that foreign keys, by default, have the _id appended to their names. Now, there are occasions in which you need to access the column name directly and it's a good idea to be aware of the column as a "bigger picture" sort of thing, but at as far as Model API is concerned, you should, when doing something against a foreign key, use the attribute name given in the model instance.
Edit from your comment:
If you want to drill down and filter against some field in the foreignkey object, you just do y__fieldname = somevalue
Note that fieldname must be in the y object.
If you are getting back and empty queryset, this is because nothing in that column matched the value you gave it.
To test this, create a queryset directly on the "y" object and then try to do y.objects.fitler(fieldname=somevalue)
if you still get back and empty queryset, you know that value doesn't exist. Furthermore, you can look into the database and try a raw query in pgadminIII if you have that set up.

Filter haystack result with SearchQuerySet

I'm using haystack with whoosh, trying to restrict search results to entries created by the currently logged in user only.
The category model, for which I created an index, has a foreign key:
user = models.ForeignKey(User, editable=False)
And in my custom search view I want to filter like this:
searchqueryset = SearchQuerySet().filter(user=request.user.id)
form = SearchForm(request.GET, searchqueryset=searchqueryset, load_all=True)
if form.is_valid():
query = form.cleaned_data['q']
results = form.search()
In the database there is one entry for table category:
id name user_id
1 test10 1
And the current user id is indeed 1.
But I get No results.
When I do this:
searchqueryset = None
I get the "test10" category entry.
So does anyone know why the user id filter isn't working as expected?
Are you sure that the "user" in your Haystack index holds the integer value of user id? Perhaps it has some other user data(such as username) there, so the comparison simply does not work?
By default the Django user object returns the user name, not the user id.

tell django not to follow foreign key?

Is there a way to tell django not to follow a foreign key relationship when you instantiate a model instance? Something to put on the model itself? Something to pass to a queryset? I'd like to have a queryset that only returns instances with the foreign key id -- I don't want the instances to go off making queries to find its relatives. Something like the opposite of select_related?
The default behaviour of Django is to wait until a foreign key relationship is accessed before performing a database queries to populate the related model instance.
To side-step the automatic querying for related instances, rather than accessing the ForeignKey field attribute directly, access attribute_id, e.g.
class Person(models.Model):
name = models.CharField(max_length=200)
user = models.ForeignKey('auth.User')
# access the user id via user_id
person = Person.objects.all()[0]
print person.user_id
Try defer