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)
I want to create a model that joins two tables in my DB. When writing the foreign keys like this:
fromnode = models.ForeignKey(znode.code)
tonode = models.ForeignKey(znode.code)
there is an error: type object 'znode' has no attribute 'code', but there is such an attribute in znode:
class znode(models.Model):
code = models.DecimalField(max_digits=65535, decimal_places=65535, blank=True, primary_key=True)
How do I write this correctly?
Just use the class name znode instead of znode.code. Django automatically adds an id column to every model which will be used as reference as mentioned in the documentation.
Behind the scenes, Django appends "_id" to the field name to create its database column name. In the above example, the database table for the Car model will have a manufacturer_id column.
Also you should use CamelCaseClassNames to meet pep8 coding style conventions.
Is is possible to define foreign keys referencing multi columns in another model?
For example one foreign key references a two-column index in the product table, and the SQL statement:
FOREIGN KEY (product_category, product_id) REFERENCES product(category, id)
BTW I've looked into django.contrib.contenttypes and don't think that's the perfect solution for this kind of scenario.
It is not supported yet. There is a ticket and possible ways to handle it if you want to. maybe you could even run custom sql
Multi-Column Primary Key support
Relational database designs use a set of columns as the primary key for a table. When this set includes more than one column, it is known as a “composite” or “compound” primary key. (For more on the terminology, here is an article discussing database keys).
Currently Django models only support a single column in this set, denying many designs where the natural primary key of a table is multiple columns. Django currently can't work with these schemas; they must instead introduce a redundant single-column key (a “surrogate” key), forcing applications to make arbitrary and otherwise-unnecessary choices about which key to use for the table in any given instance.
This page discusses how to have Django support these composite primary keys. There are a lot of details to get right here, but done right, it would allow for more flexibility and potential simplicity in data modeling.
Current Status
Current state is that the issue is accepted/assigned and being worked on, and there is a partial implementation at http://github.com/dcramer/django-compositepks. The implementation allows having composite primary keys. However, support for composite keys is missing in ForeignKey and RelatedManager. As a consequence, it isn't possible to navigate relationships from models that have a composite primary key.
Discussions:
David Cramer's initial patch
The composite foreign key API design
Ticket
Note - SqlAlchemy allows this as described below and you can use SqlAlchemy to replace Django's ORM
Foreign keys may also be defined at the table level, using the ForeignKeyConstraint object. This object can describe a single- or multi-column foreign key. A multi-column foreign key is known as a composite foreign key, and almost always references a table that has a composite primary key. Below we define a table invoice which has a composite primary key:
invoice = Table('invoice', metadata,
Column('invoice_id', Integer, primary_key=True),
Column('ref_num', Integer, primary_key=True),
Column('description', String(60), nullable=False)
)
And then a table invoice_item with a composite foreign key referencing invoice:
invoice_item = Table('invoice_item', metadata,
Column('item_id', Integer, primary_key=True),
Column('item_name', String(60), nullable=False),
Column('invoice_id', Integer, nullable=False),
Column('ref_num', Integer, nullable=False),
ForeignKeyConstraint(['invoice_id', 'ref_num'], ['invoice.invoice_id', 'invoice.ref_num'])
)
Reference
Yes its possible but you will need to create a composite key when you use multiple column constraint i.e. foreign key or primary key.
For example:
CREATE TABLE Student (
S_num INTEGER,
S_Cate INTEGER,
S_descr CHAR(200),
PRIMARY KEY (S_num, S_Cate))
CREATE TABLE sub_Student (
Ssub_ID INTEGER PRIMARY KEY,
Sref_num INTEGER,
Sref_Cate INTEGER,
sub_descr CHAR(500),
FOREIGN KEY (Sref_num, Sref_Cate) REFERENCES Student
(S_num, S_Cate))
Anyway, you can to create a "Django fixture" like this:
CREATE INDEX product_category_id_id ON product (category_id, id);
To do this, you must to create a file named product.sql on subfolder sql where your model resides. The fixture is loaded on initial syncdb.
#pratik-mandrekar's answer is excellent, but I wanted to point out that even without proper multi-column primary keys; django is able to accommodate queries spanning multi-column foreign keys. Here's an example based on a legacy database who's schema I wasn't permitted to modify:
Given:
from django.db import models
class Account(models.Model):
# Collectively, location_no and occupant_no function as the primary key for Account.
location_no = models.IntegerField()
occupant_no = models.SmallIntegerField()
name = models.CharField(max_length=100)
class Meta:
managed = False
db_table = 'csracct'
unique_together = (('location_no', 'occupant_no'),)
class Call(models.Model):
call_id = models.IntegerField(primary_key=True)
# Collectively, location_no and occupant_no act as a foreign key to Account.
location_no = models.IntegerField()
occupant_no = models.SmallIntegerField()
notes = models.TextField()
class Meta:
managed = False
db_table = 'csrcall'
Here's how you'd use extra() to fetch the 10 most recent calls for accounts with the name 'steve':
calls = Call.extra(
tables = ['csracct'],
where = [
'csracct.location_no=csrcall.location_no',
'csracct.occupant_no=csrcall.occupant_no',
'csracct.name=%s',
],
params = ['steve'],
).order_by('-call_id')[:10]
It's not the most elegant solution, but extra() is part of django's base queryset toolkit; so it plays well with the rest of your django code. Notice how we order_by, and limit/slice the queryset using the usual django methods.
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.
Hi I'm having trouble with what I thought would be an easy task.
I am retrieving a post from the database. The Post entity has a field createdBy which is associated to a User entity.
What I would like to do is load Post and User with two separate queries (no join). That means I need to have access to the created_by foreign key integer on the $post object. Doctrine does not seem to expose that at all. A var_dump of post shows createdBy => null. If I join the user on directly in the post query createdBy => User object. Is there no way to get the created_by foreign key integer from post so I can query for the user?
Thanks
Use this on your query:
$q->setHint(\Doctrine\ORM\Query::HINT_INCLUDE_META_COLUMNS, true);
$q->getResult(\Doctrine\ORM\Query::HYDRATE_ARRAY);
Hydratation is disabled, so you have your result as an array.