Difference between PositiveInteger and PositiveSmallInteger Field in Django - django

There is no difference between PositiveInteger and PositiveSmallInteger field in the Django source code. But, Django documentation says,
PositiveInteger starts from 0 to 2147483647 and PositiveSmallInteger starts from 0 to 32767.
Please clarify me what is the difference between these two types.
Thanks in advance.

This is one of those things that is the way it is because it got that way.
Django supports SmallIntegerField because Django grew up on PostgreSQL, and PostgreSQL supports smallint. The PosgreSQL docs say
The smallint type is generally only used if disk space is at a premium.
Also there's a difference in the code if you check the backends of Django. There you see it uses the SMALLINT feature on some databases, for example sqlite.
...
class FlexibleFieldLookupDict:
# Maps SQL types to Django Field types. Some of the SQL types have multiple
# entries here because SQLite allows for anything and doesn't normalize the
# field type; it uses whatever was given.
base_data_types_reverse = {
'bool': 'BooleanField',
'boolean': 'BooleanField',
'smallint': 'SmallIntegerField',
'smallint unsigned': 'PositiveSmallIntegerField',
'smallinteger': 'SmallIntegerField',
'int': 'IntegerField',
'integer': 'IntegerField',
'bigint': 'BigIntegerField',
'integer unsigned': 'PositiveIntegerField',
'decimal': 'DecimalField',
'real': 'FloatField',
...

Related

Filter List in Django JSON Field with string contains

My Django JSON field contains a list of values like ["N05BB01", "R06AX33"].
atc_code = JSONField(default=list())
I would like to filter this field, for 'does any string in list contain "N05"?'.
like
mymodel.objects.filter(?????)
In this case if you are not using SQLite or Oracle, you can use contains:
mymodel.objects.filter(atc_code__contains='N05')
Which generates this SQL:
SELECT * FROM "mymodel" WHERE UPPER("mymodel"."atc_code"::text) LIKE UPPER(%N05%)
Relational-based answer
Usually, such an approach (with a list of values in JSONField) can be possible when the relational structure is used in the wrong way.
The best approach here:
Create a new model that describes your atc_code entity. For example AtcCode
Depends on the meaning of the atc_code and its relation to the MainEnity use ForeignKeyField or ManyToManyField
Utilize all pros from the relational database and powerful Django ORM with such built-in features as filtering, adding, removing, querying with any database backend.
It will work on any supported database. A relational database will work faster when you are using relations properly.
My recommendation is to use JSONField when you have a really unstructured object.

Django: using C collation on a Postgres column?

I am using Django 1.7 and Postgres 9.4. I would like to create an index using C collation on a VARCHAR column in my database.
This is because C-collated indexes can apparently make SELECT... LIKE queries much faster, and I'm noticing that these queries are slow in my database, even though they are using a varchar_pattern_ops index.
From the Django models file, is it possible to specify that a particular index should use C collation? The documentation doesn't mention this, so I assume not.
If I create the index manually in Postgres and specify C collation, can I then continue to use the Django ORM with startswith queries and use the index? In other words, will these queries from Django automatically specify C collation, or will they continue to ask for UTF-8 collation, thus bypassing the index?
Perhaps I could get round this by specifying that the whole database should use C collation, but I'm not sure. Any advice would be appreciated.

Queryset sorting: Specifying column collation for django ORM query

I started investigating why my Django Model.objects.filter(condition = variable).order_by(textcolumn) queries do not yield objects in correct order. And found out that it is database (Postgresql) issue.
In my earlier question (Postgresql sorting language specific characters (collation)) i figured out (with a lot of help from zero323 in actually getting it to work) that i can specify collation per database query like this:
SELECT nimi COLLATE "et_EE" FROM test ORDER BY nimi ASC;
But as much as i can see, order_by only accepts field names as arguments.
I was wondering, that if it is somehow possible to extend that functionality to include also the collation parameter? Is it possible to hack it in somehow using mixins or whatnot? Or is feature request the only way to do this right now?
I wish it would work something like this:
Model.objects.filter(condition = variable).order_by(*fieldnames, collation = 'et_EE')
Edit1:
Apparently im not the only one to ask for this:
https://groups.google.com/forum/#!msg/django-developers/0iESVnawNAY/JefMfAm7nQMJ
Alan
As #olau menioned in the comment, since Django 3.2 Collate utility is available. For older Django versions see the original information below the following code sample:
# Starting with Django 3.2:
Test.objects.order_by(Collate('nimi', 'et_EE'))
Since Django 1.8 order_by() accepts not only field names but also query expressions.
In another answer I gave an example of how you can override the default collation for a column. The useful query expression here is Func(), which you may subclass or use directly:
nimi_et = Func(
'nimi',
function='et_EE',
template='(%(expressions)s) COLLATE "%(function)s"')
Test.objects.order_by(nimi_et.asc())
Yet, note that the resulting SQL will be more like:
SELECT nimi FROM test ORDER BY nimi COLLATE "et_EE" ASC;
That is, the collation is overridden in ORDER BY clause rather than in SELECT clause. However, if you need to use it in a WHERE clause, you can use Func() in annotate().
allright. It seems that right now the Raw Queries are the only way to do this.
But There is django ticket open which will hopefully be closed/resolved sometime soon.

How to determine the maximum integer the model can handle?

"What is the biggest integer the model field that this application instance can handle?"
We have sys.maxint, but I'm looking for the database+model instance. We have the IntegerField, the SmallIntegerField, the PositiveSmallIntegerField, and a couple of others beside. They could all vary between each other and each database type.
I found the "IntegerRangeField" custom field example here on stackoverflow. Might have to use that, and guess the lowest common denominator? Or rethink the design I suppose.
Is there an easy way to work out the biggest integer an IntegerField, or its variants, can cope with?
It depends on your database backend.
Use ./manage.py sql your_app_name to check generated types for your DB-columns, and look through your database documentation for type ranges.
For MySQL: http://dev.mysql.com/doc/refman/5.1/en/numeric-types.html
For PostgreSQL: http://www.postgresql.org/docs/8.1/static/datatype.html#DATATYPE-TABLE
Can't be easily done. Just set a constant and use that.
MAX_SMALL_INT = 32767
position = models.PositiveSmallIntegerField(default=MAX_SMALL_INT)

How to limit columns returned by Django query?

That seems simple enough, but all Django Queries seems to be 'SELECT *'
How do I build a query returning only a subset of fields ?
In Django 1.1 onwards, you can use defer('col1', 'col2') to exclude columns from the query, or only('col1', 'col2') to only get a specific set of columns. See the documentation.
values does something slightly different - it only gets the columns you specify, but it returns a list of dictionaries rather than a set of model instances.
Append a .values("column1", "column2", ...) to your query
The accepted answer advising defer and only which the docs discourage in most cases.
only use defer() when you cannot, at queryset load time, determine if you will need the extra fields or not. If you are frequently loading and using a particular subset of your data, the best choice you can make is to normalize your models and put the non-loaded data into a separate model (and database table). If the columns must stay in the one table for some reason, create a model with Meta.managed = False (see the managed attribute documentation) containing just the fields you normally need to load and use that where you might otherwise call defer(). This makes your code more explicit to the reader, is slightly faster and consumes a little less memory in the Python process.