edc-lab-results


Nameedc-lab-results JSON
Version 0.3.15 PyPI version JSON
download
home_pagehttps://github.com/clinicedc/edc-lab-results
SummarySimple blood result data collection format model classes for clinicedc/edc projects
upload_time2024-11-20 22:44:52
maintainerNone
docs_urlNone
authorErik van Widenfelt
requires_python>=3.12
licenseGPL license, see LICENSE
keywords django laboratory data collection clinicedc clinical trials
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage
            |pypi| |actions| |codecov| |downloads|

edc-lab-results
---------------

Simple blood result data collection format for django models

In this design
    * a specimen requisition for a panel is completed first (SubjectRequisition)
    * result is received and entered into a result form
    * if a result is admnormal or gradable, an ActionItem is created.

Building the Model
==================

Below we create a model class with ``BloodResultsModelMixin``. On the class we specify the ``lab_panel`` and limit the FK the requisitions of this panel using ``limit_choices_to``.

.. code-block:: python

    # models.py

    from edc_lab.model_mixins import CrfWithRequisitionModelMixin, requisition_fk_options
    from edc_lab_panels.panels import chemistry_panel

    class BloodResultsFbc(
        CrfWithRequisitionModelMixin,
        BloodResultsModelMixin,
        BaseUuidModel,
    ):

        lab_panel = fbc_panel

        requisition = models.ForeignKey(
            limit_choices_to={"panel__name": fbc_panel.name}, **requisition_fk_options
        )

        class Meta(CrfWithActionModelMixin.Meta, BaseUuidModel.Meta):
            verbose_name = "Blood Result: FBC"
            verbose_name_plural = "Blood Results: FBC"

The above example has no fields for results, so let's add some model mixins, one for each result item.

.. code-block:: python

    # models.py

    class BloodResultsFbc(
        CrfWithRequisitionModelMixin,
        HaemoglobinModelMixin,
        HctModelMixin,
        RbcModelMixin,
        WbcModelMixin,
        PlateletsModelMixin,
        MchModelMixin,
        MchcModelMixin,
        McvModelMixin,
        BloodResultsModelMixin,
        CrfStatusModelMixin,
        BaseUuidModel,
    ):

        lab_panel = fbc_panel

        requisition = models.ForeignKey(
            limit_choices_to={"panel__name": fbc_panel.name}, **requisition_fk_options
        )

        class Meta(CrfWithActionModelMixin.Meta, BaseUuidModel.Meta):
            verbose_name = "Blood Result: FBC"
            verbose_name_plural = "Blood Results: FBC"

If an ``ActionItem`` is to be created because of an abnormal or reportable result item, add the ActionItem.

.. code-block:: python

    # models.py

    class BloodResultsFbc(
        CrfWithActionModelMixin,
        CrfWithRequisitionModelMixin,
        HaemoglobinModelMixin,
        HctModelMixin,
        RbcModelMixin,
        WbcModelMixin,
        PlateletsModelMixin,
        MchModelMixin,
        MchcModelMixin,
        McvModelMixin,
        BloodResultsModelMixin,
        CrfStatusModelMixin,
        BaseUuidModel,
    ):
        action_name = BLOOD_RESULTS_FBC_ACTION

        lab_panel = fbc_panel

        requisition = models.ForeignKey(
            limit_choices_to={"panel__name": fbc_panel.name}, **requisition_fk_options
        )

        class Meta(CrfWithActionModelMixin.Meta, BaseUuidModel.Meta):
            verbose_name = "Blood Result: FBC"
            verbose_name_plural = "Blood Results: FBC"

Building the ModeForm class
===========================
The ModelForm class just needs the Model class and the panel. In this case ``BloodResultsFbc`` and ``fbc_panel``.

.. code-block:: python

    # forms.py

    class BloodResultsFbcFormValidator(BloodResultsFormValidatorMixin, CrfFormValidator):
        panel = fbc_panel


    class BloodResultsFbcForm(ActionItemCrfFormMixin, CrfModelFormMixin, forms.ModelForm):
        form_validator_cls = BloodResultsFbcFormValidator

        class Meta(ActionItemCrfFormMixin.Meta):
            model = BloodResultsFbc
            fields = "__all__"


Building the ModelAdmin class
=============================

The ModelAdmin class needs the Model class, ModelForm class and the panel.

.. code-block:: python

    # admin.py

    @admin.register(BloodResultsFbc, site=intecomm_subject_admin)
    class BloodResultsFbcAdmin(BloodResultsModelAdminMixin, CrfModelAdmin):
        form = BloodResultsFbcForm
        fieldsets = BloodResultFieldset(
            BloodResultsFbc.lab_panel,
            model_cls=BloodResultsFbc,
            extra_fieldsets=[(-1, action_fieldset_tuple)],
        ).fieldsets


The SubjectRequistion ModelAdmin class
======================================

When using ``autocomplete`` for the subject requsition FK on the result form ModelAdmin class, the subject requsition model admin class needs to filter the search results passed to the autocomplete control.

If all result models are prefixed with "bloodresult", you can filter on the path name like this:

.. code-block:: python

    # admin.py

    @admin.register(SubjectRequisition, site=intecomm_subject_admin)
    class SubjectRequisitionAdmin(RequisitionAdminMixin, CrfModelAdmin):
        form = SubjectRequisitionForm

        # ...

        def get_search_results(self, request, queryset, search_term):
            queryset, use_distinct = super().get_search_results(request, queryset, search_term)
            path = urlsplit(request.META.get("HTTP_REFERER")).path
            query = urlsplit(request.META.get("HTTP_REFERER")).query
            if "bloodresult" in str(path):
                attrs = parse_qs(str(query))
                try:
                    subject_visit = attrs.get("subject_visit")[0]
                except (TypeError, IndexError):
                    pass
                else:
                    queryset = queryset.filter(subject_visit=subject_visit, is_drawn=YES)
            return queryset, use_distinct




.. |pypi| image:: https://img.shields.io/pypi/v/edc-lab-results.svg
    :target: https://pypi.python.org/pypi/edc-lab-results

.. |actions| image:: https://github.com/clinicedc/edc-lab-results/actions/workflows/build.yml/badge.svg
  :target: https://github.com/clinicedc/edc-lab-results/actions/workflows/build.yml

.. |codecov| image:: https://codecov.io/gh/clinicedc/edc-lab-results/branch/develop/graph/badge.svg
  :target: https://codecov.io/gh/clinicedc/edc-lab-results

.. |downloads| image:: https://pepy.tech/badge/edc-lab-results
   :target: https://pepy.tech/project/edc-lab-results

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/clinicedc/edc-lab-results",
    "name": "edc-lab-results",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.12",
    "maintainer_email": null,
    "keywords": "django laboratory data collection, clinicedc, clinical trials",
    "author": "Erik van Widenfelt",
    "author_email": "ew2789@gmail.com",
    "download_url": "https://files.pythonhosted.org/packages/66/be/3e411014051709b1969c9cd183112bf72cbd39e303b58ca28eb6261922df/edc_lab_results-0.3.15.tar.gz",
    "platform": null,
    "description": "|pypi| |actions| |codecov| |downloads|\n\nedc-lab-results\n---------------\n\nSimple blood result data collection format for django models\n\nIn this design\n    * a specimen requisition for a panel is completed first (SubjectRequisition)\n    * result is received and entered into a result form\n    * if a result is admnormal or gradable, an ActionItem is created.\n\nBuilding the Model\n==================\n\nBelow we create a model class with ``BloodResultsModelMixin``. On the class we specify the ``lab_panel`` and limit the FK the requisitions of this panel using ``limit_choices_to``.\n\n.. code-block:: python\n\n    # models.py\n\n    from edc_lab.model_mixins import CrfWithRequisitionModelMixin, requisition_fk_options\n    from edc_lab_panels.panels import chemistry_panel\n\n    class BloodResultsFbc(\n        CrfWithRequisitionModelMixin,\n        BloodResultsModelMixin,\n        BaseUuidModel,\n    ):\n\n        lab_panel = fbc_panel\n\n        requisition = models.ForeignKey(\n            limit_choices_to={\"panel__name\": fbc_panel.name}, **requisition_fk_options\n        )\n\n        class Meta(CrfWithActionModelMixin.Meta, BaseUuidModel.Meta):\n            verbose_name = \"Blood Result: FBC\"\n            verbose_name_plural = \"Blood Results: FBC\"\n\nThe above example has no fields for results, so let's add some model mixins, one for each result item.\n\n.. code-block:: python\n\n    # models.py\n\n    class BloodResultsFbc(\n        CrfWithRequisitionModelMixin,\n        HaemoglobinModelMixin,\n        HctModelMixin,\n        RbcModelMixin,\n        WbcModelMixin,\n        PlateletsModelMixin,\n        MchModelMixin,\n        MchcModelMixin,\n        McvModelMixin,\n        BloodResultsModelMixin,\n        CrfStatusModelMixin,\n        BaseUuidModel,\n    ):\n\n        lab_panel = fbc_panel\n\n        requisition = models.ForeignKey(\n            limit_choices_to={\"panel__name\": fbc_panel.name}, **requisition_fk_options\n        )\n\n        class Meta(CrfWithActionModelMixin.Meta, BaseUuidModel.Meta):\n            verbose_name = \"Blood Result: FBC\"\n            verbose_name_plural = \"Blood Results: FBC\"\n\nIf an ``ActionItem`` is to be created because of an abnormal or reportable result item, add the ActionItem.\n\n.. code-block:: python\n\n    # models.py\n\n    class BloodResultsFbc(\n        CrfWithActionModelMixin,\n        CrfWithRequisitionModelMixin,\n        HaemoglobinModelMixin,\n        HctModelMixin,\n        RbcModelMixin,\n        WbcModelMixin,\n        PlateletsModelMixin,\n        MchModelMixin,\n        MchcModelMixin,\n        McvModelMixin,\n        BloodResultsModelMixin,\n        CrfStatusModelMixin,\n        BaseUuidModel,\n    ):\n        action_name = BLOOD_RESULTS_FBC_ACTION\n\n        lab_panel = fbc_panel\n\n        requisition = models.ForeignKey(\n            limit_choices_to={\"panel__name\": fbc_panel.name}, **requisition_fk_options\n        )\n\n        class Meta(CrfWithActionModelMixin.Meta, BaseUuidModel.Meta):\n            verbose_name = \"Blood Result: FBC\"\n            verbose_name_plural = \"Blood Results: FBC\"\n\nBuilding the ModeForm class\n===========================\nThe ModelForm class just needs the Model class and the panel. In this case ``BloodResultsFbc`` and ``fbc_panel``.\n\n.. code-block:: python\n\n    # forms.py\n\n    class BloodResultsFbcFormValidator(BloodResultsFormValidatorMixin, CrfFormValidator):\n        panel = fbc_panel\n\n\n    class BloodResultsFbcForm(ActionItemCrfFormMixin, CrfModelFormMixin, forms.ModelForm):\n        form_validator_cls = BloodResultsFbcFormValidator\n\n        class Meta(ActionItemCrfFormMixin.Meta):\n            model = BloodResultsFbc\n            fields = \"__all__\"\n\n\nBuilding the ModelAdmin class\n=============================\n\nThe ModelAdmin class needs the Model class, ModelForm class and the panel.\n\n.. code-block:: python\n\n    # admin.py\n\n    @admin.register(BloodResultsFbc, site=intecomm_subject_admin)\n    class BloodResultsFbcAdmin(BloodResultsModelAdminMixin, CrfModelAdmin):\n        form = BloodResultsFbcForm\n        fieldsets = BloodResultFieldset(\n            BloodResultsFbc.lab_panel,\n            model_cls=BloodResultsFbc,\n            extra_fieldsets=[(-1, action_fieldset_tuple)],\n        ).fieldsets\n\n\nThe SubjectRequistion ModelAdmin class\n======================================\n\nWhen using ``autocomplete`` for the subject requsition FK on the result form ModelAdmin class, the subject requsition model admin class needs to filter the search results passed to the autocomplete control.\n\nIf all result models are prefixed with \"bloodresult\", you can filter on the path name like this:\n\n.. code-block:: python\n\n    # admin.py\n\n    @admin.register(SubjectRequisition, site=intecomm_subject_admin)\n    class SubjectRequisitionAdmin(RequisitionAdminMixin, CrfModelAdmin):\n        form = SubjectRequisitionForm\n\n        # ...\n\n        def get_search_results(self, request, queryset, search_term):\n            queryset, use_distinct = super().get_search_results(request, queryset, search_term)\n            path = urlsplit(request.META.get(\"HTTP_REFERER\")).path\n            query = urlsplit(request.META.get(\"HTTP_REFERER\")).query\n            if \"bloodresult\" in str(path):\n                attrs = parse_qs(str(query))\n                try:\n                    subject_visit = attrs.get(\"subject_visit\")[0]\n                except (TypeError, IndexError):\n                    pass\n                else:\n                    queryset = queryset.filter(subject_visit=subject_visit, is_drawn=YES)\n            return queryset, use_distinct\n\n\n\n\n.. |pypi| image:: https://img.shields.io/pypi/v/edc-lab-results.svg\n    :target: https://pypi.python.org/pypi/edc-lab-results\n\n.. |actions| image:: https://github.com/clinicedc/edc-lab-results/actions/workflows/build.yml/badge.svg\n  :target: https://github.com/clinicedc/edc-lab-results/actions/workflows/build.yml\n\n.. |codecov| image:: https://codecov.io/gh/clinicedc/edc-lab-results/branch/develop/graph/badge.svg\n  :target: https://codecov.io/gh/clinicedc/edc-lab-results\n\n.. |downloads| image:: https://pepy.tech/badge/edc-lab-results\n   :target: https://pepy.tech/project/edc-lab-results\n",
    "bugtrack_url": null,
    "license": "GPL license, see LICENSE",
    "summary": "Simple blood result data collection format model classes for clinicedc/edc projects",
    "version": "0.3.15",
    "project_urls": {
        "Homepage": "https://github.com/clinicedc/edc-lab-results"
    },
    "split_keywords": [
        "django laboratory data collection",
        " clinicedc",
        " clinical trials"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "f51edfb493e553e5c98c839dd4263cdd8a7e14b76c6bfbe49fb2957b398ee8db",
                "md5": "4bcfda012f872ac4af6a8e387fdc614c",
                "sha256": "f9a766b3be9df2f307d7b94a314693b2af3ce1bcb885b121c64062988a00932a"
            },
            "downloads": -1,
            "filename": "edc_lab_results-0.3.15-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "4bcfda012f872ac4af6a8e387fdc614c",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.12",
            "size": 47404,
            "upload_time": "2024-11-20T22:44:50",
            "upload_time_iso_8601": "2024-11-20T22:44:50.199801Z",
            "url": "https://files.pythonhosted.org/packages/f5/1e/dfb493e553e5c98c839dd4263cdd8a7e14b76c6bfbe49fb2957b398ee8db/edc_lab_results-0.3.15-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "66be3e411014051709b1969c9cd183112bf72cbd39e303b58ca28eb6261922df",
                "md5": "7e844c8635a21619b7056f4167bd310e",
                "sha256": "bb07e491b286d77b1190bcc6bde544a7977c7ade23258d591ccc2f3cea540167"
            },
            "downloads": -1,
            "filename": "edc_lab_results-0.3.15.tar.gz",
            "has_sig": false,
            "md5_digest": "7e844c8635a21619b7056f4167bd310e",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.12",
            "size": 40718,
            "upload_time": "2024-11-20T22:44:52",
            "upload_time_iso_8601": "2024-11-20T22:44:52.127156Z",
            "url": "https://files.pythonhosted.org/packages/66/be/3e411014051709b1969c9cd183112bf72cbd39e303b58ca28eb6261922df/edc_lab_results-0.3.15.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-11-20 22:44:52",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "clinicedc",
    "github_project": "edc-lab-results",
    "travis_ci": false,
    "coveralls": true,
    "github_actions": true,
    "lcname": "edc-lab-results"
}
        
Elapsed time: 0.44756s