codex 1.5.12__py3-none-any.whl → 1.5.13a0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of codex might be problematic. Click here for more details.
- codex/librarian/importer/importerd.py +2 -1
- codex/librarian/importer/query_fks.py +1 -2
- codex/middleware.py +50 -1
- codex/serializers/browser/settings.py +1 -0
- codex/serializers/choices.py +11 -13
- codex/serializers/metadata.py +1 -1
- codex/settings/settings.py +16 -5
- codex/signals/django_signals.py +6 -0
- codex/static_root/assets/{VCheckbox-CC74mhfV.a196e804e50a.js → VCheckbox-BMRDCYNv.7f791d7f065f.js} +1 -1
- codex/static_root/assets/VCheckbox-BMRDCYNv.7f791d7f065f.js.br +0 -0
- codex/static_root/assets/VCheckbox-BMRDCYNv.7f791d7f065f.js.gz +0 -0
- codex/static_root/assets/{VCheckbox-CC74mhfV.js → VCheckbox-BMRDCYNv.js} +1 -1
- codex/static_root/assets/VCheckbox-BMRDCYNv.js.br +0 -0
- codex/static_root/assets/VCheckbox-BMRDCYNv.js.gz +0 -0
- codex/static_root/assets/{VCheckboxBtn-F27UKlAX.f74083aa5b9a.js → VCheckboxBtn-Dqp1u3GT.e80f145994b6.js} +1 -1
- codex/static_root/assets/VCheckboxBtn-Dqp1u3GT.e80f145994b6.js.br +0 -0
- codex/static_root/assets/VCheckboxBtn-Dqp1u3GT.e80f145994b6.js.gz +0 -0
- codex/static_root/assets/{VCheckboxBtn-F27UKlAX.js → VCheckboxBtn-Dqp1u3GT.js} +1 -1
- codex/static_root/assets/VCheckboxBtn-Dqp1u3GT.js.br +0 -0
- codex/static_root/assets/VCheckboxBtn-Dqp1u3GT.js.gz +0 -0
- codex/static_root/assets/VCombobox-DT52mZm3.309c77be4a55.js +1 -0
- codex/static_root/assets/VCombobox-DT52mZm3.309c77be4a55.js.br +0 -0
- codex/static_root/assets/VCombobox-DT52mZm3.309c77be4a55.js.gz +0 -0
- codex/static_root/assets/VCombobox-DT52mZm3.js +1 -0
- codex/static_root/assets/VCombobox-DT52mZm3.js.br +0 -0
- codex/static_root/assets/VCombobox-DT52mZm3.js.gz +0 -0
- codex/static_root/assets/{VDataTableVirtual-BgFOSn9_.969c17b4d50a.js → VDataTableVirtual-DhhCmPtf.0735a1ab4c2f.js} +1 -1
- codex/static_root/assets/VDataTableVirtual-DhhCmPtf.0735a1ab4c2f.js.br +0 -0
- codex/static_root/assets/VDataTableVirtual-DhhCmPtf.0735a1ab4c2f.js.gz +0 -0
- codex/static_root/assets/{VDataTableVirtual-BgFOSn9_.js → VDataTableVirtual-DhhCmPtf.js} +1 -1
- codex/static_root/assets/VDataTableVirtual-DhhCmPtf.js.br +0 -0
- codex/static_root/assets/VDataTableVirtual-DhhCmPtf.js.gz +0 -0
- codex/static_root/assets/{VExpansionPanel-B06inlZY.a77a3ad1cc7c.js → VExpansionPanel-C593uXqT.d3bdc6a21208.js} +1 -1
- codex/static_root/assets/VExpansionPanel-C593uXqT.d3bdc6a21208.js.br +0 -0
- codex/static_root/assets/VExpansionPanel-C593uXqT.d3bdc6a21208.js.gz +0 -0
- codex/static_root/assets/{VExpansionPanel-B06inlZY.js → VExpansionPanel-C593uXqT.js} +1 -1
- codex/static_root/assets/VExpansionPanel-C593uXqT.js.br +0 -0
- codex/static_root/assets/VExpansionPanel-C593uXqT.js.gz +0 -0
- codex/static_root/assets/{VMain-BR4DrMy3.977234e0db6a.js → VMain-DmQvRj_k.1e0480bed9a6.js} +1 -1
- codex/static_root/assets/VMain-DmQvRj_k.1e0480bed9a6.js.br +0 -0
- codex/static_root/assets/VMain-DmQvRj_k.1e0480bed9a6.js.gz +0 -0
- codex/static_root/assets/{VMain-BR4DrMy3.js → VMain-DmQvRj_k.js} +1 -1
- codex/static_root/assets/VMain-DmQvRj_k.js.br +0 -0
- codex/static_root/assets/VMain-DmQvRj_k.js.gz +0 -0
- codex/static_root/assets/{VRadioGroup-DE0KmC8d.75bdb9d16a32.js → VRadioGroup-Bi16yPEE.69086b77f9b1.js} +1 -1
- codex/static_root/assets/VRadioGroup-Bi16yPEE.69086b77f9b1.js.br +0 -0
- codex/static_root/assets/VRadioGroup-Bi16yPEE.69086b77f9b1.js.gz +0 -0
- codex/static_root/assets/{VRadioGroup-DE0KmC8d.js → VRadioGroup-Bi16yPEE.js} +1 -1
- codex/static_root/assets/VRadioGroup-Bi16yPEE.js.br +0 -0
- codex/static_root/assets/VRadioGroup-Bi16yPEE.js.gz +0 -0
- codex/static_root/assets/VSelect-BdaijxdJ.b969ab260593.js +1 -0
- codex/static_root/assets/VSelect-BdaijxdJ.b969ab260593.js.br +0 -0
- codex/static_root/assets/VSelect-BdaijxdJ.b969ab260593.js.gz +0 -0
- codex/static_root/assets/VSelect-BdaijxdJ.js +1 -0
- codex/static_root/assets/VSelect-BdaijxdJ.js.br +0 -0
- codex/static_root/assets/VSelect-BdaijxdJ.js.gz +0 -0
- codex/static_root/assets/{VSelectionControl-B1zPb_Yg.6112179d7a5d.js → VSelectionControl-CuM4okF6.0f246e35e86f.js} +1 -1
- codex/static_root/assets/VSelectionControl-CuM4okF6.0f246e35e86f.js.br +0 -0
- codex/static_root/assets/VSelectionControl-CuM4okF6.0f246e35e86f.js.gz +0 -0
- codex/static_root/assets/{VSelectionControl-B1zPb_Yg.js → VSelectionControl-CuM4okF6.js} +1 -1
- codex/static_root/assets/VSelectionControl-CuM4okF6.js.br +0 -0
- codex/static_root/assets/VSelectionControl-CuM4okF6.js.gz +0 -0
- codex/static_root/assets/VSlideGroup-ztBraz6g.02a0bc55b207.js +1 -0
- codex/static_root/assets/VSlideGroup-ztBraz6g.02a0bc55b207.js.br +0 -0
- codex/static_root/assets/VSlideGroup-ztBraz6g.02a0bc55b207.js.gz +0 -0
- codex/static_root/assets/VSlideGroup-ztBraz6g.js +1 -0
- codex/static_root/assets/VSlideGroup-ztBraz6g.js.br +0 -0
- codex/static_root/assets/VSlideGroup-ztBraz6g.js.gz +0 -0
- codex/static_root/assets/{VTable-Pq4fCfUx.e50f8ad539ed.js → VTable-CGuSv-Tv.eddaf5526d93.js} +1 -1
- codex/static_root/assets/VTable-CGuSv-Tv.eddaf5526d93.js.br +0 -0
- codex/static_root/assets/VTable-CGuSv-Tv.eddaf5526d93.js.gz +0 -0
- codex/static_root/assets/{VTable-Pq4fCfUx.js → VTable-CGuSv-Tv.js} +1 -1
- codex/static_root/assets/VTable-CGuSv-Tv.js.br +0 -0
- codex/static_root/assets/VTable-CGuSv-Tv.js.gz +0 -0
- codex/static_root/assets/{VToolbar-BFYiqJrS.js → VToolbar-CAUhD2BO.279f0b52347a.js} +2 -2
- codex/static_root/assets/VToolbar-CAUhD2BO.279f0b52347a.js.br +0 -0
- codex/static_root/assets/VToolbar-CAUhD2BO.279f0b52347a.js.gz +0 -0
- codex/static_root/assets/{VToolbar-BFYiqJrS.71a0cbf7eb5f.js → VToolbar-CAUhD2BO.js} +2 -2
- codex/static_root/assets/VToolbar-CAUhD2BO.js.br +0 -0
- codex/static_root/assets/VToolbar-CAUhD2BO.js.gz +0 -0
- codex/static_root/assets/{VToolbar-BfNszTMd.css → VToolbar-DqQLg1UA.614d6a4a8a09.css} +1 -1
- codex/static_root/assets/VToolbar-DqQLg1UA.614d6a4a8a09.css.br +0 -0
- codex/static_root/assets/{VToolbar-BfNszTMd.111f25cdd6d8.css.gz → VToolbar-DqQLg1UA.614d6a4a8a09.css.gz} +0 -0
- codex/static_root/assets/{VToolbar-BfNszTMd.111f25cdd6d8.css → VToolbar-DqQLg1UA.css} +1 -1
- codex/static_root/assets/VToolbar-DqQLg1UA.css.br +0 -0
- codex/static_root/assets/{VToolbar-BfNszTMd.css.gz → VToolbar-DqQLg1UA.css.gz} +0 -0
- codex/static_root/assets/{VWindowItem-g6ho7Hf4.b91f9a3277ff.js → VWindowItem-YvmNwCNb.20a7e3b303de.js} +1 -1
- codex/static_root/assets/VWindowItem-YvmNwCNb.20a7e3b303de.js.br +0 -0
- codex/static_root/assets/VWindowItem-YvmNwCNb.20a7e3b303de.js.gz +0 -0
- codex/static_root/assets/{VWindowItem-g6ho7Hf4.js → VWindowItem-YvmNwCNb.js} +1 -1
- codex/static_root/assets/VWindowItem-YvmNwCNb.js.br +0 -0
- codex/static_root/assets/VWindowItem-YvmNwCNb.js.gz +0 -0
- codex/static_root/assets/{admin-BVkY78tW.affa20285127.js → admin-Ch9WezG1.bdace86b7c25.js} +1 -1
- codex/static_root/assets/admin-Ch9WezG1.bdace86b7c25.js.br +0 -0
- codex/static_root/assets/admin-Ch9WezG1.bdace86b7c25.js.gz +0 -0
- codex/static_root/assets/{admin-BVkY78tW.js → admin-Ch9WezG1.js} +1 -1
- codex/static_root/assets/admin-Ch9WezG1.js.br +0 -0
- codex/static_root/assets/admin-Ch9WezG1.js.gz +0 -0
- codex/static_root/assets/{admin-drawer-panel-CEiEnUcn.9f94b93a422f.js → admin-drawer-panel-B4VvGE4s.2265b9de60ab.js} +4 -4
- codex/static_root/assets/admin-drawer-panel-B4VvGE4s.2265b9de60ab.js.br +0 -0
- codex/static_root/assets/admin-drawer-panel-B4VvGE4s.2265b9de60ab.js.gz +0 -0
- codex/static_root/assets/{admin-drawer-panel-CEiEnUcn.js → admin-drawer-panel-B4VvGE4s.js} +4 -4
- codex/static_root/assets/admin-drawer-panel-B4VvGE4s.js.br +0 -0
- codex/static_root/assets/admin-drawer-panel-B4VvGE4s.js.gz +0 -0
- codex/static_root/assets/{admin-drawer-panel-s72VfDNy.css → admin-drawer-panel-Bk7z8uTR.1531b747003f.css} +1 -1
- codex/static_root/assets/admin-drawer-panel-Bk7z8uTR.1531b747003f.css.br +0 -0
- codex/static_root/assets/admin-drawer-panel-Bk7z8uTR.1531b747003f.css.gz +0 -0
- codex/static_root/assets/{admin-drawer-panel-s72VfDNy.ef6cb7221a44.css → admin-drawer-panel-Bk7z8uTR.css} +1 -1
- codex/static_root/assets/admin-drawer-panel-Bk7z8uTR.css.br +0 -0
- codex/static_root/assets/admin-drawer-panel-Bk7z8uTR.css.gz +0 -0
- codex/static_root/assets/browser-BTel3sYS.8e1515bc039a.js +1 -0
- codex/static_root/assets/browser-BTel3sYS.8e1515bc039a.js.br +0 -0
- codex/static_root/assets/browser-BTel3sYS.8e1515bc039a.js.gz +0 -0
- codex/static_root/assets/browser-BTel3sYS.js +1 -0
- codex/static_root/assets/browser-BTel3sYS.js.br +0 -0
- codex/static_root/assets/browser-BTel3sYS.js.gz +0 -0
- codex/static_root/assets/{browser-2i0QA4La.587673ac534c.css → browser-CVvV08AM.7667051b18fa.css} +1 -1
- codex/static_root/assets/browser-CVvV08AM.7667051b18fa.css.br +0 -0
- codex/static_root/assets/browser-CVvV08AM.7667051b18fa.css.gz +0 -0
- codex/static_root/assets/{browser-2i0QA4La.css → browser-CVvV08AM.css} +1 -1
- codex/static_root/assets/browser-CVvV08AM.css.br +0 -0
- codex/static_root/assets/browser-CVvV08AM.css.gz +0 -0
- codex/static_root/assets/{change-password-dialog-Bh7raeqK.6d408dcd933e.js → change-password-dialog-Dq6GjT1T.01b56b4b3e87.js} +1 -1
- codex/static_root/assets/change-password-dialog-Dq6GjT1T.01b56b4b3e87.js.br +0 -0
- codex/static_root/assets/change-password-dialog-Dq6GjT1T.01b56b4b3e87.js.gz +0 -0
- codex/static_root/assets/{change-password-dialog-Bh7raeqK.js → change-password-dialog-Dq6GjT1T.js} +1 -1
- codex/static_root/assets/change-password-dialog-Dq6GjT1T.js.br +0 -0
- codex/static_root/assets/change-password-dialog-Dq6GjT1T.js.gz +0 -0
- codex/static_root/assets/{confirm-dialog-CvURjaTY.cadecd4cefa8.js → confirm-dialog-D-Fx-51m.54b7d1059106.js} +1 -1
- codex/static_root/assets/confirm-dialog-D-Fx-51m.54b7d1059106.js.br +0 -0
- codex/static_root/assets/confirm-dialog-D-Fx-51m.54b7d1059106.js.gz +0 -0
- codex/static_root/assets/{confirm-dialog-CvURjaTY.js → confirm-dialog-D-Fx-51m.js} +1 -1
- codex/static_root/assets/confirm-dialog-D-Fx-51m.js.br +0 -0
- codex/static_root/assets/confirm-dialog-D-Fx-51m.js.gz +0 -0
- codex/static_root/assets/{confirm-footer-C-VAfuKA.js → confirm-footer-Yn7T9Tns.75a17cd86ca9.js} +1 -1
- codex/static_root/assets/confirm-footer-Yn7T9Tns.75a17cd86ca9.js.br +0 -0
- codex/static_root/assets/confirm-footer-Yn7T9Tns.75a17cd86ca9.js.gz +0 -0
- codex/static_root/assets/{confirm-footer-C-VAfuKA.c93e5c6d41ca.js → confirm-footer-Yn7T9Tns.js} +1 -1
- codex/static_root/assets/confirm-footer-Yn7T9Tns.js.br +0 -0
- codex/static_root/assets/confirm-footer-Yn7T9Tns.js.gz +0 -0
- codex/static_root/assets/{datetime-column-CDcOr8sM.951343a94a28.js → datetime-column-DCeBthsr.22ed49a999cc.js} +1 -1
- codex/static_root/assets/datetime-column-DCeBthsr.22ed49a999cc.js.br +0 -0
- codex/static_root/assets/datetime-column-DCeBthsr.22ed49a999cc.js.gz +0 -0
- codex/static_root/assets/{datetime-column-CDcOr8sM.js → datetime-column-DCeBthsr.js} +1 -1
- codex/static_root/assets/datetime-column-DCeBthsr.js.br +0 -0
- codex/static_root/assets/datetime-column-DCeBthsr.js.gz +0 -0
- codex/static_root/assets/{filter-DT8MlNGw.c70bb7a7c265.js → filter-Dw0fjwZi.4d5f085435ab.js} +1 -1
- codex/static_root/assets/filter-Dw0fjwZi.4d5f085435ab.js.br +0 -0
- codex/static_root/assets/filter-Dw0fjwZi.4d5f085435ab.js.gz +0 -0
- codex/static_root/assets/{filter-DT8MlNGw.js → filter-Dw0fjwZi.js} +1 -1
- codex/static_root/assets/filter-Dw0fjwZi.js.br +0 -0
- codex/static_root/assets/filter-Dw0fjwZi.js.gz +0 -0
- codex/static_root/assets/{flag-tab-BVoz2gvN.591572581c12.js → flag-tab-D5RcLFbQ.1073708ea164.js} +1 -1
- codex/static_root/assets/flag-tab-D5RcLFbQ.1073708ea164.js.br +0 -0
- codex/static_root/assets/flag-tab-D5RcLFbQ.1073708ea164.js.gz +0 -0
- codex/static_root/assets/{flag-tab-BVoz2gvN.js → flag-tab-D5RcLFbQ.js} +1 -1
- codex/static_root/assets/flag-tab-D5RcLFbQ.js.br +0 -0
- codex/static_root/assets/flag-tab-D5RcLFbQ.js.gz +0 -0
- codex/static_root/assets/{group-tab-Bu1Hn4DR.8c9fb2cbc4d2.js → group-tab-BilDDNz5.cba5ca15d7cf.js} +1 -1
- codex/static_root/assets/group-tab-BilDDNz5.cba5ca15d7cf.js.br +0 -0
- codex/static_root/assets/group-tab-BilDDNz5.cba5ca15d7cf.js.gz +0 -0
- codex/static_root/assets/{group-tab-Bu1Hn4DR.js → group-tab-BilDDNz5.js} +1 -1
- codex/static_root/assets/group-tab-BilDDNz5.js.br +0 -0
- codex/static_root/assets/group-tab-BilDDNz5.js.gz +0 -0
- codex/static_root/assets/{http-error-BKXUvS3w.93b39ceed2f7.js → http-error-DHmC7qgT.bde1d32b55df.js} +1 -1
- codex/static_root/assets/http-error-DHmC7qgT.bde1d32b55df.js.br +0 -0
- codex/static_root/assets/http-error-DHmC7qgT.bde1d32b55df.js.gz +0 -0
- codex/static_root/assets/{http-error-BKXUvS3w.js → http-error-DHmC7qgT.js} +1 -1
- codex/static_root/assets/http-error-DHmC7qgT.js.br +0 -0
- codex/static_root/assets/http-error-DHmC7qgT.js.gz +0 -0
- codex/static_root/assets/{library-tab-AM2XWHOr.31f48701358e.js → library-tab-dbcbv0--.efa2d1d95b77.js} +1 -1
- codex/static_root/assets/library-tab-dbcbv0--.efa2d1d95b77.js.br +0 -0
- codex/static_root/assets/library-tab-dbcbv0--.efa2d1d95b77.js.gz +0 -0
- codex/static_root/assets/{library-tab-AM2XWHOr.js → library-tab-dbcbv0--.js} +1 -1
- codex/static_root/assets/library-tab-dbcbv0--.js.br +0 -0
- codex/static_root/assets/library-tab-dbcbv0--.js.gz +0 -0
- codex/static_root/assets/main-CCY5Ix0K.b067e1d16cf5.js +37 -0
- codex/static_root/assets/main-CCY5Ix0K.b067e1d16cf5.js.br +0 -0
- codex/static_root/assets/main-CCY5Ix0K.b067e1d16cf5.js.gz +0 -0
- codex/static_root/assets/main-CCY5Ix0K.js +37 -0
- codex/static_root/assets/main-CCY5Ix0K.js.br +0 -0
- codex/static_root/assets/main-CCY5Ix0K.js.gz +0 -0
- codex/static_root/assets/{metadata-dialog-BGJasBRy.0553851658b5.css → metadata-dialog-DIhQctD5.67830cc94cf8.css} +1 -1
- codex/static_root/assets/metadata-dialog-DIhQctD5.67830cc94cf8.css.br +0 -0
- codex/static_root/assets/metadata-dialog-DIhQctD5.67830cc94cf8.css.gz +0 -0
- codex/static_root/assets/{metadata-dialog-BGJasBRy.css → metadata-dialog-DIhQctD5.css} +1 -1
- codex/static_root/assets/metadata-dialog-DIhQctD5.css.br +0 -0
- codex/static_root/assets/metadata-dialog-DIhQctD5.css.gz +0 -0
- codex/static_root/assets/metadata-dialog-PkTw4uLp.ce5ee2377f27.js +1 -0
- codex/static_root/assets/metadata-dialog-PkTw4uLp.ce5ee2377f27.js.br +0 -0
- codex/static_root/assets/metadata-dialog-PkTw4uLp.ce5ee2377f27.js.gz +0 -0
- codex/static_root/assets/metadata-dialog-PkTw4uLp.js +1 -0
- codex/static_root/assets/metadata-dialog-PkTw4uLp.js.br +0 -0
- codex/static_root/assets/metadata-dialog-PkTw4uLp.js.gz +0 -0
- codex/static_root/assets/{pdf-doc-DSq1qfWx.50ab90d8b609.js → pdf-doc-CEOcuQZb.260e6671eb89.js} +1 -1
- codex/static_root/assets/pdf-doc-CEOcuQZb.260e6671eb89.js.br +0 -0
- codex/static_root/assets/pdf-doc-CEOcuQZb.260e6671eb89.js.gz +0 -0
- codex/static_root/assets/{pdf-doc-DSq1qfWx.js → pdf-doc-CEOcuQZb.js} +1 -1
- codex/static_root/assets/pdf-doc-CEOcuQZb.js.br +0 -0
- codex/static_root/assets/pdf-doc-CEOcuQZb.js.gz +0 -0
- codex/static_root/assets/{reader-Qan6W6n-.fc91835a9075.js → reader-DRsYPz-3.b8ee57f2aefc.js} +2 -2
- codex/static_root/assets/reader-DRsYPz-3.b8ee57f2aefc.js.br +0 -0
- codex/static_root/assets/reader-DRsYPz-3.b8ee57f2aefc.js.gz +0 -0
- codex/static_root/assets/{reader-Qan6W6n-.js → reader-DRsYPz-3.js} +2 -2
- codex/static_root/assets/reader-DRsYPz-3.js.br +0 -0
- codex/static_root/assets/reader-DRsYPz-3.js.gz +0 -0
- codex/static_root/assets/{stats-tab-Bv3OL9xU.949c9b8d7135.js → stats-tab-QTG23RuT.654f85e0b21d.js} +1 -1
- codex/static_root/assets/stats-tab-QTG23RuT.654f85e0b21d.js.br +0 -0
- codex/static_root/assets/stats-tab-QTG23RuT.654f85e0b21d.js.gz +0 -0
- codex/static_root/assets/{stats-tab-Bv3OL9xU.js → stats-tab-QTG23RuT.js} +1 -1
- codex/static_root/assets/stats-tab-QTG23RuT.js.br +0 -0
- codex/static_root/assets/stats-tab-QTG23RuT.js.gz +0 -0
- codex/static_root/assets/{task-tab-CgR8JqMw.54569b8df927.js → task-tab-Kff6fz1t.28380a665ed7.js} +1 -1
- codex/static_root/assets/task-tab-Kff6fz1t.28380a665ed7.js.br +0 -0
- codex/static_root/assets/task-tab-Kff6fz1t.28380a665ed7.js.gz +0 -0
- codex/static_root/assets/{task-tab-CgR8JqMw.js → task-tab-Kff6fz1t.js} +1 -1
- codex/static_root/assets/task-tab-Kff6fz1t.js.br +0 -0
- codex/static_root/assets/task-tab-Kff6fz1t.js.gz +0 -0
- codex/static_root/assets/{user-tab-Xzi_07Yi.d165773d55aa.js → user-tab-OAmZ6CQl.eed3361aefb7.js} +1 -1
- codex/static_root/assets/user-tab-OAmZ6CQl.eed3361aefb7.js.br +0 -0
- codex/static_root/assets/user-tab-OAmZ6CQl.eed3361aefb7.js.gz +0 -0
- codex/static_root/assets/{user-tab-Xzi_07Yi.js → user-tab-OAmZ6CQl.js} +1 -1
- codex/static_root/assets/user-tab-OAmZ6CQl.js.br +0 -0
- codex/static_root/assets/user-tab-OAmZ6CQl.js.gz +0 -0
- codex/static_root/js/choices.a4dcff295a04.json +1 -0
- codex/static_root/js/choices.a4dcff295a04.json.br +0 -0
- codex/static_root/js/choices.a4dcff295a04.json.gz +0 -0
- codex/static_root/js/choices.json +1 -1
- codex/static_root/js/choices.json.br +0 -0
- codex/static_root/js/choices.json.gz +0 -0
- codex/static_root/{manifest.0d2e5eed5ce7.json → manifest.13219ea92507.json} +217 -216
- codex/static_root/manifest.13219ea92507.json.br +0 -0
- codex/static_root/manifest.13219ea92507.json.gz +0 -0
- codex/static_root/manifest.json +217 -216
- codex/static_root/manifest.json.br +0 -0
- codex/static_root/manifest.json.gz +0 -0
- codex/static_root/staticfiles.json +1 -1
- codex/views/bookmark.py +12 -9
- codex/views/browser/base.py +21 -8
- codex/views/browser/browser.py +88 -68
- codex/views/browser/browser_annotations.py +19 -7
- codex/views/browser/choices.py +3 -5
- codex/views/browser/const.py +3 -0
- codex/views/browser/filters/search.py +114 -26
- codex/views/browser/metadata.py +4 -6
- codex/views/error.py +7 -3
- codex/views/opds/v1/feed.py +2 -1
- codex/views/opds/v2/feed.py +4 -6
- codex/views/opds/v2/publications.py +6 -3
- codex/views/session.py +1 -0
- {codex-1.5.12.dist-info → codex-1.5.13a0.dist-info}/METADATA +23 -12
- {codex-1.5.12.dist-info → codex-1.5.13a0.dist-info}/RECORD +255 -254
- codex/static_root/assets/VCheckbox-CC74mhfV.a196e804e50a.js.br +0 -0
- codex/static_root/assets/VCheckbox-CC74mhfV.a196e804e50a.js.gz +0 -0
- codex/static_root/assets/VCheckbox-CC74mhfV.js.br +0 -0
- codex/static_root/assets/VCheckbox-CC74mhfV.js.gz +0 -0
- codex/static_root/assets/VCheckboxBtn-F27UKlAX.f74083aa5b9a.js.br +0 -0
- codex/static_root/assets/VCheckboxBtn-F27UKlAX.f74083aa5b9a.js.gz +0 -0
- codex/static_root/assets/VCheckboxBtn-F27UKlAX.js.br +0 -0
- codex/static_root/assets/VCheckboxBtn-F27UKlAX.js.gz +0 -0
- codex/static_root/assets/VCombobox-Dw57vrly.b1184dfd61ec.js +0 -1
- codex/static_root/assets/VCombobox-Dw57vrly.b1184dfd61ec.js.br +0 -0
- codex/static_root/assets/VCombobox-Dw57vrly.b1184dfd61ec.js.gz +0 -0
- codex/static_root/assets/VCombobox-Dw57vrly.js +0 -1
- codex/static_root/assets/VCombobox-Dw57vrly.js.br +0 -0
- codex/static_root/assets/VCombobox-Dw57vrly.js.gz +0 -0
- codex/static_root/assets/VDataTableVirtual-BgFOSn9_.969c17b4d50a.js.br +0 -0
- codex/static_root/assets/VDataTableVirtual-BgFOSn9_.969c17b4d50a.js.gz +0 -0
- codex/static_root/assets/VDataTableVirtual-BgFOSn9_.js.br +0 -0
- codex/static_root/assets/VDataTableVirtual-BgFOSn9_.js.gz +0 -0
- codex/static_root/assets/VExpansionPanel-B06inlZY.a77a3ad1cc7c.js.br +0 -0
- codex/static_root/assets/VExpansionPanel-B06inlZY.a77a3ad1cc7c.js.gz +0 -0
- codex/static_root/assets/VExpansionPanel-B06inlZY.js.br +0 -0
- codex/static_root/assets/VExpansionPanel-B06inlZY.js.gz +0 -0
- codex/static_root/assets/VMain-BR4DrMy3.977234e0db6a.js.br +0 -0
- codex/static_root/assets/VMain-BR4DrMy3.977234e0db6a.js.gz +0 -0
- codex/static_root/assets/VMain-BR4DrMy3.js.br +0 -0
- codex/static_root/assets/VMain-BR4DrMy3.js.gz +0 -0
- codex/static_root/assets/VRadioGroup-DE0KmC8d.75bdb9d16a32.js.br +0 -0
- codex/static_root/assets/VRadioGroup-DE0KmC8d.75bdb9d16a32.js.gz +0 -0
- codex/static_root/assets/VRadioGroup-DE0KmC8d.js.br +0 -0
- codex/static_root/assets/VRadioGroup-DE0KmC8d.js.gz +0 -0
- codex/static_root/assets/VSelect-5wraBYHV.54a9a3184add.js +0 -1
- codex/static_root/assets/VSelect-5wraBYHV.54a9a3184add.js.br +0 -0
- codex/static_root/assets/VSelect-5wraBYHV.54a9a3184add.js.gz +0 -0
- codex/static_root/assets/VSelect-5wraBYHV.js +0 -1
- codex/static_root/assets/VSelect-5wraBYHV.js.br +0 -0
- codex/static_root/assets/VSelect-5wraBYHV.js.gz +0 -0
- codex/static_root/assets/VSelectionControl-B1zPb_Yg.6112179d7a5d.js.br +0 -0
- codex/static_root/assets/VSelectionControl-B1zPb_Yg.6112179d7a5d.js.gz +0 -0
- codex/static_root/assets/VSelectionControl-B1zPb_Yg.js.br +0 -0
- codex/static_root/assets/VSelectionControl-B1zPb_Yg.js.gz +0 -0
- codex/static_root/assets/VSlideGroup-F7Hpcms9.dce335daf8f2.js +0 -1
- codex/static_root/assets/VSlideGroup-F7Hpcms9.dce335daf8f2.js.br +0 -0
- codex/static_root/assets/VSlideGroup-F7Hpcms9.dce335daf8f2.js.gz +0 -0
- codex/static_root/assets/VSlideGroup-F7Hpcms9.js +0 -1
- codex/static_root/assets/VSlideGroup-F7Hpcms9.js.br +0 -0
- codex/static_root/assets/VSlideGroup-F7Hpcms9.js.gz +0 -0
- codex/static_root/assets/VTable-Pq4fCfUx.e50f8ad539ed.js.br +0 -0
- codex/static_root/assets/VTable-Pq4fCfUx.e50f8ad539ed.js.gz +0 -0
- codex/static_root/assets/VTable-Pq4fCfUx.js.br +0 -0
- codex/static_root/assets/VTable-Pq4fCfUx.js.gz +0 -0
- codex/static_root/assets/VToolbar-BFYiqJrS.71a0cbf7eb5f.js.br +0 -0
- codex/static_root/assets/VToolbar-BFYiqJrS.71a0cbf7eb5f.js.gz +0 -0
- codex/static_root/assets/VToolbar-BFYiqJrS.js.br +0 -0
- codex/static_root/assets/VToolbar-BFYiqJrS.js.gz +0 -0
- codex/static_root/assets/VToolbar-BfNszTMd.111f25cdd6d8.css.br +0 -0
- codex/static_root/assets/VToolbar-BfNszTMd.css.br +0 -0
- codex/static_root/assets/VWindowItem-g6ho7Hf4.b91f9a3277ff.js.br +0 -0
- codex/static_root/assets/VWindowItem-g6ho7Hf4.b91f9a3277ff.js.gz +0 -0
- codex/static_root/assets/VWindowItem-g6ho7Hf4.js.br +0 -0
- codex/static_root/assets/VWindowItem-g6ho7Hf4.js.gz +0 -0
- codex/static_root/assets/admin-BVkY78tW.affa20285127.js.br +0 -0
- codex/static_root/assets/admin-BVkY78tW.affa20285127.js.gz +0 -0
- codex/static_root/assets/admin-BVkY78tW.js.br +0 -0
- codex/static_root/assets/admin-BVkY78tW.js.gz +0 -0
- codex/static_root/assets/admin-drawer-panel-CEiEnUcn.9f94b93a422f.js.br +0 -0
- codex/static_root/assets/admin-drawer-panel-CEiEnUcn.9f94b93a422f.js.gz +0 -0
- codex/static_root/assets/admin-drawer-panel-CEiEnUcn.js.br +0 -0
- codex/static_root/assets/admin-drawer-panel-CEiEnUcn.js.gz +0 -0
- codex/static_root/assets/admin-drawer-panel-s72VfDNy.css.br +0 -0
- codex/static_root/assets/admin-drawer-panel-s72VfDNy.css.gz +0 -0
- codex/static_root/assets/admin-drawer-panel-s72VfDNy.ef6cb7221a44.css.br +0 -0
- codex/static_root/assets/admin-drawer-panel-s72VfDNy.ef6cb7221a44.css.gz +0 -0
- codex/static_root/assets/browser-2i0QA4La.587673ac534c.css.br +0 -0
- codex/static_root/assets/browser-2i0QA4La.587673ac534c.css.gz +0 -0
- codex/static_root/assets/browser-2i0QA4La.css.br +0 -0
- codex/static_root/assets/browser-2i0QA4La.css.gz +0 -0
- codex/static_root/assets/browser-BYquFWOA.3e5479490c40.js +0 -1
- codex/static_root/assets/browser-BYquFWOA.3e5479490c40.js.br +0 -0
- codex/static_root/assets/browser-BYquFWOA.3e5479490c40.js.gz +0 -0
- codex/static_root/assets/browser-BYquFWOA.js +0 -1
- codex/static_root/assets/browser-BYquFWOA.js.br +0 -0
- codex/static_root/assets/browser-BYquFWOA.js.gz +0 -0
- codex/static_root/assets/change-password-dialog-Bh7raeqK.6d408dcd933e.js.br +0 -0
- codex/static_root/assets/change-password-dialog-Bh7raeqK.6d408dcd933e.js.gz +0 -0
- codex/static_root/assets/change-password-dialog-Bh7raeqK.js.br +0 -0
- codex/static_root/assets/change-password-dialog-Bh7raeqK.js.gz +0 -0
- codex/static_root/assets/confirm-dialog-CvURjaTY.cadecd4cefa8.js.br +0 -0
- codex/static_root/assets/confirm-dialog-CvURjaTY.cadecd4cefa8.js.gz +0 -0
- codex/static_root/assets/confirm-dialog-CvURjaTY.js.br +0 -0
- codex/static_root/assets/confirm-dialog-CvURjaTY.js.gz +0 -0
- codex/static_root/assets/confirm-footer-C-VAfuKA.c93e5c6d41ca.js.br +0 -0
- codex/static_root/assets/confirm-footer-C-VAfuKA.c93e5c6d41ca.js.gz +0 -0
- codex/static_root/assets/confirm-footer-C-VAfuKA.js.br +0 -0
- codex/static_root/assets/confirm-footer-C-VAfuKA.js.gz +0 -0
- codex/static_root/assets/datetime-column-CDcOr8sM.951343a94a28.js.br +0 -0
- codex/static_root/assets/datetime-column-CDcOr8sM.951343a94a28.js.gz +0 -0
- codex/static_root/assets/datetime-column-CDcOr8sM.js.br +0 -0
- codex/static_root/assets/datetime-column-CDcOr8sM.js.gz +0 -0
- codex/static_root/assets/filter-DT8MlNGw.c70bb7a7c265.js.br +0 -0
- codex/static_root/assets/filter-DT8MlNGw.c70bb7a7c265.js.gz +0 -0
- codex/static_root/assets/filter-DT8MlNGw.js.br +0 -0
- codex/static_root/assets/filter-DT8MlNGw.js.gz +0 -0
- codex/static_root/assets/flag-tab-BVoz2gvN.591572581c12.js.br +0 -0
- codex/static_root/assets/flag-tab-BVoz2gvN.591572581c12.js.gz +0 -0
- codex/static_root/assets/flag-tab-BVoz2gvN.js.br +0 -0
- codex/static_root/assets/flag-tab-BVoz2gvN.js.gz +0 -0
- codex/static_root/assets/group-tab-Bu1Hn4DR.8c9fb2cbc4d2.js.br +0 -0
- codex/static_root/assets/group-tab-Bu1Hn4DR.8c9fb2cbc4d2.js.gz +0 -0
- codex/static_root/assets/group-tab-Bu1Hn4DR.js.br +0 -0
- codex/static_root/assets/group-tab-Bu1Hn4DR.js.gz +0 -0
- codex/static_root/assets/http-error-BKXUvS3w.93b39ceed2f7.js.br +0 -4
- codex/static_root/assets/http-error-BKXUvS3w.93b39ceed2f7.js.gz +0 -0
- codex/static_root/assets/http-error-BKXUvS3w.js.br +0 -4
- codex/static_root/assets/http-error-BKXUvS3w.js.gz +0 -0
- codex/static_root/assets/library-tab-AM2XWHOr.31f48701358e.js.br +0 -0
- codex/static_root/assets/library-tab-AM2XWHOr.31f48701358e.js.gz +0 -0
- codex/static_root/assets/library-tab-AM2XWHOr.js.br +0 -0
- codex/static_root/assets/library-tab-AM2XWHOr.js.gz +0 -0
- codex/static_root/assets/main-Dr7xEc75.ffae6222f1aa.js +0 -37
- codex/static_root/assets/main-Dr7xEc75.ffae6222f1aa.js.br +0 -0
- codex/static_root/assets/main-Dr7xEc75.ffae6222f1aa.js.gz +0 -0
- codex/static_root/assets/main-Dr7xEc75.js +0 -37
- codex/static_root/assets/main-Dr7xEc75.js.br +0 -0
- codex/static_root/assets/main-Dr7xEc75.js.gz +0 -0
- codex/static_root/assets/metadata-dialog-BGJasBRy.0553851658b5.css.br +0 -0
- codex/static_root/assets/metadata-dialog-BGJasBRy.0553851658b5.css.gz +0 -0
- codex/static_root/assets/metadata-dialog-BGJasBRy.css.br +0 -0
- codex/static_root/assets/metadata-dialog-BGJasBRy.css.gz +0 -0
- codex/static_root/assets/metadata-dialog-DFDQ4P3u.b959bb5a03a2.js +0 -1
- codex/static_root/assets/metadata-dialog-DFDQ4P3u.b959bb5a03a2.js.br +0 -0
- codex/static_root/assets/metadata-dialog-DFDQ4P3u.b959bb5a03a2.js.gz +0 -0
- codex/static_root/assets/metadata-dialog-DFDQ4P3u.js +0 -1
- codex/static_root/assets/metadata-dialog-DFDQ4P3u.js.br +0 -0
- codex/static_root/assets/metadata-dialog-DFDQ4P3u.js.gz +0 -0
- codex/static_root/assets/pdf-doc-DSq1qfWx.50ab90d8b609.js.br +0 -0
- codex/static_root/assets/pdf-doc-DSq1qfWx.50ab90d8b609.js.gz +0 -0
- codex/static_root/assets/pdf-doc-DSq1qfWx.js.br +0 -0
- codex/static_root/assets/pdf-doc-DSq1qfWx.js.gz +0 -0
- codex/static_root/assets/reader-Qan6W6n-.fc91835a9075.js.br +0 -0
- codex/static_root/assets/reader-Qan6W6n-.fc91835a9075.js.gz +0 -0
- codex/static_root/assets/reader-Qan6W6n-.js.br +0 -0
- codex/static_root/assets/reader-Qan6W6n-.js.gz +0 -0
- codex/static_root/assets/stats-tab-Bv3OL9xU.949c9b8d7135.js.br +0 -0
- codex/static_root/assets/stats-tab-Bv3OL9xU.949c9b8d7135.js.gz +0 -0
- codex/static_root/assets/stats-tab-Bv3OL9xU.js.br +0 -0
- codex/static_root/assets/stats-tab-Bv3OL9xU.js.gz +0 -0
- codex/static_root/assets/task-tab-CgR8JqMw.54569b8df927.js.br +0 -0
- codex/static_root/assets/task-tab-CgR8JqMw.54569b8df927.js.gz +0 -0
- codex/static_root/assets/task-tab-CgR8JqMw.js.br +0 -0
- codex/static_root/assets/task-tab-CgR8JqMw.js.gz +0 -0
- codex/static_root/assets/user-tab-Xzi_07Yi.d165773d55aa.js.br +0 -0
- codex/static_root/assets/user-tab-Xzi_07Yi.d165773d55aa.js.gz +0 -0
- codex/static_root/assets/user-tab-Xzi_07Yi.js.br +0 -0
- codex/static_root/assets/user-tab-Xzi_07Yi.js.gz +0 -0
- codex/static_root/js/choices.fedcbd1ec085.json +0 -1
- codex/static_root/js/choices.fedcbd1ec085.json.br +0 -0
- codex/static_root/js/choices.fedcbd1ec085.json.gz +0 -0
- codex/static_root/manifest.0d2e5eed5ce7.json.br +0 -0
- codex/static_root/manifest.0d2e5eed5ce7.json.gz +0 -0
- {codex-1.5.12.dist-info → codex-1.5.13a0.dist-info}/LICENSE +0 -0
- {codex-1.5.12.dist-info → codex-1.5.13a0.dist-info}/WHEEL +0 -0
- {codex-1.5.12.dist-info → codex-1.5.13a0.dist-info}/entry_points.txt +0 -0
|
@@ -1,56 +1,144 @@
|
|
|
1
1
|
"""Search Filters Methods."""
|
|
2
2
|
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from time import time
|
|
5
|
+
|
|
3
6
|
from django.db.models import Q
|
|
4
7
|
|
|
5
8
|
from codex._vendor.haystack.query import SearchQuerySet
|
|
6
9
|
from codex.logger.logging import get_logger
|
|
7
10
|
from codex.models import Comic
|
|
11
|
+
from codex.settings.settings import DEBUG
|
|
12
|
+
from codex.views.browser.const import MAX_OBJ_PER_PAGE
|
|
8
13
|
|
|
9
14
|
LOG = get_logger(__name__)
|
|
10
15
|
|
|
11
16
|
|
|
17
|
+
@dataclass
|
|
18
|
+
class SearchScores:
|
|
19
|
+
"""Search Scores for annotation."""
|
|
20
|
+
|
|
21
|
+
scores: tuple[tuple[int, float], ...] = ()
|
|
22
|
+
scored_pks: tuple[int, ...] = ()
|
|
23
|
+
prev_pks: tuple[int, ...] = ()
|
|
24
|
+
next_pks: tuple[int, ...] = ()
|
|
25
|
+
|
|
26
|
+
|
|
12
27
|
class SearchFilterMixin:
|
|
13
28
|
"""Search Filters Methods."""
|
|
14
29
|
|
|
15
|
-
def
|
|
30
|
+
def _get_binary_search_scores(self, sqs):
|
|
31
|
+
"""Get search scores for choices and metadata."""
|
|
32
|
+
sqs = sqs.values_list("pk", flat=True)
|
|
33
|
+
search_results_limit = self.params.get( # type: ignore
|
|
34
|
+
"search_results_limit",
|
|
35
|
+
MAX_OBJ_PER_PAGE, # type: ignore
|
|
36
|
+
)
|
|
37
|
+
if search_results_limit:
|
|
38
|
+
sqs = sqs[:search_results_limit] # type: ignore
|
|
39
|
+
return tuple(sqs)
|
|
40
|
+
|
|
41
|
+
def _get_browser_search_scores(self, sqs):
|
|
42
|
+
"""Get search scores for the browser cards."""
|
|
43
|
+
page = self.kwargs.get("page", 1) # type: ignore
|
|
44
|
+
search_results_limit = self.params.get( # type: ignore
|
|
45
|
+
"search_results_limit",
|
|
46
|
+
MAX_OBJ_PER_PAGE, # type: ignore
|
|
47
|
+
)
|
|
48
|
+
if search_results_limit:
|
|
49
|
+
offset = 0
|
|
50
|
+
limit = search_results_limit
|
|
51
|
+
else:
|
|
52
|
+
offset = max(0, (page - 1) * MAX_OBJ_PER_PAGE) # type: ignore
|
|
53
|
+
limit = offset + MAX_OBJ_PER_PAGE # type: ignore
|
|
54
|
+
|
|
55
|
+
if DEBUG:
|
|
56
|
+
LOG.debug(
|
|
57
|
+
f"searching... {page=} page_{offset=} page_{limit=} {search_results_limit=}"
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
scores_pairs = []
|
|
61
|
+
prev_pks = []
|
|
62
|
+
next_pks = []
|
|
63
|
+
|
|
64
|
+
if DEBUG:
|
|
65
|
+
start_time = time()
|
|
66
|
+
scores_values = sqs.values_list("pk", "score")
|
|
67
|
+
if search_results_limit:
|
|
68
|
+
scores_values = scores_values[:limit]
|
|
69
|
+
for index, pair in enumerate(scores_values):
|
|
70
|
+
if index < offset:
|
|
71
|
+
prev_pks.append(pair[0])
|
|
72
|
+
elif index > limit:
|
|
73
|
+
next_pks.append(pair[0])
|
|
74
|
+
else:
|
|
75
|
+
scores_pairs.append(pair)
|
|
76
|
+
|
|
77
|
+
if DEBUG:
|
|
78
|
+
LOG.debug(
|
|
79
|
+
f"search {time() - start_time}s" # type: ignore
|
|
80
|
+
f" {len(scores_pairs)=} {len(prev_pks)=} {len(next_pks)=}"
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
return tuple(scores_pairs), tuple(prev_pks), tuple(next_pks)
|
|
84
|
+
|
|
85
|
+
def get_search_scores(self, binary=False) -> SearchScores | None:
|
|
16
86
|
"""Perform the search and return the scores as a dict."""
|
|
17
|
-
search_scores = {}
|
|
18
87
|
text = self.params.get("q", "") # type: ignore
|
|
19
88
|
if not text:
|
|
20
|
-
|
|
21
|
-
text = self.params.get("query", "") # type: ignore
|
|
22
|
-
text = text.strip()
|
|
23
|
-
if not text:
|
|
24
|
-
return search_scores
|
|
89
|
+
return None
|
|
25
90
|
|
|
26
|
-
|
|
27
|
-
|
|
91
|
+
scores_pairs = ()
|
|
92
|
+
scored_pks = ()
|
|
93
|
+
prev_pks = ()
|
|
94
|
+
next_pks = ()
|
|
28
95
|
try:
|
|
29
|
-
|
|
30
|
-
|
|
96
|
+
sqs = SearchQuerySet()
|
|
97
|
+
sqs = sqs.auto_query(text) # .filter(score__gt=0.0)
|
|
98
|
+
if binary:
|
|
99
|
+
scored_pks = self._get_binary_search_scores(sqs)
|
|
100
|
+
else:
|
|
101
|
+
scores_pairs, prev_pks, next_pks = self._get_browser_search_scores(sqs)
|
|
102
|
+
|
|
31
103
|
except MemoryError:
|
|
32
104
|
LOG.warning("Search engine needs more memory, results truncated.")
|
|
33
105
|
except Exception:
|
|
34
|
-
LOG.exception("
|
|
35
|
-
|
|
36
|
-
return None
|
|
37
|
-
return search_scores
|
|
106
|
+
LOG.exception("Getting Search Scores")
|
|
107
|
+
return SearchScores(scores_pairs, scored_pks, prev_pks, next_pks)
|
|
38
108
|
|
|
39
|
-
def _get_search_query_filter(
|
|
109
|
+
def _get_search_query_filter(
|
|
110
|
+
self,
|
|
111
|
+
model,
|
|
112
|
+
search_scores: SearchScores,
|
|
113
|
+
):
|
|
40
114
|
"""Get the search filter and scores."""
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
115
|
+
if search_scores.scores:
|
|
116
|
+
query = Q(search_score__gt=0.0)
|
|
117
|
+
else:
|
|
118
|
+
prefix = "" if model == Comic else self.rel_prefix # type: ignore
|
|
119
|
+
rel = prefix + "pk__in"
|
|
120
|
+
query_dict = {rel: search_scores.scored_pks}
|
|
121
|
+
query = Q(**query_dict)
|
|
122
|
+
return query
|
|
45
123
|
|
|
46
|
-
def
|
|
124
|
+
def apply_search_filter(
|
|
125
|
+
self,
|
|
126
|
+
qs,
|
|
127
|
+
model,
|
|
128
|
+
search_scores: SearchScores | None,
|
|
129
|
+
):
|
|
47
130
|
"""Preparse search, search and return the filter and scores."""
|
|
48
|
-
search_filter = Q()
|
|
49
131
|
try:
|
|
50
132
|
if search_scores:
|
|
51
|
-
# Query haystack
|
|
52
133
|
search_filter = self._get_search_query_filter(model, search_scores)
|
|
53
|
-
|
|
54
|
-
|
|
134
|
+
qs = qs.filter(search_filter)
|
|
135
|
+
except Exception:
|
|
136
|
+
LOG.exception("Creating the search filter")
|
|
137
|
+
|
|
138
|
+
return qs
|
|
55
139
|
|
|
56
|
-
|
|
140
|
+
def apply_binary_search_filter(self, qs):
|
|
141
|
+
"""Apply scoreless search filter for choices & metadata."""
|
|
142
|
+
search_scores = self.get_search_scores(binary=True)
|
|
143
|
+
model = self.model # type: ignore
|
|
144
|
+
return self.apply_search_filter(qs, model, search_scores)
|
codex/views/browser/metadata.py
CHANGED
|
@@ -97,7 +97,7 @@ class MetadataView(BrowserAnnotationsView):
|
|
|
97
97
|
if not self.is_model_comic:
|
|
98
98
|
size_func = self.get_aggregate_func(self.model, "size")
|
|
99
99
|
qs = qs.annotate(size=size_func)
|
|
100
|
-
return self.annotate_common_aggregates(qs, self.model,
|
|
100
|
+
return self.annotate_common_aggregates(qs, self.model, None)
|
|
101
101
|
|
|
102
102
|
def _annotate_values_and_fks(self, qs, simple_qs):
|
|
103
103
|
"""Annotate comic values and comic foreign key values."""
|
|
@@ -242,13 +242,11 @@ class MetadataView(BrowserAnnotationsView):
|
|
|
242
242
|
if self.model is None:
|
|
243
243
|
raise NotFound(detail=f"Cannot get metadata for {self.group=}")
|
|
244
244
|
|
|
245
|
-
|
|
246
|
-
if search_scores is None:
|
|
247
|
-
self._raise_not_found()
|
|
248
|
-
object_filter = self.get_query_filters_without_group(self.model, search_scores) # type: ignore
|
|
245
|
+
object_filter = self.get_query_filters_without_group(self.model)
|
|
249
246
|
pk = self.kwargs["pk"]
|
|
250
247
|
qs = self.model.objects.filter(object_filter, pk=pk)
|
|
251
|
-
|
|
248
|
+
if self.model != Comic:
|
|
249
|
+
qs = self.apply_binary_search_filter(qs)
|
|
252
250
|
qs = self._annotate_aggregates(qs)
|
|
253
251
|
simple_qs = qs
|
|
254
252
|
|
codex/views/error.py
CHANGED
|
@@ -7,15 +7,19 @@ from rest_framework.views import exception_handler
|
|
|
7
7
|
|
|
8
8
|
from codex.exceptions import SeeOtherRedirectError
|
|
9
9
|
|
|
10
|
+
_OPDS_PREFIX = "opds/v"
|
|
11
|
+
|
|
10
12
|
|
|
11
13
|
def codex_exception_handler(exc, context):
|
|
12
14
|
"""Assume OPDS clients want redirects instead of errors."""
|
|
13
15
|
response = None
|
|
14
16
|
request = context.get("request")
|
|
15
|
-
|
|
16
|
-
|
|
17
|
+
if _OPDS_PREFIX in request.path:
|
|
18
|
+
name = "opds:v2:feed" if _OPDS_PREFIX + "2" in request.path else "opds:v1:feed"
|
|
19
|
+
opds_start = reverse(name)
|
|
20
|
+
|
|
17
21
|
if isinstance(exc, SeeOtherRedirectError):
|
|
18
|
-
response = exc.get_response(
|
|
22
|
+
response = exc.get_response(opds_start)
|
|
19
23
|
elif hasattr(exc, "status_code") and exc.status_code in (
|
|
20
24
|
status.HTTP_400_BAD_REQUEST,
|
|
21
25
|
status.HTTP_404_NOT_FOUND,
|
codex/views/opds/v1/feed.py
CHANGED
|
@@ -12,6 +12,7 @@ from codex.serializers.opds.v1 import (
|
|
|
12
12
|
OPDS1TemplateSerializer,
|
|
13
13
|
)
|
|
14
14
|
from codex.views.browser.browser import BrowserView
|
|
15
|
+
from codex.views.browser.const import MAX_OBJ_PER_PAGE
|
|
15
16
|
from codex.views.const import FALSY
|
|
16
17
|
from codex.views.opds.const import BLANK_TITLE, MimeType
|
|
17
18
|
from codex.views.opds.v1.entry.data import OPDS1EntryData
|
|
@@ -107,7 +108,7 @@ class OPDS1FeedView(CodexXMLTemplateView, LinksMixin):
|
|
|
107
108
|
"""Return opensearch:itemsPerPage."""
|
|
108
109
|
try:
|
|
109
110
|
if self.params.get("q"):
|
|
110
|
-
return
|
|
111
|
+
return MAX_OBJ_PER_PAGE
|
|
111
112
|
except Exception:
|
|
112
113
|
LOG.exception("Getting OPDS v1 items per page")
|
|
113
114
|
|
codex/views/opds/v2/feed.py
CHANGED
|
@@ -11,6 +11,7 @@ from codex.logger.logging import get_logger
|
|
|
11
11
|
from codex.models import AdminFlag
|
|
12
12
|
from codex.serializers.opds.v2 import OPDS2FeedSerializer
|
|
13
13
|
from codex.views.browser.browser import BrowserView
|
|
14
|
+
from codex.views.browser.const import MAX_OBJ_PER_PAGE
|
|
14
15
|
from codex.views.const import FALSY
|
|
15
16
|
from codex.views.opds.const import BLANK_TITLE
|
|
16
17
|
from codex.views.opds.v2.const import (
|
|
@@ -175,14 +176,11 @@ class OPDS2FeedView(PublicationMixin, TopLinksMixin):
|
|
|
175
176
|
"""Get the browser page and serialize it for this subclass."""
|
|
176
177
|
group = self.kwargs.get("group")
|
|
177
178
|
if group in ("f", "a"):
|
|
178
|
-
self.acquisition_groups = frozenset()
|
|
179
|
-
else:
|
|
180
|
-
self.acquisition_groups = frozenset(self.valid_nav_groups[-2:])
|
|
181
|
-
if group == "a":
|
|
182
179
|
pk = self.kwargs["pk"]
|
|
183
180
|
self.is_opds_2_acquisition = bool(pk)
|
|
184
181
|
else:
|
|
185
|
-
|
|
182
|
+
acquisition_groups = frozenset(self.valid_nav_groups[-2:])
|
|
183
|
+
self.is_opds_2_acquisition = group in acquisition_groups
|
|
186
184
|
self.is_opds_metadata = (
|
|
187
185
|
self.request.query_params.get("opdsMetadata", "").lower() not in FALSY
|
|
188
186
|
)
|
|
@@ -202,7 +200,7 @@ class OPDS2FeedView(PublicationMixin, TopLinksMixin):
|
|
|
202
200
|
"metadata": {
|
|
203
201
|
"title": title,
|
|
204
202
|
"number_of_items": number_of_items,
|
|
205
|
-
"items_per_page":
|
|
203
|
+
"items_per_page": MAX_OBJ_PER_PAGE,
|
|
206
204
|
"current_page": self.kwargs.get("page"),
|
|
207
205
|
},
|
|
208
206
|
"links": self.get_links(browser_page["up_route"]),
|
|
@@ -144,8 +144,10 @@ class PublicationMixin(LinksMixin):
|
|
|
144
144
|
|
|
145
145
|
download_mime_type = MimeType.FILE_TYPE_MAP.get(obj.file_type, MimeType.OCTET)
|
|
146
146
|
self_kwargs = {"group": "c", "pk": obj.pk, "page": 1}
|
|
147
|
-
|
|
148
|
-
|
|
147
|
+
|
|
148
|
+
# This would be for comic streaming which is not supported by OPDS 2 yet?
|
|
149
|
+
# self_href_data = HrefData(self_kwargs, absolute_query_params=True)
|
|
150
|
+
# self_link_data = LinkData(Rel.SELF, self_href_data, mime_type=MimeType.OPDS_PUB)
|
|
149
151
|
|
|
150
152
|
alt_kwargs = self_kwargs
|
|
151
153
|
alt_href_data = HrefData(
|
|
@@ -168,7 +170,8 @@ class PublicationMixin(LinksMixin):
|
|
|
168
170
|
mime_type=download_mime_type,
|
|
169
171
|
)
|
|
170
172
|
links = [
|
|
171
|
-
|
|
173
|
+
# Comic streaming link (unsupported)
|
|
174
|
+
# self.link(self_link_data),
|
|
172
175
|
self.link(alt_link_data),
|
|
173
176
|
self.link(acq_link_data),
|
|
174
177
|
]
|
codex/views/session.py
CHANGED
|
@@ -105,6 +105,7 @@ class BrowserSessionViewBase(SessionViewBaseBase):
|
|
|
105
105
|
"order_reverse": False,
|
|
106
106
|
"q": DEFAULTS["q"],
|
|
107
107
|
"route": DEFAULTS["route"],
|
|
108
|
+
"search_results_limit": DEFAULTS["searchResultsLimit"],
|
|
108
109
|
"show": DEFAULTS["show"],
|
|
109
110
|
"twenty_four_hour_time": False,
|
|
110
111
|
"top_group": DEFAULTS["topGroup"],
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: codex
|
|
3
|
-
Version: 1.5.
|
|
3
|
+
Version: 1.5.13a0
|
|
4
4
|
Summary: A comic archive web server.
|
|
5
5
|
Home-page: https://github.com/ajslater/codex
|
|
6
6
|
License: GPL-3.0-only
|
|
@@ -30,6 +30,7 @@ Requires-Dist: case-converter (>=1.1.0,<2.0.0)
|
|
|
30
30
|
Requires-Dist: channels (>=4.0.0,<5.0.0)
|
|
31
31
|
Requires-Dist: comicbox[pdf] (>=1.1.4,<2.0.0)
|
|
32
32
|
Requires-Dist: django (>=5.0.3,<6.0.0)
|
|
33
|
+
Requires-Dist: django-cachalot (>=2.6.2,<3.0.0)
|
|
33
34
|
Requires-Dist: django-cors-headers (>=4.0,<5.0)
|
|
34
35
|
Requires-Dist: django-rest-registration (>=0.8.0,<0.9.0)
|
|
35
36
|
Requires-Dist: django-vite (>=3.0.1,<4.0.0)
|
|
@@ -267,15 +268,29 @@ remove users to groups.
|
|
|
267
268
|
Codex can make groups for libraries that exclude groups of users or exclude
|
|
268
269
|
everyone and include only certain groups of users.
|
|
269
270
|
|
|
270
|
-
###
|
|
271
|
+
### PDF Metadata
|
|
271
272
|
|
|
272
|
-
Codex
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
273
|
+
Codex reads PDF metadata from the filename, PDF metadata fields and also many
|
|
274
|
+
formats of common complex comic metadata if they are embedded in the PDF
|
|
275
|
+
`keywords` field.
|
|
276
|
+
|
|
277
|
+
If you decide to include PDFs in your comic library, I recommend taking time to
|
|
278
|
+
rename your files so Codex can find some metadata. Codex recognizes several file
|
|
279
|
+
naming schemes. This one has good results:
|
|
276
280
|
|
|
277
281
|
`{series} v{volume} #{issue} {title} ({year}) {ignored}.pdf`
|
|
278
282
|
|
|
283
|
+
Complex comic metadata, such as ComicInfo.xml, can be also be embedded in the
|
|
284
|
+
keywords field by using the [comicbox](https://github.com/ajslater/comicbox)
|
|
285
|
+
command line tool. Codex will read this data because it relies on comicbox
|
|
286
|
+
internally. Not many people use comicbox or embedded metadata in PDFs in this
|
|
287
|
+
fashion, so you likely won't find it unless you've added it yourself.
|
|
288
|
+
|
|
289
|
+
### 🗝️ API with Key Access
|
|
290
|
+
|
|
291
|
+
Codex has a limited number of API endpoints available with API Key Access. The
|
|
292
|
+
API Key is available on the admin/stats tab.
|
|
293
|
+
|
|
279
294
|
## <a name="configuration">🎛️ Configuration</a>
|
|
280
295
|
|
|
281
296
|
### Config Dir
|
|
@@ -384,7 +399,7 @@ If you must run Codex in an admin restricted memory environment you might want
|
|
|
384
399
|
to temporarily give Codex a lot of memory to run a very large import job and
|
|
385
400
|
then restrict it for normal operation.
|
|
386
401
|
|
|
387
|
-
## <a name="
|
|
402
|
+
## <a name="use">📖 Use</a>
|
|
388
403
|
|
|
389
404
|
### 👤 Sessions & Accounts
|
|
390
405
|
|
|
@@ -395,11 +410,6 @@ To preserve these settings across browsers and after sessions expire, you may
|
|
|
395
410
|
register an account with a username and password. You will have to contact your
|
|
396
411
|
administrator to reset your password if you forget it.
|
|
397
412
|
|
|
398
|
-
### 🗝️ API with Key Access
|
|
399
|
-
|
|
400
|
-
Codex has a limited number of API endpoints available with API Key Access. The
|
|
401
|
-
API Key is available on the admin/stats tab.
|
|
402
|
-
|
|
403
413
|
### ᯤ OPDS
|
|
404
414
|
|
|
405
415
|
Codex supports OPDS syndication and OPDS streaming. You may find the OPDS url in
|
|
@@ -438,6 +448,7 @@ authentication. In that case the OPDS url will look like:
|
|
|
438
448
|
- [OPDS-PSE 1.2](https://github.com/anansi-project/opds-pse/blob/master/v1.2.md)
|
|
439
449
|
- [OPDS Authentication 1.0](https://drafts.opds.io/authentication-for-opds-1.0.html)
|
|
440
450
|
- [OpenSearch 1.1](https://github.com/dewitt/opensearch)
|
|
451
|
+
- [OPDS 2.0 (draft)](https://drafts.opds.io/opds-2.0.html)
|
|
441
452
|
|
|
442
453
|
## <a name="troubleshooting">🩺 Troubleshooting</a>
|
|
443
454
|
|