I'm trying to use some of the shiny new Postgres fields in Django.
For a booking system the DateRangeField seems perfect.
Can I use the validators UNIQUE or even UNIQUE_DATE in regard to this field?
The excellent Django documentation is, unfortunately, not elaborating regarding validators and the Postgres fields.
So basically, to my knowledge, the field option unique and unique_for_date do not work with Postgres DateRange fields.
However, there is a way using a Porstgres index
We need a btree_gist combined index in Postgres.
This is a Postgres extension and it is provided with Postgres, we just need to install it into the database with
CREATE EXTENSION btree_gist;
Once we have this, we can have a constraint on the date_range field with combined with another field in our table.
Say we have a hotel room number (room_id) and a booking date range (dt_range), which, combined, should be unique. Our constraint would be
ALTER TABLE <yourtablename> ADD EXCLUDE USING gist ( room_id WITH =, dt_range WITH && );
Now, whenever we have a booking for room room_id with conflicting booking dates, Postgres will throw an error which is a
django.db.utils.IntegrityError
I hope that helps!
Related
I was trying to find the answer in Django Documentation, but failed to do so.
Can anyone please explain how does Django "match" the objects of the related models?
eg. I have two models, and I am showing Django that they are related:
class Reporter(models.Model):
# ...
pass
class Article(models.Model):
reporter = models.ForeignKey(Reporter, related_name='report')
Then the magic happens and Django matches the two models, and adds _id field.
My question is:
How does Django know which objects of those two models are related?
Is it checking each and every field of those objects and sees if there is a match?
EDIT:
How does Django determine that a particular Reporter object is related to a particular Article object?
I understand that when it finds a match it adds the _id field, what I do not understand is based on what django "matches" two objects from different models.
To be more specific:
Let's say that there are two Reporter objects - r1 and r2.
There is one object in Article class - a1
How does django know that a1 is related to r1 and not to r2?
Thanks for your help!
It looks like you're not really SQL-savy, because there's really no "magic" involved and it's all basic relational model design.
Your above models translates to the canonical one to many SQL schema:
CREATE TABLE yourappname_reporter (
id int(11) NOT NULL AUTO_INCREMENT,
PRIMARY KEY(id)
);
CREATE TABLE yourappname_article(
id int(11) NOT NULL AUTO_INCREMENT,
reporter_id int(11) NOT NULL,
PRIMARY KEY(id),
CONSTRAINT `reporter_id_refs_id_XXXX` FOREIGN KEY (`reporter_id`) REFERENCES `yourappname_reporter` (`id`)
);
As you can see, Django adds an 'id' primary key to your models (since you didn't explicitely defined one yourself), and the Article.reporter field translates to the reporter_id foreign key which references reporter.id. Here again Django uses the reporter.id primary key as foreign key reference as a (very sensible) default since you didn't explicitely told him to target another field.
Now when you create a new Article, you have to provide a Reporter instance, ie (assuming you have a reporter with id 1):
reporter = Reporter.objects.get(id=1)
article = Article.objects.create(reporter=reporter)
Then the ORM will issue the SQL query insert into yourappname_article (reporter_id) values (1), hence relating this new article row with this reporter row, and you can now get all articles from reporter 1 with select * from yourappname_article where reporter_id=1 (which is the query Django ORM will issue for Article.objects.filter(reporter_id=1))
To make a long story short: Django ORM is only a thin wrapper over your database, and you do have to know what a relational database is, how it works and how to properly use it (including how to properly design your db schema) if you expect to do anything good. If you don't even know what a foreign key is then by all means first learn about the relational model, proper relational design and basic SQL stuff.
Is it possible to prevent multiple querys when i use django ORM ? Example:
product = Product.objects.get(name="Banana")
for provider in product.providers.all():
print provider.name
This code will make 2 SQL querys:
1 - SELECT ••• FROM stock_product WHERE stock_product.name = 'Banana'
2 - SELECT stock_provider.id, stock_provider.name FROM stock_provider INNER JOIN stock_product_reference ON (stock_provider.id = stock_product_reference.provider_id) WHERE stock_product_reference.product_id = 1
I confess, i use Doctrine (PHP) for some projects. With doctrine it's possible to specify joins when retrieve the object (relations are populated in object, so no need to query database again for get attribute relation value).
Is it possible to do the same with Django's ORM ?
PS: I hop my question is comprehensive, english is not my primary language.
In Django 1.4 or later, you can use prefetch_related. It's like select_related but allows M2M relations and such.
product = Product.objects.prefetch_related('providers').get(name="Banana")
You still get two queries, though. From the docs:
prefetch_related, on the other hand, does a separate lookup for each relationship, and does the ‘joining’ in Python.
As for packing this down into a single query, Django won't do it like Doctrine because it doesn't do that much post-processing of the result set (Django would have to remove all the redundant column data, since you'll get a row per provider and each of these rows will have a copy of all of product's fields).
So if you want to pack this down to one query, you're going to have to turn it around and run the query on the Provider table (I'm guessing at your schema):
providers = Provider.objects.filter(product__name="Banana").select_related('product')
This should pack it down to one query, but you won't get a single product ORM object out of it, instead needing to get the product fields via providers[k].product.
You can use prefetch_related, sometimes in combination with select_related, to get all related objects in a single query: https://docs.djangoproject.com/en/1.5/ref/models/querysets/#prefetch-related
In MySQL, we can have foreign key relationships between tables in different databases. I am finding it difficult to translate this relationship on the respective Django models.
I have read in the docs that cross-db relationships are not supported, but can we override some property/function so that we can make tables be identified as DB.table rather than table?
For example, there is table table1 in DB1 that gets referenced in some table2 in DB2. Django tries (unsuccessfully) to find table1 in DB2, and raises a DatabaseError
Variable Value
charset 'latin1'
exc <class '_mysql_exceptions.ProgrammingError'>
self <MySQLdb.cursors.Cursor object at 0x2a87ed0>
args (195,)
db <weakproxy at 0x2a95208 to Connection at 0xdad0>
value ProgrammingError(1146, "Table 'DB2.table1' doesn't exist")
query 'SELECT (1) AS `a` FROM `table1` WHERE `table1`.`ndx` = 195 LIMIT 1'
Almost everything works, except the save method. A push in the right direction would help a lot!
You required Manually Selecting a Database.
Looking on the error you gave, you should do something like this:
qs = table1.objects.using('DB1 ').filter(pk=id)
# just an example
In this example we are explicitly telling Django to locate table1 in DB1.
It seems we cannot do anything to get relationships working between two tables in different mysql DBs. This is by design. Ticket 17875 has some info. We need to write code that works around this.
I've got 2 existing models that I need to join that are non-relational (no foreign keys). These were written by other developers are cannot be modified by me.
Here's a quick description of them:
Model Process
Field filename
Field path
Field somethingelse
Field bar
Model Service
Field filename
Field path
Field servicename
Field foo
I need to join all instances of these two models on the filename and path columns. I've got existing filters I have to apply to each of them before this join occurs.
Example:
A = Process.objects.filter(somethingelse=231)
B = Service.objects.filter(foo='abc')
result = A.filter(filename=B.filename,path=B.path)
This sucks, but your best bet is to iterate all models of one type, and issue queries to get your joined models for the other type.
The other alternative is to run a raw SQL query to perform these joins, and retrieve the IDs for each model object, and then retrieve each joined pair based on that. More efficient at run time, but it will need to be manually maintained if your schema evolves.
I created the models in a Django app using manage.py inspectdb on an
existing postgres database. This seemed to work except that all the
primary keys were described in the models as IntegerFields, which made
them editable in the admin panel, and had to be hand-entered based on
knowledge of the id of the previous record. I just learned about this
after some usage by the client, so I went back to change things like
blog_id = models.IntegerField(primary_key=True)
...to...
blog_id = models.AutoField(primary_key=True)
Now the id fields don't appear in the admin panel (good), but adding new rows
has become impossible (not good).
IntegrityError at /admin/franklins_app/blog/add/
duplicate key value violates unique constraint "blog_pkey"
What's the fix? (Bonus question: is it possible to capture the value that Django is trying to assign as the primary key for the new row?)
The sequence behind the serial field which is your primary key doesn't know about the manually entered records.
Find the maximum value of the primary key:
SELECT MAX(<primary_key>) FROM <your_table>;
Then set the next value of the underlying sequence to a number greater than that:
SELECT SETVAL('<primary_key_seq>', <max_value_in_primary_key_plus_something_for_safety>);
You'll find the name of the sequence (mentioned above as <primary_key_seq>) using:
SELECT pg_get_serial_sequence('<your_table_name>', '<primary_key_column_name');