how to get the value of an attribute (pk) using QuerySet - django

I am trying to get the value of the primary attribute (pk). How to do it ?
Equivalence for this
SELECT id FROM User WHERE username="Fokoa"

Multiple ways:
User.objects.filter(username='Fokoa').values_list('id', flat=True)
Or, if you know that username is unique:
user = User.objects.get(username='Fokoa')
user.id

You can use a .values_list(..) [Django-doc] for that:
from django.contrib.auth.models import User
User.objects.filter(username='Fokoa').values_list('pk', flat=True)
or we can conver this to a list of primary keys with:
from django.contrib.auth.models import User
list(User.objects.filter(username='Fokoa').values_list('id', flat=True))
That being said, it is not very common to query for a specific column in Django. It is good practice to see primary keys as "black box tokens", so not interpret these as integers process these. After all, summing up two primary keys frequently does not make much sense.

Related

Django - How to check all the attributes of a queryset?

I am looking a way to get all the attributes of a variable after we set the value in it using queryset.
For example...refer below code... using user.id or user.first_name i can get the value for that attribute. But if i want to check what all other attributes it has? Is there a way i can get.
If we use user then it will just return which is what we have defined in admin.py.
Code, i am using Django Shell
from django.contrib.auth.models import User
user=User.objects.get(id=1)
user.first_name # Will return some value say testUser
user.id # will return some value say 1
I guessing what you are saying is you want to print all attributes of an object instead of QuerySet
To print all attributes of an object you can do the follow:
from django.contrib.auth.models import User
user=User.objects.get(id=1)
print(user.__dict__)
But if you just what to find out what django default user models fields are, you can check this docs:
https://docs.djangoproject.com/en/3.0/ref/contrib/auth/
Django returns a tuple of fields associated with a model if you want.
Django 3.0:
from django.contrib.auth.models import User
User._meta.get_fields()
Adding to #MarkL 's answer:
You can pretty print it for better readability.
from django.contrib.auth.models import User
from pprint import pprint # new
user=User.objects.get(id=1)
pprint(user.__dict__) # new ----> pprint() instead of print()
Another way which I always prefer using over __dict__ is vars() method:
user=User.objects.get(id=1)
pprint(vars(user))
Both return the same result but to me vars() is more convenient to write than the dunder dict method i-e __dict__, coz I am too lazy to write 4 underscores.
Building on MarkL's answer, here is the same thing, but with nicer formatting:
[f"{key}: {value}" for key, value in user.__dict__.items()]
(Sorry, I don't have enough rep to post this as a comment.)

Django insert data to model with foreign key

I am using django models and am running into issues. I have a couple of models that I am trying to load data to, one with a foreign key to another. I will use two models as an example, but the hope is that I can write the code so that it will generalize to work for models with different names and different field names. The models look as follows:
class ProgramInfo(models.Model):
program_code = models.CharField(max_length=5, primary_key=True)
...
class StudentInfo(models.Model):
...
program_code = models.ForeignKey('ProgramInfo', on_delete=models.PROTECT)
I also have a dictionary called _model_dict with the field names of StudentInfo as the keys and the values being the values I want to put in the model. When I run
_model.objects.update_or_create(**_model_dict)
It tells me
Cannot assign "'ABCD'": "StudentInfo.program_code" must be a "ProgramInfo" instance.
Even though that value exists in the ProgramInfo table.
I have no issue inserting data to models without foreign keys using this same method.
As I understand it the value for the key in _model_dict of the foreign key field should not just be the value for a single field, but an object of the model the foreign key links to.
I tried singling out the foreign key fields in order to be able to use model_get with filter and obtain the row from the target model and put that in the _model_dict but I couldn't find out how to obtain the target model given a known ForeignKey field. Because I intend the to generalize I don't want to specify the target model in specific code, but will like to obtain it from the field that I managed to conclude was the foreign key field. I have been googling around for many hours now and can't find the attribute for the target model a of ForeignKey field.
i don't know if it will be useful, but here is the code I used for trying to create a class for the foreign key:
# check for foreign keys
_model_field_objects = [f for f in _model._meta.get_fields()]
foreign_key_fields_dict = {}
for field in _model_field_objects:
if field.__class__ is ForeignKey:
foreign_key_fields_dict[field.name] = field #here i try to obtain target model of the field
print("Foreign key fields are: " + str(foreign_key_fields_dict))
sys.stdout.flush()
for row in data:
_model_dict = {key: value for key, value in zip(titles, row) if key in _model_field_names}
# adjust foreign key to their class
for key in _model_dict:
filter_arguments = {}
if key in foreign_key_fields_dict:
filter_arguments[key] = _model_dict[key]
_model_dict[key] = foreign_key_fields_dict[key].objects.filter(**filter_arguments)
# insert to table
_model.objects.update_or_create(**_model_dict)
I am probably way over complicating this. If there is a simple way Django provides for adding to a model with foreign keys given the known value for the foreign key field (and not the full object for the model it points to) I would be glad to learn of it.
Thanks in advance for any help available!
because program_code is the primarykey in the ProgramInfo model, you can set or get using the value of that field:
for example, lets say you have a ProgramInfo instance with a primarykey that its value is 'abcd', you can create a StudentInfo using that like this:
StudentInfo.objects.create(program_code_id='abcd', ..... other fields ....)
because program_code_id is what that really is stored in the StudentInfo database.
I solved it in an non-elegant way that works for me. Other answers given might be better, but I am too scared to change my code for now as it seems to be working. Here is what I did in case it can help anyone else:
Using:
from pprint import pprint
pprint(vars(myobject))
I managed to find out that the ForeignKey type object has an attribute ForeignKey.related_model. Once I had the model I could use it as follows to obtain the row in the model that is being pointed to:
field.related_model.objects.get(pk=_model_dict[key])
where field is the field in the model that I am trying to insert data into. The result from that could be put into the _model_dict dictionary containing all the other values for fields for the model I am inserting data into, so using the following worked for inserting the data:
_model.objects.update_or_create(**_model_dict)
NOTE:
The update_or_create would sometimes crash saying there was a problem with uniqueness, which I thought was the "update_or" part was suppose to resolve. In any case adding a try/except around it solved that problem for me - though I know its a hack..

How to select users and groups in single query in django?

I need something like this for selecting user and groups in a single query in django.
user = User.objects.select_related('groups').get(id=user_id)
I don't want to use raw queries for this.
There is another way to do this which makes two queries:
user = User.objects.get(id=user_id)
groups = user.groups
Edit: It seems there is no way to do that in one query except raw sql or extra.
So if you only want to get one user, your second example should work.
If many users:
You should use prefetch-related, but in two queries.
prefetch_related, on the other hand, does a separate lookup for each relationship, and does the ‘joining’ in Python. This allows it to prefetch many-to-many and many-to-one objects, which cannot be done using select_related, in addition to the foreign key and one-to-one relationships that are supported by select_related. It also supports prefetching of GenericRelation and GenericForeignKey.
...
The additional queries in prefetch_related() are executed after the QuerySet has begun to be evaluated and the primary query has been executed.
So if you want to prefetch groups, it will execute two queries whether you use all or get.
You can use prefetch related in the view, and then pass it to the template
def view(request):
user = User.objects.all().select_related(
).prefetch_related(
'groups',
).get(pk=request.user.pk)
return render(request, 'app/template.html', {
'user': user,
})
You should select from Group model 'cause the relation is many to many.
I have not tried my answer but perhaps it will work;
group_list_with_user = Group.objects.filter(user = USERID).all()
thereafter you can access all groups which are assigned to user and access user for example;
group_list_with_user[0].name # group name
group_list_with_user[0].user.first_name # user's first name

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.

django unique field

is there another REGEX way (or another way) to ensure that a model class field would be unique? (it is not a key, or at least not declared as a key, is shoulb be a simple CharField)
Thanks
The normal way to make a single field unique is to use the unique argument to the field constructor.
If you need to make this unique on more than one field, have a look at:
unique-together
There are two ways of doing so.
The first is to mark the entire column as unique. For example:
product_name = models.Charfield(max_length=10, unique=True)
This method is good when you want your entire column to be inherently unique regardless of the situation. This can be used for username, id, key etc.
However, if the column cannot be inherently unique but it has to be unique in relation to others, you have to use the manual way.
from django.core.exceptions import ObjectDoesNotExist
try:
n = WishList.objects.get(user=sample_user, product=sample_product)
# already exists
return False
except ObjectDoesNotExist:
# does not exist
wish_list = WishList(user=sample_user, product=sample_product)
wish_list.save()
return True
Take this as an example. You have a wish list which none of the items can be unique. A single user can have many products and a single product can be in the wish list of many users. However, a single user cannot add one particular product to his or her wish list more than once. And this is where unique=True cannot be used and we have to use try and except