From the title this sounds like something I shouldn't wanna do. But I have two models. Both have AutoField PK's and model B has a foreign key ID for A.
In my form to create B, I have all of B's fields including the foreign key ID. This simply shows up to the user as something like "B Object 1". This is absolutely useless to me as when I have more items I'd rather have a name to identify it to the user.
So my question is: can I substitute A.name in place of the foreign key ID, but still save just the foreign key when it comes to saving the model?
You can use the method __str__ in your model B. That should change the 'friendly' output for the model, and you can compose a string with multiple values as well.
def __str__(self):
return self.your_field
Related
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.
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..
I'm having some trouble understanding many-to-many fields in Django.
When I create a many-to-many field, ex:
class GlobalPart (Models.model):
...
category_id=models.ManyToManyField(Category, related_name = 'globalpart')
...
and
class Category (Model.model):
...
category = models.CharField(max_length=250)
...
I notice that it created a new table called appname_globalpart_category_id in addition to the appname_globalpart table for the GlobalPart model.
What I'm wondering is, how should the field types in that table be defined. I would think that
there should be at least one foreign key there to relate the fields. But instead there is the primary key for the table, and the other fields are integers (globalpart_id and category_id).
So my question is -- is that normal? Or did I somehow define the many-to-many field incorrectly? And my next question is how would I get all the category_ids associated to a particular GlobalPart?
(1) short answer: Yes this is normal.
Long answer: ManyToMany table will need a foreign key to both Category and GlobalPart tables. Strictly speaking those two foreign keys should be sufficient. The extra pk that you see in there is just for django magic. You can really get away with only those two foreign keys in that table if you manually define the many-to-many table yourself. However if you let django do it for you (by using ManyToManyField) you get this extra pk
(2) I suggest changing your model fields category_id to categories:
class GlobalPart (Models.model):
categories=models.ManyToManyField(Category, related_name = 'globalpart')
This is because, ManyToManyFields refers well to "many" items. This field does not refer to "one" category_id, it refers to all related categories. So when naming it would be natural to name it accordingly.
As for accessing all categories you can do it by accessing the "categories" property. Say if your object instance named global_part, you can access categories like this:
categories = global_part.categories.all()
Instead of all(), you can use filter() or exclude() the same way you use it when querying models.
Here is a link to related django docs
What do you think a foreign key is? It's a field containing values that equate to IDs - usually primary keys - in the "foreign" table. If the other table has integer keys, as most Django tables do, then the foreign key field will be of type integer as well.
Additionally, Django creates constraints so that the database will enforce that the IDs do actually reference valid values in the foreign table. Depending on your database, these might or might not be displayed as part of the field definition.
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.
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