django-compositepk-model


Namedjango-compositepk-model JSON
Version 1.0.3 PyPI version JSON
download
home_pageNone
SummaryExtended Django Model class with composite-primary-key support
upload_time2024-05-23 03:18:07
maintainerNone
docs_urlNone
authorNone
requires_python>=3.6
licenseMIT License
keywords multi-column primary key composite primary keys django django-admin model
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # django-compositepk-model

[日本語](https://gijutsu.com/2021/06/06/djangodjango-compositepk-model/#cpkmodel)
 
Provide an extended Django Model class named 'CPkModel' that supports composite primary keys. Also provide an extended Query class 'CPkQuery' that supports multi-column lookups.

This package supports treating legacy db tables with a composite primary key, without adding a surrogate key.

This is my other approach to [ticket373](https://code.djangoproject.com/ticket/373).

## Features

### 1. Easy to use

For a table with a composite primary key, change the base class from Model to CPkModel, and set 'unique_together' in Meta. In addition, set 'primary_key=True' to each primary keys.

(model definition sample)

```python
from django.db import models
from cpkmodel import CPkModel

# Normal Model
#   primary_key is auto 'id'
class Company(models.Model):
    name = models.CharField(max_length=100)
    established_date = models.DateField()
    company_code = models.CharField(max_length=100)

    class Meta:
        db_table = 'Company'

# Child Model (CpkModel)
#   composite primary key: company_id, country_code
class CompanyBranch(CPkModel):
    company = models.ForeignKey(
        Company,
        primary_key=True,       # for CompositePK
        on_delete=models.CASCADE,
    )
    country_code = models.CharField(
        max_length=100,
        primary_key=True,       # for CompositePK
    )
    name = models.CharField(max_length=100)
    established_date = models.DateField()

    class Meta:
        managed = False  # for CompositePK *1
        db_table = 'CompanyBranch'
        unique_together = (('company', 'country_code'),)  # for CompositePK
```

That's all. No additional definitions or virtual fields are required.

*1: "Migration" will fail because "primary_key=True" to multi-column unless "managed = False". 
    Legacy tables already exisit, or have to be created by hand.
    Or, comment out "primary_key=True" and "managed=False" while migration.
    
### 2. Admin avairable

CPkModel can be used in Django Admin. The values of composite primary key are displayed in a comma separated style. Change(Update), Delete are fine. Add(Create) has a problem that CreateView do unique check to each key Field. So you can't add enough child records. But, this is only CreateView's problem. Your program can create child records by QuerySet or Model method.

### 3. Multi-column lookup avairable

To support composite primary keys, CPkQuery supports multi-column lookups.

```python
obj = CompanyBranch.objects.get(pk=(1,'JP'))
qs = CompanyBranch.objects.filter(pk='1,JP')
qs = CompanyBranch.objects.filter(**{'company,country_code':(1,'JP')})
qs = CompanyBranch.objects.filter(**{'company_id,country_code':'1,JP'})
```

LHS with comma is not just primary, also other columns are OK.

```python
qs = CompanyBranch.objects.filter(**{'country_code,name':'JP,Google'})
```

Lookup Multi-Column with 'in' is also avairable. PostgreSQL is fine, But SQLite3 is not supported.

```python
qs = CompanyBranch.objects.filter(pk__in=[(1,'JP'),(1,'US'),(2,'JP'),])
qs = CompanyBranch.objects.filter(**{'country_code,name__in':[('JP','HONDA'),('CN','SONY'),]})
```

### 4. bulk_update avairable (v1.0.2)

bulk_update methond avairable for PostgreSQL. But SQLite3 is not supported.

```python
   Album.objects.bulk_update(albums, ['num_stars',])
```

## Limitations

### 1. Migration(Create table)
Migration will fail because "primary_key=True" to multi-column unless "managed = False". 
Legacy tables already exisit, or have to be created by hand.
Otherwise, comment out "primary_key=True" and "managed=False" while migration.

### 2. Create in Admin(CreateView's problem)
CreateView do unique check to each key Field. So you can't add enough child records. But, this is only CreateView's problem. Your program can create child records by QuerySet or Model method.

### 3. ForeignKey
Need to make CPkForeignKey to support relations to GrandChild model.

### 4. Multi-column IN query not available for SQLite
Django model doesn't support multi-column "IN" query for SQLite at present.

### 5. Create is better than Save for INSERT
For INSERT, you'd better use CPKQuerySet.create rather than CPKModel.save. 
Because Model.save will try to UPDATE first if key value is set. Another way to avoid this, you can use option force_insert=True.

```python
CompanyBranch.objects.create(**params)

 or 
 
obj = CompanyBranch(**params)
obj.save(force_insert=True)
```

## Installation

pip install django-compositepk-model

[![Downloads](https://static.pepy.tech/badge/django-compositepk-model)](https://pepy.tech/project/django-compositepk-model)

## Links

https://code.djangoproject.com/ticket/373  
https://code.djangoproject.com/wiki/MultipleColumnPrimaryKeys  
https://gijutsu.com/en/2021/01/19/django-composite-primary-key/  
https://gijutsu.com/en/2021/03/16/django-ticket373/  

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "django-compositepk-model",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.6",
    "maintainer_email": null,
    "keywords": "Multi-Column Primary Key, composite primary keys, django, django-admin, model",
    "author": null,
    "author_email": "Arisophy <arisophy@is-jpn.com>",
    "download_url": "https://files.pythonhosted.org/packages/d9/c3/8e40200ed12166bc1934217703868b8de94e2c1b1a1879962ad7d5f0dd70/django_compositepk_model-1.0.3.tar.gz",
    "platform": null,
    "description": "# django-compositepk-model\n\n[\u65e5\u672c\u8a9e](https://gijutsu.com/2021/06/06/djangodjango-compositepk-model/#cpkmodel)\n \nProvide an extended Django Model class named 'CPkModel' that supports composite primary keys. Also provide an extended Query class 'CPkQuery' that supports multi-column lookups.\n\nThis package supports treating legacy db tables with a composite primary key, without adding a surrogate key.\n\nThis is my other approach to [ticket373](https://code.djangoproject.com/ticket/373).\n\n## Features\n\n### 1. Easy to use\n\nFor a table with a composite primary key, change the base class from Model to CPkModel, and set 'unique_together' in Meta. In addition, set 'primary_key=True' to each primary keys.\n\n(model definition sample)\n\n```python\nfrom django.db import models\nfrom cpkmodel import CPkModel\n\n# Normal Model\n#   primary_key is auto 'id'\nclass Company(models.Model):\n    name = models.CharField(max_length=100)\n    established_date = models.DateField()\n    company_code = models.CharField(max_length=100)\n\n    class Meta:\n        db_table = 'Company'\n\n# Child Model (CpkModel)\n#   composite primary key: company_id, country_code\nclass CompanyBranch(CPkModel):\n    company = models.ForeignKey(\n        Company,\n        primary_key=True,       # for CompositePK\n        on_delete=models.CASCADE,\n    )\n    country_code = models.CharField(\n        max_length=100,\n        primary_key=True,       # for CompositePK\n    )\n    name = models.CharField(max_length=100)\n    established_date = models.DateField()\n\n    class Meta:\n        managed = False  # for CompositePK *1\n        db_table = 'CompanyBranch'\n        unique_together = (('company', 'country_code'),)  # for CompositePK\n```\n\nThat's all. No additional definitions or virtual fields are required.\n\n*1: \"Migration\" will fail because \"primary_key=True\" to multi-column unless \"managed = False\". \n    Legacy tables already exisit, or have to be created by hand.\n    Or, comment out \"primary_key=True\" and \"managed=False\" while migration.\n    \n### 2. Admin avairable\n\nCPkModel can be used in Django Admin. The values of composite primary key are displayed in a comma separated style. Change(Update), Delete are fine. Add(Create) has a problem that CreateView do unique check to each key Field. So you can't add enough child records. But, this is only CreateView's problem. Your program can create child records by QuerySet or Model method.\n\n### 3. Multi-column lookup avairable\n\nTo support composite primary keys, CPkQuery supports multi-column lookups.\n\n```python\nobj = CompanyBranch.objects.get(pk=(1,'JP'))\nqs = CompanyBranch.objects.filter(pk='1,JP')\nqs = CompanyBranch.objects.filter(**{'company,country_code':(1,'JP')})\nqs = CompanyBranch.objects.filter(**{'company_id,country_code':'1,JP'})\n```\n\nLHS with comma is not just primary, also other columns are OK.\n\n```python\nqs = CompanyBranch.objects.filter(**{'country_code,name':'JP,Google'})\n```\n\nLookup Multi-Column with 'in' is also avairable. PostgreSQL is fine, But SQLite3 is not supported.\n\n```python\nqs = CompanyBranch.objects.filter(pk__in=[(1,'JP'),(1,'US'),(2,'JP'),])\nqs = CompanyBranch.objects.filter(**{'country_code,name__in':[('JP','HONDA'),('CN','SONY'),]})\n```\n\n### 4. bulk_update avairable (v1.0.2)\n\nbulk_update methond avairable for PostgreSQL. But SQLite3 is not supported.\n\n```python\n   Album.objects.bulk_update(albums, ['num_stars',])\n```\n\n## Limitations\n\n### 1. Migration(Create table)\nMigration will fail because \"primary_key=True\" to multi-column unless \"managed = False\". \nLegacy tables already exisit, or have to be created by hand.\nOtherwise, comment out \"primary_key=True\" and \"managed=False\" while migration.\n\n### 2. Create in Admin(CreateView's problem)\nCreateView do unique check to each key Field. So you can't add enough child records. But, this is only CreateView's problem. Your program can create child records by QuerySet or Model method.\n\n### 3. ForeignKey\nNeed to make CPkForeignKey to support relations to GrandChild model.\n\n### 4. Multi-column IN query not available for SQLite\nDjango model doesn't support multi-column \"IN\" query for SQLite at present.\n\n### 5. Create is better than Save for INSERT\nFor INSERT, you'd better use CPKQuerySet.create rather than CPKModel.save. \nBecause Model.save will try to UPDATE first if key value is set. Another way to avoid this, you can use option force_insert=True.\n\n```python\nCompanyBranch.objects.create(**params)\n\n or \n \nobj = CompanyBranch(**params)\nobj.save(force_insert=True)\n```\n\n## Installation\n\npip install django-compositepk-model\n\n[![Downloads](https://static.pepy.tech/badge/django-compositepk-model)](https://pepy.tech/project/django-compositepk-model)\n\n## Links\n\nhttps://code.djangoproject.com/ticket/373  \nhttps://code.djangoproject.com/wiki/MultipleColumnPrimaryKeys  \nhttps://gijutsu.com/en/2021/01/19/django-composite-primary-key/  \nhttps://gijutsu.com/en/2021/03/16/django-ticket373/  \n",
    "bugtrack_url": null,
    "license": "MIT License",
    "summary": "Extended Django Model class with composite-primary-key support",
    "version": "1.0.3",
    "project_urls": {
        "Homepage": "https://github.com/Arisophy/django-compositepk-model",
        "Issues": "https://github.com/Arisophy/django-compositepk-model/issues",
        "Repository": "https://github.com/Arisophy/django-compositepk-model.git"
    },
    "split_keywords": [
        "multi-column primary key",
        " composite primary keys",
        " django",
        " django-admin",
        " model"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "28defe2597dcacd3981f3b885d7771f7057072c425a5c574ebaa1f6b15c754a4",
                "md5": "4f8f2cd22b67cb4462a52fe1ec515182",
                "sha256": "347f68eef2d7d34c2885cfd1642d6e5b036d7dd39f40bacd3eb961ec564edf88"
            },
            "downloads": -1,
            "filename": "django_compositepk_model-1.0.3-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "4f8f2cd22b67cb4462a52fe1ec515182",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.6",
            "size": 9331,
            "upload_time": "2024-05-23T03:18:06",
            "upload_time_iso_8601": "2024-05-23T03:18:06.015960Z",
            "url": "https://files.pythonhosted.org/packages/28/de/fe2597dcacd3981f3b885d7771f7057072c425a5c574ebaa1f6b15c754a4/django_compositepk_model-1.0.3-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "d9c38e40200ed12166bc1934217703868b8de94e2c1b1a1879962ad7d5f0dd70",
                "md5": "bdfff3c12917d83bb8cb374a6a8935cd",
                "sha256": "69c45a6b306da97f8caa6b19e8191fed4ed9ae800d4edcff7381bbae432454b0"
            },
            "downloads": -1,
            "filename": "django_compositepk_model-1.0.3.tar.gz",
            "has_sig": false,
            "md5_digest": "bdfff3c12917d83bb8cb374a6a8935cd",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.6",
            "size": 10361,
            "upload_time": "2024-05-23T03:18:07",
            "upload_time_iso_8601": "2024-05-23T03:18:07.567840Z",
            "url": "https://files.pythonhosted.org/packages/d9/c3/8e40200ed12166bc1934217703868b8de94e2c1b1a1879962ad7d5f0dd70/django_compositepk_model-1.0.3.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-05-23 03:18:07",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "Arisophy",
    "github_project": "django-compositepk-model",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "django-compositepk-model"
}
        
Elapsed time: 0.27299s