Compare commits
528 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5f607cc034 | ||
|
|
3b9f508be9 | ||
|
|
89e381b7ea | ||
|
|
57869b2145 | ||
|
|
46976900d7 | ||
|
|
a1535da117 | ||
|
|
f43d782b5c | ||
|
|
5c443e2f93 | ||
|
|
54f01f63f7 | ||
|
|
c64b4473e4 | ||
|
|
d413a37c1f | ||
|
|
202fb12008 | ||
|
|
59dea63870 | ||
|
|
9a18f2b553 | ||
|
|
4293ec3805 | ||
|
|
f3b616e495 | ||
|
|
003ea24990 | ||
|
|
92d4566a54 | ||
|
|
70a933edc1 | ||
|
|
d2d77f28aa | ||
|
|
39179971c5 | ||
|
|
c06f36e8c2 | ||
|
|
1d2d9d8b99 | ||
|
|
5f529817ef | ||
|
|
7c91bc2f37 | ||
|
|
ef022f5a6d | ||
|
|
54ce00c8b9 | ||
|
|
baabbfb1ea | ||
|
|
28e676ac9a | ||
|
|
21fac9ec7a | ||
|
|
335955820b | ||
|
|
d2b0e7209f | ||
|
|
f8ed21c819 | ||
|
|
9c2143effe | ||
|
|
8a3fa6aff6 | ||
|
|
7e304bb231 | ||
|
|
99d614289e | ||
|
|
b90894c20f | ||
|
|
921834c917 | ||
|
|
83df4451e6 | ||
|
|
2ad9e1bb43 | ||
|
|
c9990e5ca4 | ||
|
|
c95e61db09 | ||
|
|
7bb12ff0ec | ||
|
|
670bfa18de | ||
|
|
130f619b05 | ||
|
|
f900c842cb | ||
|
|
c2844a8f35 | ||
|
|
a864dabbaf | ||
|
|
02786f4801 | ||
|
|
5a4fe266c6 | ||
|
|
b30a4db0b8 | ||
|
|
2e76e07764 | ||
|
|
1be92f5078 | ||
|
|
8afff29cd4 | ||
|
|
9c6090a355 | ||
|
|
27b73227ed | ||
|
|
9582f8380f | ||
|
|
bfeac7e70b | ||
|
|
2050c0b7a8 | ||
|
|
144f9bed69 | ||
|
|
f2b642d944 | ||
|
|
bcdc75953e | ||
|
|
1fabe5a7cf | ||
|
|
fe9a4b7aa3 | ||
|
|
56735dc1c6 | ||
|
|
42287b92f1 | ||
|
|
7d9e642f24 | ||
|
|
b20e10585f | ||
|
|
8438b211a6 | ||
|
|
f94314afec | ||
|
|
4584d23434 | ||
|
|
2791501781 | ||
|
|
6ea798e55b | ||
|
|
0ab6ac569e | ||
|
|
f91d7352a4 | ||
|
|
d644b8fe01 | ||
|
|
5a8042cc10 | ||
|
|
ae910eb731 | ||
|
|
c1158c3175 | ||
|
|
79562e7ad9 | ||
|
|
e3388bea96 | ||
|
|
a3b4a7ef1d | ||
|
|
947b06cd61 | ||
|
|
a3f3561f02 | ||
|
|
48095d38be | ||
|
|
1c6858653a | ||
|
|
648797325e | ||
|
|
af3fa88d67 | ||
|
|
8123effa65 | ||
|
|
554800c06f | ||
|
|
687ce29366 | ||
|
|
c70301572c | ||
|
|
714f58e2c5 | ||
|
|
9bf9dca88a | ||
|
|
0663f25208 | ||
|
|
275d162b81 | ||
|
|
675956a7c4 | ||
|
|
cf1602c0af | ||
|
|
35979ed332 | ||
|
|
6e65ae5306 | ||
|
|
95e716b8ce | ||
|
|
554284ac67 | ||
|
|
fa6102bbad | ||
|
|
f28d5f19a7 | ||
|
|
34d59c7741 | ||
|
|
21d432a3ca | ||
|
|
d444935140 | ||
|
|
9de9d96e35 | ||
|
|
5932558ca2 | ||
|
|
7b22adb72e | ||
|
|
0db5d062be | ||
|
|
678d510e29 | ||
|
|
1fc3307d22 | ||
|
|
45c17ba949 | ||
|
|
15bd1d9006 | ||
|
|
b4715f0931 | ||
|
|
6f24a2a88c | ||
|
|
fcbecf895a | ||
|
|
5abe8a109c | ||
|
|
ee6d0af795 | ||
|
|
0dc82b6a28 | ||
|
|
a530eda9fc | ||
|
|
3fa39798e5 | ||
|
|
b7f8832633 | ||
|
|
2add8d671a | ||
|
|
d5d1fcf331 | ||
|
|
9007501d81 | ||
|
|
fc12a8f549 | ||
|
|
86f03b3399 | ||
|
|
80ad0e7f68 | ||
|
|
ea970be6f2 | ||
|
|
4bd0b96a2d | ||
|
|
c7f0436ec0 | ||
|
|
ecc788fd79 | ||
|
|
8ea9d5685d | ||
|
|
c2bd2f0672 | ||
|
|
424b7964b4 | ||
|
|
98394fdc63 | ||
|
|
625e90518e | ||
|
|
d446191cf4 | ||
|
|
ea2557274f | ||
|
|
1bcca566ab | ||
|
|
cf365635ef | ||
|
|
df6a93da5f | ||
|
|
433512a256 | ||
|
|
e0fe78b82e | ||
|
|
d3a84690f2 | ||
|
|
3df4b4dc57 | ||
|
|
b2801f3a40 | ||
|
|
e1bdfd7e4e | ||
|
|
5584c12d0a | ||
|
|
91bd02157c | ||
|
|
02d2b88a54 | ||
|
|
6ae5c5e6ce | ||
|
|
123d2f6120 | ||
|
|
3ada10c3f4 | ||
|
|
b21a928028 | ||
|
|
374cf08086 | ||
|
|
15a85bb873 | ||
|
|
4b12678fa4 | ||
|
|
b2d4bea1d0 | ||
|
|
6df3a7d4b5 | ||
|
|
6964bf7c8a | ||
|
|
965424799d | ||
|
|
f7de2ead40 | ||
|
|
260ba19e44 | ||
|
|
5caff5d28e | ||
|
|
8fa490c938 | ||
|
|
8e3cc0df0c | ||
|
|
1a5a4cf72d | ||
|
|
6c5b7bbed0 | ||
|
|
f9eee6a864 | ||
|
|
4ad0fe5653 | ||
|
|
a02823ca38 | ||
|
|
513f8e66f5 | ||
|
|
0cecc168b6 | ||
|
|
6f7281b0f5 | ||
|
|
c7022bd285 | ||
|
|
e89e3d2e1b | ||
|
|
574fb6804f | ||
|
|
caf75fafdf | ||
|
|
bc74fb63d1 | ||
|
|
b576a87d61 | ||
|
|
6e81d8acec | ||
|
|
c67a53d156 | ||
|
|
bf5ea81b40 | ||
|
|
1261b8670f | ||
|
|
17dad33f8b | ||
|
|
1d5c160e1d | ||
|
|
f04b7fa365 | ||
|
|
fa011fbdce | ||
|
|
759c5374d9 | ||
|
|
f631acdf18 | ||
|
|
b2dfd8ab11 | ||
|
|
43f4803da7 | ||
|
|
019d8220b8 | ||
|
|
b946010bdb | ||
|
|
c3097b12c3 | ||
|
|
12a53710c3 | ||
|
|
983326e610 | ||
|
|
b4eb707b38 | ||
|
|
e44f34f0a9 | ||
|
|
3c762adbf4 | ||
|
|
ebabd20d09 | ||
|
|
8694e1901a | ||
|
|
0f2875e89a | ||
|
|
74d9921be1 | ||
|
|
41e56adfdb | ||
|
|
4ff1d302d9 | ||
|
|
d6e213d51a | ||
|
|
2a4deeba55 | ||
|
|
24b1d2afcb | ||
|
|
5cea3d824a | ||
|
|
78a8a7d744 | ||
|
|
a3bf85754a | ||
|
|
006b6fd5e8 | ||
|
|
8ff2c42070 | ||
|
|
c5d18c6884 | ||
|
|
48b3621f1e | ||
|
|
fb716eb498 | ||
|
|
5d8e294350 | ||
|
|
8a96d8c24e | ||
|
|
6396d2f922 | ||
|
|
ed7e90451b | ||
|
|
f5990dd5c4 | ||
|
|
f29f615aec | ||
|
|
f1300badb8 | ||
|
|
88a1cddb23 | ||
|
|
d53fbc52d1 | ||
|
|
ec9511c17a | ||
|
|
3f2bb3beae | ||
|
|
c8b96696b0 | ||
|
|
0bb6b53ebc | ||
|
|
7400c2373b | ||
|
|
635329f102 | ||
|
|
b5a2123d1c | ||
|
|
396c558b25 | ||
|
|
60e178d821 | ||
|
|
7769aaccea | ||
|
|
5ff6d0b014 | ||
|
|
7d9a1b5e0c | ||
|
|
127086a50e | ||
|
|
90d14c004f | ||
|
|
8c457c057e | ||
|
|
36215a989a | ||
|
|
74259bd4c6 | ||
|
|
4561b7dce2 | ||
|
|
89d6166dbe | ||
|
|
f451977a04 | ||
|
|
aac05727ed | ||
|
|
c9ae65a9a8 | ||
|
|
f4a9dbb546 | ||
|
|
3eec791584 | ||
|
|
57473da182 | ||
|
|
fd90752a12 | ||
|
|
0d3f5e0c32 | ||
|
|
c98b0aac90 | ||
|
|
3de85975d6 | ||
|
|
962cdef69a | ||
|
|
b301d20488 | ||
|
|
1b2895b0ca | ||
|
|
d6943bb1dd | ||
|
|
51d74503ae | ||
|
|
5eac3cf9cf | ||
|
|
27d6f24c3c | ||
|
|
d929b163db | ||
|
|
571b3fbfa8 | ||
|
|
db05f8eaa3 | ||
|
|
d8eba81efc | ||
|
|
429ef67bbf | ||
|
|
e5d9e69e3e | ||
|
|
dc32bdc474 | ||
|
|
c45b709d54 | ||
|
|
e1be084d98 | ||
|
|
20b8aafe11 | ||
|
|
c719adf235 | ||
|
|
d08a0bdb00 | ||
|
|
8294391ebc | ||
|
|
394c206133 | ||
|
|
2fcd561ff7 | ||
|
|
f95b77fd7a | ||
|
|
7509bf69ca | ||
|
|
d9adec88c8 | ||
|
|
938a1bca0d | ||
|
|
ab757c502c | ||
|
|
6b17388bd8 | ||
|
|
48a933b757 | ||
|
|
6c02bf73b5 | ||
|
|
960d0bcdf2 | ||
|
|
d389e4390f | ||
|
|
55ce83a642 | ||
|
|
300f8f666d | ||
|
|
5d6083dce4 | ||
|
|
82f9f5027f | ||
|
|
4f015f1d96 | ||
|
|
bbe272c35c | ||
|
|
39513448f3 | ||
|
|
bee61bf398 | ||
|
|
010c31cf10 | ||
|
|
d1643b4506 | ||
|
|
623307b348 | ||
|
|
09e8fca132 | ||
|
|
2c96a26d91 | ||
|
|
f639d2aa57 | ||
|
|
5a68eb345f | ||
|
|
603a3d78fc | ||
|
|
cafc6a7226 | ||
|
|
0b068f6d79 | ||
|
|
ec73c916b7 | ||
|
|
110ccb5587 | ||
|
|
d224ae3eb0 | ||
|
|
dd9c0b3a01 | ||
|
|
d2d711c1f8 | ||
|
|
3dd2492926 | ||
|
|
bc1520ec35 | ||
|
|
3033a82c92 | ||
|
|
bb75be7e8e | ||
|
|
b52f2f5a9e | ||
|
|
5bcfb958f0 | ||
|
|
5f52963ce0 | ||
|
|
3f76be2287 | ||
|
|
92aa65a839 | ||
|
|
bd5337a2c2 | ||
|
|
990d5815f2 | ||
|
|
c1d51cc196 | ||
|
|
f5b871f8f5 | ||
|
|
bc6b84f900 | ||
|
|
5ee79c8148 | ||
|
|
e4706dd3ba | ||
|
|
3c59a870e7 | ||
|
|
ae6ad8870d | ||
|
|
07fed0acce | ||
|
|
7dd99f3d18 | ||
|
|
03d8cfb401 | ||
|
|
ccb981e6ce | ||
|
|
984d5c716b | ||
|
|
43121a08bd | ||
|
|
54c7f16c4c | ||
|
|
6cd2674f2a | ||
|
|
602947a3d7 | ||
|
|
5048963aa2 | ||
|
|
8d16e2b59b | ||
|
|
4accbef6a9 | ||
|
|
2e9d95b96a | ||
|
|
03dfd1b96f | ||
|
|
ee1ccb7f01 | ||
|
|
a6a3544628 | ||
|
|
ca762083b6 | ||
|
|
550ab7de18 | ||
|
|
4919f8991c | ||
|
|
867a8132aa | ||
|
|
c661122bb6 | ||
|
|
80bd8d2039 | ||
|
|
7267496367 | ||
|
|
9dacea11dd | ||
|
|
91c48c50e5 | ||
|
|
67e5ecb931 | ||
|
|
887152a0e2 | ||
|
|
c1a76c4c18 | ||
|
|
8dacbe0fc6 | ||
|
|
a4ead5bd07 | ||
|
|
2f6e36c504 | ||
|
|
bcdb4fd000 | ||
|
|
99395c722d | ||
|
|
e28030576a | ||
|
|
455b0f2015 | ||
|
|
6da0125b7d | ||
|
|
48912bdf55 | ||
|
|
ba70ddfb76 | ||
|
|
f828fcdcab | ||
|
|
c1403207de | ||
|
|
4514bd7e53 | ||
|
|
f2378168c1 | ||
|
|
e0e3a72268 | ||
|
|
c932892dbd | ||
|
|
f03ad7c68f | ||
|
|
d3a26d8022 | ||
|
|
446698d52f | ||
|
|
69faab01b2 | ||
|
|
36d6b6f9ab | ||
|
|
ea70b5fa46 | ||
|
|
927e21e5d1 | ||
|
|
259c0cca69 | ||
|
|
11ce4c2078 | ||
|
|
76ec402fc5 | ||
|
|
df956816b4 | ||
|
|
5d431b3843 | ||
|
|
91ca4f2184 | ||
|
|
b00a0eccc6 | ||
|
|
d675ad18e0 | ||
|
|
031ed8f3cd | ||
|
|
aed78c2d69 | ||
|
|
af3e811f94 | ||
|
|
811c498080 | ||
|
|
e6d58b3b0d | ||
|
|
b7dc671028 | ||
|
|
8418eb2c6b | ||
|
|
5a882a0fae | ||
|
|
be1cbfeb91 | ||
|
|
96c61a073c | ||
|
|
64ef293ce2 | ||
|
|
55953d5b4e | ||
|
|
c63e69db5f | ||
|
|
f9646d9325 | ||
|
|
6bbdbddfaa | ||
|
|
177d46ab8d | ||
|
|
ecd90da554 | ||
|
|
2302dbade6 | ||
|
|
cbf735487f | ||
|
|
a10090b1fb | ||
|
|
babf76371e | ||
|
|
1baac6bb21 | ||
|
|
b1c60065b2 | ||
|
|
af4a2c7184 | ||
|
|
b6f42ecd6d | ||
|
|
8b7d2314b8 | ||
|
|
81adbb3813 | ||
|
|
684198fc08 | ||
|
|
a86431bb6d | ||
|
|
767e3ac659 | ||
|
|
910d6831bf | ||
|
|
c251a48e31 | ||
|
|
8e4b71eb19 | ||
|
|
a2cb219d9b | ||
|
|
f722d4e83e | ||
|
|
ed04f3124f | ||
|
|
08e7a29623 | ||
|
|
09020143e7 | ||
|
|
33e7a10bea | ||
|
|
5e64f6ac88 | ||
|
|
f16aabc136 | ||
|
|
2d00563088 | ||
|
|
124c3a99e6 | ||
|
|
7e135be012 | ||
|
|
d94c67bc7a | ||
|
|
3636bbbf3f | ||
|
|
7c687ee397 | ||
|
|
c3fb033d33 | ||
|
|
8b2257161f | ||
|
|
c4bf73c8d6 | ||
|
|
0db927407d | ||
|
|
9b7223c0e8 | ||
|
|
7b33fc6633 | ||
|
|
8310597944 | ||
|
|
c03ac624fc | ||
|
|
323beb1ab0 | ||
|
|
73490d2923 | ||
|
|
a8e630d271 | ||
|
|
e3e8a162bd | ||
|
|
824ca54478 | ||
|
|
8661bfe4a4 | ||
|
|
4c2c302bfd | ||
|
|
c83f539bba | ||
|
|
8f5849a90c | ||
|
|
b7df5eff19 | ||
|
|
eb4ba70be8 | ||
|
|
136094caf9 | ||
|
|
1fa0256363 | ||
|
|
6de44aee02 | ||
|
|
43facbecda | ||
|
|
0dfca824e2 | ||
|
|
70ee678fef | ||
|
|
680e7cb0da | ||
|
|
498ac97bdd | ||
|
|
3c75072868 | ||
|
|
8e09aa9b54 | ||
|
|
c4fe2322a1 | ||
|
|
43abe14293 | ||
|
|
7146d984d0 | ||
|
|
5495cd749a | ||
|
|
ef93b8ae38 | ||
|
|
2d370aaf5a | ||
|
|
3037309711 | ||
|
|
01c3200258 | ||
|
|
bf9987e05f | ||
|
|
cd61c0833d | ||
|
|
90bdb30449 | ||
|
|
92c2dcaf25 | ||
|
|
a3cd8d151d | ||
|
|
ba455a3630 | ||
|
|
123f47ab39 | ||
|
|
d6503e3e48 | ||
|
|
4f4e5854f2 | ||
|
|
48461122f8 | ||
|
|
aba7652aee | ||
|
|
78fc58cc93 | ||
|
|
3a2ca8d3d6 | ||
|
|
fecc5ec307 | ||
|
|
0665bd443b | ||
|
|
221526c979 | ||
|
|
04369ff4f1 | ||
|
|
e71691d4a5 | ||
|
|
598e7c5637 | ||
|
|
ad73c0e05b | ||
|
|
d4573e8c25 | ||
|
|
1d0def19b1 | ||
|
|
80a1bcf033 | ||
|
|
2f0cbcc565 | ||
|
|
48a2090e01 | ||
|
|
520b978ab0 | ||
|
|
ec42557305 | ||
|
|
bbb71ef891 | ||
|
|
7300c60e73 | ||
|
|
9f90ac80a0 | ||
|
|
f2260212ee | ||
|
|
b94459c761 | ||
|
|
3e26a4d9cc | ||
|
|
6bcfa4980f | ||
|
|
829b6a7d56 | ||
|
|
56bf3fe459 | ||
|
|
63bdb397e7 | ||
|
|
d4b3bf4370 | ||
|
|
7120e95d2a | ||
|
|
f285390f46 | ||
|
|
559864dd01 | ||
|
|
8021e1f269 | ||
|
|
53713acd9a | ||
|
|
5212f6b035 | ||
|
|
ea807239b1 | ||
|
|
2ec534e32d | ||
|
|
ec90efbf4a | ||
|
|
ffa35a9b9b | ||
|
|
2a6629e075 | ||
|
|
59d440b213 | ||
|
|
e6a6043a7a | ||
|
|
ecb1eedcba | ||
|
|
41c8ed2400 |
35
.codecov.yml
Normal file
@@ -0,0 +1,35 @@
|
||||
codecov:
|
||||
notify:
|
||||
require_ci_to_pass: yes
|
||||
|
||||
coverage:
|
||||
precision: 2
|
||||
round: down
|
||||
range: "60...100"
|
||||
|
||||
status:
|
||||
project:
|
||||
default:
|
||||
target: auto
|
||||
threshold: 2%
|
||||
base: auto
|
||||
patch:
|
||||
default:
|
||||
target: auto
|
||||
threshold: 2%
|
||||
base: auto
|
||||
changes: no
|
||||
|
||||
parsers:
|
||||
gcov:
|
||||
branch_detection:
|
||||
conditional: yes
|
||||
loop: yes
|
||||
method: no
|
||||
macro: no
|
||||
|
||||
comment:
|
||||
require_changes: yes
|
||||
layout: "header, diff, files"
|
||||
behavior: default
|
||||
require_changes: no
|
||||
14
.gitattributes
vendored
@@ -3,4 +3,18 @@ src/static/lightbox/* linguist-vendored
|
||||
src/static/typeahead/* linguist-vendored
|
||||
src/static/moment/* linguist-vendored
|
||||
src/static/datetimepicker/* linguist-vendored
|
||||
src/static/colorpicker/* linguist-vendored
|
||||
src/static/fileupload/* linguist-vendored
|
||||
src/static/charts/* linguist-vendored
|
||||
src/pretix/plugins/ticketoutputpdf/static/pretixplugins/ticketoutputpdf/fabric.* linguist-vendored
|
||||
src/pretix/plugins/ticketoutputpdf/static/pretixplugins/ticketoutputpdf/pdf.* linguist-vendored
|
||||
|
||||
# Denote all files that are truly binary and should not be modified.
|
||||
*.eot binary
|
||||
*.otf binary
|
||||
*.ttf binary
|
||||
*.woff binary
|
||||
*.zip binary
|
||||
*.png binary
|
||||
*.gif binary
|
||||
*.jpg binary
|
||||
|
||||
2
.gitignore
vendored
@@ -21,4 +21,6 @@ pretixeu/
|
||||
local/
|
||||
.project
|
||||
.pydevproject
|
||||
.DS_Store
|
||||
|
||||
|
||||
|
||||
@@ -2,11 +2,31 @@ before_script:
|
||||
tests:
|
||||
stage: test
|
||||
script:
|
||||
- virtualenv-3.4 env
|
||||
- virtualenv env
|
||||
- source env/bin/activate
|
||||
- pip install -U pip wheel setuptools
|
||||
- XDG_CACHE_HOME=/cache bash .travis.sh style
|
||||
- XDG_CACHE_HOME=/cache bash .travis.sh tests
|
||||
- XDG_CACHE_HOME=/cache bash .travis.sh doctests
|
||||
tags:
|
||||
- python3
|
||||
pypi:
|
||||
stage: release
|
||||
script:
|
||||
- cp /keys/.pypirc ~/.pypirc
|
||||
- virtualenv env
|
||||
- source env/bin/activate
|
||||
- pip install -U pip wheel setuptools
|
||||
- XDG_CACHE_HOME=/cache pip3 install -Ur src/requirements.txt -r src/requirements/dev.txt -r src/requirements/py34.txt
|
||||
- cd src
|
||||
- python setup.py sdist upload
|
||||
- python setup.py bdist_wheel upload
|
||||
tags:
|
||||
- python3
|
||||
only:
|
||||
- release
|
||||
artifacts:
|
||||
paths:
|
||||
- src/dist/
|
||||
stages:
|
||||
- test
|
||||
- build
|
||||
- release
|
||||
|
||||
31
.travis.sh
@@ -4,11 +4,21 @@ set -x
|
||||
|
||||
echo "Executing job $1"
|
||||
|
||||
if [ "$PRETIX_CONFIG_FILE" == "tests/travis_mysql.cfg" ]; then
|
||||
mysql -u root -e 'CREATE DATABASE pretix DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci;'
|
||||
pip3 install -Ur src/requirements/mysql.txt
|
||||
fi
|
||||
|
||||
if [ "$PRETIX_CONFIG_FILE" == "tests/travis_postgres.cfg" ]; then
|
||||
psql -c 'create database travis_ci_test;' -U postgres
|
||||
pip3 install -Ur src/requirements/postgres.txt
|
||||
fi
|
||||
|
||||
if [ "$1" == "style" ]; then
|
||||
XDG_CACHE_HOME=/cache pip3 install -Ur src/requirements.txt -r src/requirements/dev.txt -r src/requirements/py34.txt
|
||||
cd src
|
||||
flake8 .
|
||||
isort -c -rc .
|
||||
isort -c -rc -df .
|
||||
fi
|
||||
if [ "$1" == "doctests" ]; then
|
||||
XDG_CACHE_HOME=/cache pip3 install -Ur doc/requirements.txt -r src/requirements/py34.txt
|
||||
@@ -20,12 +30,27 @@ if [ "$1" == "tests" ]; then
|
||||
cd src
|
||||
python manage.py check
|
||||
make all compress
|
||||
coverage run -m py.test --rerun 5 tests && coverage report
|
||||
py.test --rerun 5 tests
|
||||
fi
|
||||
if [ "$1" == "tests-cov" ]; then
|
||||
pip3 install -r src/requirements.txt -Ur src/requirements/dev.txt -r src/requirements/py34.txt
|
||||
cd src
|
||||
python manage.py check
|
||||
make all compress
|
||||
coverage run -m py.test --rerun 5 tests && coveralls
|
||||
coverage run -m py.test --rerun 5 tests && codecov
|
||||
fi
|
||||
if [ "$1" == "plugins" ]; then
|
||||
pip3 install -r src/requirements.txt -Ur src/requirements/dev.txt -r src/requirements/py34.txt
|
||||
cd src
|
||||
python setup.py develop
|
||||
make all compress
|
||||
|
||||
pushd ~
|
||||
git clone --depth 1 https://github.com/pretix/pretix-cartshare.git
|
||||
cd pretix-cartshare
|
||||
python setup.py develop
|
||||
make
|
||||
py.test --rerun 5 tests
|
||||
popd
|
||||
|
||||
fi
|
||||
|
||||
45
.travis.yml
@@ -1,15 +1,40 @@
|
||||
language: python
|
||||
sudo: false
|
||||
python:
|
||||
- "3.4"
|
||||
install:
|
||||
- pip install -U pip wheel setuptools==28.6.1
|
||||
- pip install -U pip wheel setuptools==28.6.1
|
||||
script:
|
||||
- bash .travis.sh $JOB
|
||||
- bash .travis.sh $JOB
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/.cache/pip
|
||||
env:
|
||||
- JOB=style
|
||||
- JOB=doctests
|
||||
- JOB=tests-cov
|
||||
directories:
|
||||
- $HOME/.cache/pip
|
||||
services:
|
||||
- mysql
|
||||
- postgresql
|
||||
matrix:
|
||||
include:
|
||||
- python: 3.4
|
||||
env: JOB=tests PRETIX_CONFIG_FILE=tests/sqlite.cfg
|
||||
- python: 3.5
|
||||
env: JOB=tests PRETIX_CONFIG_FILE=tests/sqlite.cfg
|
||||
- python: 3.6
|
||||
env: JOB=tests PRETIX_CONFIG_FILE=tests/sqlite.cfg
|
||||
- python: 3.4
|
||||
env: JOB=tests PRETIX_CONFIG_FILE=tests/travis_mysql.cfg
|
||||
- python: 3.5
|
||||
env: JOB=tests PRETIX_CONFIG_FILE=tests/travis_mysql.cfg
|
||||
- python: 3.6
|
||||
env: JOB=tests PRETIX_CONFIG_FILE=tests/travis_mysql.cfg
|
||||
- python: 3.4
|
||||
env: JOB=tests PRETIX_CONFIG_FILE=tests/travis_postgres.cfg
|
||||
- python: 3.5
|
||||
env: JOB=tests PRETIX_CONFIG_FILE=tests/travis_postgres.cfg
|
||||
- python: 3.6
|
||||
env: JOB=tests PRETIX_CONFIG_FILE=tests/travis_postgres.cfg
|
||||
- python: 3.6
|
||||
env: JOB=style
|
||||
- python: 3.6
|
||||
env: JOB=plugins
|
||||
- python: 3.6
|
||||
env: JOB=tests-cov
|
||||
addons:
|
||||
postgresql: "9.4"
|
||||
|
||||
18
AUTHORS
@@ -3,21 +3,35 @@ people who have submitted patches, reported bugs, added translations, helped
|
||||
answer newbie questions, improved the documentation, and generally made pretix
|
||||
an awesome project. Thank you all!
|
||||
|
||||
Adam K. Sumner <asumner101@gmail.com>
|
||||
Ahrdie <robert.deppe@me.com>
|
||||
Alexander Brock <Brock.Alexander@web.de>
|
||||
Ben Oswald
|
||||
Brandon Pineda
|
||||
Bolutife Lawrence
|
||||
Christian Franke <nobody@nowhere.ws>
|
||||
Christopher Dambamuromo <me@chridam.com>
|
||||
chotee <chotee@openended.eu>
|
||||
Cpt. Foo
|
||||
Daniel Rosenblüh
|
||||
Enrique Saez
|
||||
Flavia Bastos
|
||||
informancer <informancer@web.de>
|
||||
Jason Estibeiro <jasonestibeiro@live.com>
|
||||
Jakob Schnell <github@ezelo.de>
|
||||
Jan Felix Wiebe <git@jfwie.be>
|
||||
Jan Weiß
|
||||
Jason Estibeiro <jasonestibeiro@live.com>
|
||||
jlwt90
|
||||
Jonas Große Sundrup <cherti@letopolis.de>
|
||||
Kevin Nelson
|
||||
Leah Oswald
|
||||
Lukas Martini
|
||||
Nathan Mattes
|
||||
Nicole Klünder
|
||||
Marc-Pascal Clement
|
||||
Martin Gross <martin@pc-coholic.de>
|
||||
Raphael Michel <mail@raphaelmichel.de>
|
||||
Team MRMCD
|
||||
Tobias Kunze <rixx@cutebit.de>
|
||||
Oliver Knapp <github@oliverknapp.de>
|
||||
Vishal Sodani <vishalsodani@rediffmail.com>
|
||||
Jan Felix Wiebe <git@jfwie.be>
|
||||
|
||||
65
Dockerfile
@@ -1,50 +1,43 @@
|
||||
FROM debian:jessie
|
||||
FROM python:3.6
|
||||
|
||||
RUN apt-get update && apt-get install -y python3 git python3-pip \
|
||||
libxml2-dev libxslt1-dev python-dev python-virtualenv locales libffi-dev \
|
||||
build-essential python3-dev zlib1g-dev libssl-dev gettext \
|
||||
libpq-dev libmysqlclient-dev libmemcached-dev libjpeg-dev \
|
||||
aqbanking-tools supervisor nginx sudo \
|
||||
--no-install-recommends
|
||||
|
||||
WORKDIR /
|
||||
|
||||
RUN dpkg-reconfigure locales && \
|
||||
RUN apt-get update && \
|
||||
apt-get install -y git libxml2-dev libxslt1-dev python-dev python-virtualenv locales \
|
||||
libffi-dev build-essential python3-dev zlib1g-dev libssl-dev gettext libpq-dev \
|
||||
libmysqlclient-dev libmemcached-dev libjpeg-dev supervisor nginx sudo \
|
||||
--no-install-recommends && \
|
||||
apt-get clean && \
|
||||
rm -rf /var/lib/apt/lists/* && \
|
||||
dpkg-reconfigure locales && \
|
||||
locale-gen C.UTF-8 && \
|
||||
/usr/sbin/update-locale LANG=C.UTF-8
|
||||
ENV LC_ALL C.UTF-8
|
||||
/usr/sbin/update-locale LANG=C.UTF-8 && \
|
||||
mkdir /etc/pretix && \
|
||||
mkdir /data && \
|
||||
useradd -ms /bin/bash -d /pretix -u 15371 pretixuser && \
|
||||
echo 'pretixuser ALL=(ALL) NOPASSWD: /usr/bin/supervisord' >> /etc/sudoers && \
|
||||
mkdir /static
|
||||
|
||||
RUN apt-get clean && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
RUN useradd -ms /bin/bash -d /pretix -u 15371 pretixuser
|
||||
RUN echo 'pretixuser ALL=(ALL) NOPASSWD: /usr/bin/supervisord' >> /etc/sudoers
|
||||
|
||||
RUN mkdir /etc/pretix
|
||||
RUN mkdir /data
|
||||
VOLUME /etc/pretix
|
||||
ENV LC_ALL=C.UTF-8 \
|
||||
DJANGO_SETTINGS_MODULE=production_settings
|
||||
|
||||
COPY deployment/docker/pretix.bash /usr/local/bin/pretix
|
||||
RUN chmod +x /usr/local/bin/pretix
|
||||
COPY deployment/docker/supervisord.conf /etc/supervisord.conf
|
||||
|
||||
COPY deployment/docker/nginx.conf /etc/nginx/nginx.conf
|
||||
RUN rm /etc/nginx/sites-enabled/default
|
||||
|
||||
COPY deployment/docker/production_settings.py /pretix/src/production_settings.py
|
||||
COPY src /pretix/src
|
||||
WORKDIR /pretix/src
|
||||
ADD deployment/docker/production_settings.py /pretix/src/production_settings.py
|
||||
ENV DJANGO_SETTINGS_MODULE production_settings
|
||||
|
||||
RUN pip3 install -U pip wheel setuptools
|
||||
RUN pip3 install -r requirements.txt -r requirements/mysql.txt -r requirements/postgres.txt \
|
||||
-r requirements/memcached.txt -r requirements/redis.txt \
|
||||
-r requirements/py34.txt gunicorn
|
||||
RUN chmod +x /usr/local/bin/pretix && \
|
||||
rm /etc/nginx/sites-enabled/default && \
|
||||
pip3 install -U pip wheel setuptools && \
|
||||
cd /pretix/src && \
|
||||
rm -f pretix.cfg && \
|
||||
pip3 install -r requirements.txt -r requirements/mysql.txt -r requirements/postgres.txt \
|
||||
-r requirements/memcached.txt -r requirements/redis.txt gunicorn && \
|
||||
mkdir -p data && \
|
||||
chown -R pretixuser:pretixuser /pretix /data data && \
|
||||
sudo -u pretixuser make production
|
||||
|
||||
RUN mkdir /static && chown -R pretixuser:pretixuser /static /pretix /data
|
||||
USER pretixuser
|
||||
RUN make production
|
||||
|
||||
VOLUME ["/etc/pretix", "/data"]
|
||||
EXPOSE 80
|
||||
|
||||
ENTRYPOINT ["pretix"]
|
||||
CMD ["all"]
|
||||
|
||||
38
README.rst
@@ -10,25 +10,30 @@ pretix
|
||||
.. image:: https://travis-ci.org/pretix/pretix.svg?branch=master
|
||||
:target: https://travis-ci.org/pretix/pretix
|
||||
|
||||
.. image:: https://coveralls.io/repos/github/pretix/pretix/badge.svg?branch=master
|
||||
:target: https://coveralls.io/r/pretix/pretix
|
||||
.. image:: https://codecov.io/gh/pretix/pretix/branch/master/graph/badge.svg
|
||||
:target: https://codecov.io/gh/pretix/pretix
|
||||
|
||||
|
||||
Reinventing ticket presales, one bit at a time.
|
||||
|
||||
Project status
|
||||
--------------
|
||||
Most features are present and sufficiently stable. pretix has been in use for multiple event and
|
||||
sold a few thousand tickets so far. There is still a bunch of features to come and there surely is
|
||||
still a bunch of bugs in there, but we consider it stable enough that we use it in production ourselves.
|
||||
Reinventing ticket presales, one ticket at a time.
|
||||
|
||||
If you deploy and use pretix, there will be a safe upgrade path for all changes to come. We're planning
|
||||
on an 1.0 release in late 2016 or early 2017. Until then, we take the liberty of changing the code as we
|
||||
like, but we try to keep the changes to documented APIs as small as possible. If you want to use pretix
|
||||
in production or develop a plugin now, I invite you to send me an email so that I can notify you of changes
|
||||
and bugs that require your attention.
|
||||
Project status & release cycle
|
||||
------------------------------
|
||||
|
||||
Since very recently we now have an `installation guide`_ in our documentation.
|
||||
While there is always a lot to do and improve on, pretix by now has been in use for more than a dozen
|
||||
conferences that sold over ten thousand tickets combined without major problems. We therefore think of
|
||||
pretix as being stable and ready to use.
|
||||
|
||||
If you want to use or extend pretix, we strongly recommend to follow our `blog`_. We will announce all
|
||||
releases there. You can always find the latest stable version on PyPI or in the ``release/X.Y`` branch of
|
||||
this repository. The ``master`` branch contains a development version that we also try to keep stable in
|
||||
the sense that it does not break your data, but its APIs might change without prior notice.
|
||||
|
||||
To get started using pretix on your own server, look at the `installation guide`_ in our documentation.
|
||||
|
||||
This project is 100 percent free and open source software. If you are interested in commercial support,
|
||||
hosting services or supporting this project financially, please go to `pretix.eu`_ or contact us at
|
||||
support@pretix.eu.
|
||||
|
||||
Contributing
|
||||
------------
|
||||
@@ -43,10 +48,7 @@ See the LICENSE file for the complete license text.
|
||||
This project is maintained by Raphael Michel <mail@raphaelmichel.de>. See the
|
||||
AUTHORS file for a list of all the awesome folks who contributed to this project.
|
||||
|
||||
This project is 100 percent free and open source software. If you are interested in
|
||||
commercial support, hosting services or supporting this project financially, please
|
||||
go to `pretix.eu`_ or contact Raphael directly.
|
||||
|
||||
.. _installation guide: https://docs.pretix.eu/en/latest/admin/installation/index.html
|
||||
.. _developer documentation: https://docs.pretix.eu/en/latest/development/index.html
|
||||
.. _pretix.eu: https://pretix.eu
|
||||
.. _blog: https://pretix.eu/about/en/blog/
|
||||
|
||||
@@ -22,9 +22,11 @@ http {
|
||||
|
||||
include /etc/nginx/mime.types;
|
||||
default_type application/octet-stream;
|
||||
add_header X-Content-Type-Options nosniff;
|
||||
|
||||
access_log /var/log/nginx/access.log private;
|
||||
error_log /var/log/nginx/error.log;
|
||||
add_header Referrer-Policy same-origin;
|
||||
|
||||
gzip on;
|
||||
gzip_disable "msie6";
|
||||
@@ -48,8 +50,16 @@ http {
|
||||
expires 7d;
|
||||
access_log off;
|
||||
}
|
||||
location ^~ /media/cachedfiles {
|
||||
deny all;
|
||||
return 404;
|
||||
}
|
||||
location ^~ /media/invoices {
|
||||
deny all;
|
||||
return 404;
|
||||
}
|
||||
location /static/ {
|
||||
alias /static/;
|
||||
alias /pretix/src/pretix/static.dist/;
|
||||
access_log off;
|
||||
expires 365d;
|
||||
add_header Cache-Control "public";
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
from pretix.settings import *
|
||||
|
||||
|
||||
LOGGING['handlers']['mail_admins']['include_html'] = True
|
||||
STATIC_ROOT = '/static'
|
||||
STATICFILES_STORAGE = 'django.contrib.staticfiles.storage.ManifestStaticFilesStorage'
|
||||
|
||||
160
doc/_templates/index.html
vendored
Normal file
@@ -0,0 +1,160 @@
|
||||
{% extends "layout.html" %}
|
||||
{% set title = 'Overview' %}
|
||||
{% block body %}
|
||||
<h1>Welcome to pretix' documentation!</h1>
|
||||
<p>
|
||||
We work hard to make this website contain all information that you need to use, run, understand, and improve
|
||||
pretix. Of course, this documentation will never be perfect or complete, but if there is anything unclear
|
||||
or anything specific that you miss here, that's a bug and we'd be happy if you'd
|
||||
<a href="https://github.com/pretix/pretix/issues/new">let us know</a>.
|
||||
</p>
|
||||
|
||||
<h2>Documentation structure</h2>
|
||||
|
||||
<div class="sectionbox">
|
||||
<div class="icon">
|
||||
<a href="user/index.html">
|
||||
<span class="fa fa-user fa-fw"></span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="text">
|
||||
<a href="user/index.html">
|
||||
<strong>User Guide</strong>
|
||||
</a>
|
||||
<p>Go here to find information on how to configure and use pretix as an event organizer.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sectionbox">
|
||||
<div class="icon">
|
||||
<a href="admin/index.html">
|
||||
<span class="fa fa-server fa-fw"></span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="text">
|
||||
<a href="admin/index.html">
|
||||
<strong>Administrator docs</strong>
|
||||
</a>
|
||||
<p>Find out how to install pretix on your own server and how to maintain an installation of pretix.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
<div class="sectionbox">
|
||||
<div class="icon">
|
||||
<a href="api/index.html">
|
||||
<span class="fa fa-plug fa-fw"></span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="text">
|
||||
<a href="api/index.html">
|
||||
<strong>REST API</strong>
|
||||
</a>
|
||||
<p>
|
||||
Documentation and reference of the RESTful API exposed by pretix for interaction with external
|
||||
components.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sectionbox">
|
||||
<div class="icon">
|
||||
<a href="development/index.html">
|
||||
<span class="fa fa-wrench fa-fw"></span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="text">
|
||||
<a href="development/index.html">
|
||||
<strong>Developer docs</strong>
|
||||
</a>
|
||||
<p>Get information on how to contribute to pretix itself and how to build plugins that interact with
|
||||
pretix.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
<div class="sectionbox">
|
||||
<div class="icon">
|
||||
<a href="plugins/index.html">
|
||||
<span class="fa fa-puzzle-piece fa-fw"></span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="text">
|
||||
<a href="plugins/index.html">
|
||||
<strong>Plugin docs</strong>
|
||||
</a>
|
||||
<p>Documentation and details on plugins that ship with pretix or are officially supported.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sectionbox">
|
||||
<div class="icon">
|
||||
<a href="contents.html">
|
||||
<span class="fa fa-list fa-fw"></span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="text">
|
||||
<a href="contents.html">
|
||||
<strong>Table of contents</strong>
|
||||
</a>
|
||||
<p>Detailled overview of everything contained in this documentation.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
|
||||
<h2>Useful links</h2>
|
||||
|
||||
<div class="sectionbox">
|
||||
<div class="icon">
|
||||
<a href="https://pretix.eu" target="_blank">
|
||||
<span class="fa fa-globe fa-fw"></span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="text">
|
||||
<a href="https://pretix.eu" target="_blank">
|
||||
<strong>Project website</strong>
|
||||
</a>
|
||||
<p>pretix.eu is the central entry-point to the pretix project and also the home of the commercial hosting
|
||||
service available.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sectionbox">
|
||||
<div class="icon">
|
||||
<a href="https://github.com/pretix/pretix" target="_blank">
|
||||
<span class="fa fa-github fa-fw"></span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="text">
|
||||
<a href="https://github.com/pretix/pretix" target="_blank">
|
||||
<strong>GitHub repository</strong>
|
||||
</a>
|
||||
<p>Our main source code repository contains all code that is part of pretix as well as some plugins and the
|
||||
source for this documentation.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
<div class="sectionbox">
|
||||
<div class="icon">
|
||||
<a href="https://pretix.eu/about/en/blog/" target="_blank">
|
||||
<span class="fa fa-newspaper-o fa-fw"></span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="text">
|
||||
<a href="https://pretix.eu/about/en/blog/" target="_blank">
|
||||
<strong>Project blog</strong>
|
||||
</a>
|
||||
<p>This important information source contains all release notes for all stable releases of pretix as well as
|
||||
general news on pretix as a project.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sectionbox">
|
||||
<div class="icon">
|
||||
<a href="https://twitter.com/pretixeu" target="_blank">
|
||||
<span class="fa fa-twitter fa-fw"></span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="text">
|
||||
<a href="https://twitter.com/pretixeu" target="_blank">
|
||||
<strong>Twitter</strong>
|
||||
</a>
|
||||
<p>Keep in touch and stay up to date by following our project account on Twitter.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
|
||||
{% endblock %}
|
||||
16
doc/_themes/pretix_theme/__init__.py
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
"""pretix sphinx theme.
|
||||
|
||||
Based on sphinx-rtd-theme
|
||||
Based on https://github.com/ryan-roemer/sphinx-bootstrap-theme.
|
||||
|
||||
"""
|
||||
import os
|
||||
|
||||
__version__ = '0.1.0'
|
||||
__version_full__ = __version__
|
||||
|
||||
|
||||
def get_html_theme_path():
|
||||
"""Return list of HTML theme paths."""
|
||||
cur_dir = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
|
||||
return cur_dir
|
||||
82
doc/_themes/pretix_theme/breadcrumbs.html
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
{# Support for Sphinx 1.3+ page_source_suffix, but don't break old builds. #}
|
||||
|
||||
{% if page_source_suffix %}
|
||||
{% set suffix = page_source_suffix %}
|
||||
{% else %}
|
||||
{% set suffix = source_suffix %}
|
||||
{% endif %}
|
||||
|
||||
{% if meta is defined and meta is not none %}
|
||||
{% set check_meta = True %}
|
||||
{% else %}
|
||||
{% set check_meta = False %}
|
||||
{% endif %}
|
||||
|
||||
{% if check_meta and 'github_url' in meta %}
|
||||
{% set display_github = True %}
|
||||
{% endif %}
|
||||
|
||||
{% if check_meta and 'bitbucket_url' in meta %}
|
||||
{% set display_bitbucket = True %}
|
||||
{% endif %}
|
||||
|
||||
{% if check_meta and 'gitlab_url' in meta %}
|
||||
{% set display_gitlab = True %}
|
||||
{% endif %}
|
||||
|
||||
<div role="navigation" aria-label="breadcrumbs navigation">
|
||||
|
||||
<ul class="wy-breadcrumbs">
|
||||
{% block breadcrumbs %}
|
||||
<li><a href="{{ pathto(master_doc) }}">{{ _('Docs') }}</a> »</li>
|
||||
{% for doc in parents %}
|
||||
<li><a href="{{ doc.link|e }}">{{ doc.title }}</a> »</li>
|
||||
{% endfor %}
|
||||
<li>{{ title }}</li>
|
||||
{% endblock %}
|
||||
{% block breadcrumbs_aside %}
|
||||
<li class="wy-breadcrumbs-aside">
|
||||
{% if pagename != "search" %}
|
||||
{% if display_github %}
|
||||
{% if check_meta and 'github_url' in meta %}
|
||||
<!-- User defined GitHub URL -->
|
||||
<a href="{{ meta['github_url'] }}" class="fa fa-github"> {{ _('Edit on GitHub') }}</a>
|
||||
{% else %}
|
||||
<a href="https://{{ github_host|default("github.com") }}/{{ github_user }}/{{ github_repo }}/blob/{{ github_version }}{{ conf_py_path }}{{ pagename }}{{ suffix }}" class="fa fa-github"> {{ _('Edit on GitHub') }}</a>
|
||||
{% endif %}
|
||||
{% elif display_bitbucket %}
|
||||
{% if check_meta and 'bitbucket_url' in meta %}
|
||||
<!-- User defined Bitbucket URL -->
|
||||
<a href="{{ meta['bitbucket_url'] }}" class="fa fa-bitbucket"> {{ _('Edit on Bitbucket') }}</a>
|
||||
{% else %}
|
||||
<a href="https://bitbucket.org/{{ bitbucket_user }}/{{ bitbucket_repo }}/src/{{ bitbucket_version}}{{ conf_py_path }}{{ pagename }}{{ suffix }}" class="fa fa-bitbucket"> {{ _('Edit on Bitbucket') }}</a>
|
||||
{% endif %}
|
||||
{% elif display_gitlab %}
|
||||
{% if check_meta and 'gitlab_url' in meta %}
|
||||
<!-- User defined GitLab URL -->
|
||||
<a href="{{ meta['gitlab_url'] }}" class="fa fa-gitlab"> {{ _('Edit on GitLab') }}</a>
|
||||
{% else %}
|
||||
<a href="https://{{ gitlab_host|default("gitlab.com") }}/{{ gitlab_user }}/{{ gitlab_repo }}/blob/{{ gitlab_version }}{{ conf_py_path }}{{ pagename }}{{ suffix }}" class="fa fa-gitlab"> {{ _('Edit on GitLab') }}</a>
|
||||
{% endif %}
|
||||
{% elif show_source and source_url_prefix %}
|
||||
<a href="{{ source_url_prefix }}{{ pagename }}{{ suffix }}">{{ _('View page source') }}</a>
|
||||
{% elif show_source and has_source and sourcename %}
|
||||
<a href="{{ pathto('_sources/' + sourcename, true)|e }}" rel="nofollow"> {{ _('View page source') }}</a>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</li>
|
||||
{% endblock %}
|
||||
</ul>
|
||||
|
||||
{% if (theme_prev_next_buttons_location == 'top' or theme_prev_next_buttons_location == 'both') and (next or prev) %}
|
||||
<div class="rst-breadcrumbs-buttons" role="navigation" aria-label="breadcrumb navigation">
|
||||
{% if next %}
|
||||
<a href="{{ next.link|e }}" class="btn btn-neutral float-right" title="{{ next.title|striptags|e }}" accesskey="n">Next <span class="fa fa-arrow-circle-right"></span></a>
|
||||
{% endif %}
|
||||
{% if prev %}
|
||||
<a href="{{ prev.link|e }}" class="btn btn-neutral" title="{{ prev.title|striptags|e }}" accesskey="p"><span class="fa fa-arrow-circle-left"></span> Previous</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
<hr/>
|
||||
</div>
|
||||
52
doc/_themes/pretix_theme/footer.html
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
<footer>
|
||||
{% if (theme_prev_next_buttons_location == 'bottom' or theme_prev_next_buttons_location == 'both') and (next or prev) %}
|
||||
<div class="rst-footer-buttons" role="navigation" aria-label="footer navigation">
|
||||
{% if next %}
|
||||
<a href="{{ next.link|e }}" class="btn btn-neutral float-right" title="{{ next.title|striptags|e }}" accesskey="n" rel="next">{{ _('Next') }} <span class="fa fa-arrow-circle-right"></span></a>
|
||||
{% endif %}
|
||||
{% if prev %}
|
||||
<a href="{{ prev.link|e }}" class="btn btn-neutral" title="{{ prev.title|striptags|e }}" accesskey="p" rel="prev"><span class="fa fa-arrow-circle-left"></span> {{ _('Previous') }}</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<hr/>
|
||||
|
||||
<div role="contentinfo">
|
||||
<p>
|
||||
{%- if show_copyright %}
|
||||
{%- if hasdoc('copyright') %}
|
||||
{% trans path=pathto('copyright'), copyright=copyright|e %}© <a href="{{ path }}">Copyright</a> {{ copyright }}.{% endtrans %}
|
||||
{%- else %}
|
||||
{% trans copyright=copyright|e %}© Copyright {{ copyright }}.{% endtrans %}
|
||||
{%- endif %}
|
||||
{%- endif %}
|
||||
|
||||
{%- if build_id and build_url %}
|
||||
{% trans build_url=build_url, build_id=build_id %}
|
||||
<span class="build">
|
||||
Build
|
||||
<a href="{{ build_url }}">{{ build_id }}</a>.
|
||||
</span>
|
||||
{% endtrans %}
|
||||
{%- elif commit %}
|
||||
{% trans commit=commit %}
|
||||
<span class="commit">
|
||||
Revision <code>{{ commit }}</code>.
|
||||
</span>
|
||||
{% endtrans %}
|
||||
{%- elif last_updated %}
|
||||
{% trans last_updated=last_updated|e %}Last updated on {{ last_updated }}.{% endtrans %}
|
||||
{%- endif %}
|
||||
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{%- if show_sphinx %}
|
||||
<small>{% trans %}Built with <a href="http://sphinx-doc.org/">Sphinx</a> using a theme that is based on a <a href="https://github.com/snide/sphinx_rtd_theme">theme</a> provided by <a href="https://readthedocs.org">Read the Docs</a>{% endtrans %}.</small>
|
||||
{%- endif %}
|
||||
|
||||
{%- block extrafooter %} {% endblock %}
|
||||
|
||||
</footer>
|
||||
|
||||
211
doc/_themes/pretix_theme/layout.html
vendored
Normal file
@@ -0,0 +1,211 @@
|
||||
{# TEMPLATE VAR SETTINGS #}
|
||||
{%- set url_root = pathto('', 1) %}
|
||||
{%- if url_root == '#' %}{% set url_root = '' %}{% endif %}
|
||||
{%- if not embedded and docstitle %}
|
||||
{%- set titlesuffix = " — "|safe + docstitle|e %}
|
||||
{%- else %}
|
||||
{%- set titlesuffix = "" %}
|
||||
{%- endif %}
|
||||
|
||||
<!DOCTYPE html>
|
||||
<!--[if IE 8]><html class="no-js lt-ie9" lang="en" > <![endif]-->
|
||||
<!--[if gt IE 8]><!--> <html class="no-js" lang="en" > <!--<![endif]-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
{{ metatags }}
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
{% block htmltitle %}
|
||||
<title>{{ title|striptags|e }}{{ titlesuffix }}</title>
|
||||
{% endblock %}
|
||||
|
||||
{# FAVICON #}
|
||||
{% if favicon %}
|
||||
<link rel="shortcut icon" href="{{ pathto('_static/' + favicon, 1) }}"/>
|
||||
{% endif %}
|
||||
{# CANONICAL URL #}
|
||||
{% if theme_canonical_url %}
|
||||
<link rel="canonical" href="{{ theme_canonical_url }}{{ pagename }}.html"/>
|
||||
{% endif %}
|
||||
|
||||
{# CSS #}
|
||||
|
||||
{# OPENSEARCH #}
|
||||
{% if not embedded %}
|
||||
{% if use_opensearch %}
|
||||
<link rel="search" type="application/opensearchdescription+xml" title="{% trans docstitle=docstitle|e %}Search within {{ docstitle }}{% endtrans %}" href="{{ pathto('_static/opensearch.xml', 1) }}"/>
|
||||
{% endif %}
|
||||
|
||||
{% endif %}
|
||||
|
||||
{# RTD hosts this file, so just load on non RTD builds #}
|
||||
<link rel="stylesheet" href="{{ pathto('_static/' + style, 1) }}" type="text/css" />
|
||||
|
||||
{% for cssfile in css_files %}
|
||||
<link rel="stylesheet" href="{{ pathto(cssfile, 1) }}" type="text/css" />
|
||||
{% endfor %}
|
||||
|
||||
{% for cssfile in extra_css_files %}
|
||||
<link rel="stylesheet" href="{{ pathto(cssfile, 1) }}" type="text/css" />
|
||||
{% endfor %}
|
||||
|
||||
{%- block linktags %}
|
||||
{%- if hasdoc('about') %}
|
||||
<link rel="author" title="{{ _('About these documents') }}"
|
||||
href="{{ pathto('about') }}"/>
|
||||
{%- endif %}
|
||||
{%- if hasdoc('genindex') %}
|
||||
<link rel="index" title="{{ _('Index') }}"
|
||||
href="{{ pathto('genindex') }}"/>
|
||||
{%- endif %}
|
||||
{%- if hasdoc('search') %}
|
||||
<link rel="search" title="{{ _('Search') }}" href="{{ pathto('search') }}"/>
|
||||
{%- endif %}
|
||||
{%- if hasdoc('copyright') %}
|
||||
<link rel="copyright" title="{{ _('Copyright') }}" href="{{ pathto('copyright') }}"/>
|
||||
{%- endif %}
|
||||
<link rel="top" title="{{ docstitle|e }}" href="{{ pathto('index') }}"/>
|
||||
{%- if parents %}
|
||||
<link rel="up" title="{{ parents[-1].title|striptags|e }}" href="{{ parents[-1].link|e }}"/>
|
||||
{%- endif %}
|
||||
{%- if next %}
|
||||
<link rel="next" title="{{ next.title|striptags|e }}" href="{{ next.link|e }}"/>
|
||||
{%- endif %}
|
||||
{%- if prev %}
|
||||
<link rel="prev" title="{{ prev.title|striptags|e }}" href="{{ prev.link|e }}"/>
|
||||
{%- endif %}
|
||||
{%- endblock %}
|
||||
{%- block extrahead %} {% endblock %}
|
||||
|
||||
{# Keep modernizr in head - http://modernizr.com/docs/#installing #}
|
||||
<script src="{{ pathto('_static/js/modernizr.min.js', 1) }}"></script>
|
||||
|
||||
</head>
|
||||
|
||||
<body class="wy-body-for-nav" role="document">
|
||||
|
||||
{% block extrabody %} {% endblock %}
|
||||
<div class="wy-grid-for-nav">
|
||||
|
||||
{# SIDE NAV, TOGGLES ON MOBILE #}
|
||||
<nav data-toggle="wy-nav-shift" class="wy-nav-side">
|
||||
<div class="wy-side-scroll">
|
||||
<div class="wy-side-nav-search">
|
||||
{% block sidebartitle %}
|
||||
|
||||
{% if logo and theme_logo_only %}
|
||||
<a href="{{ pathto('index') }}">
|
||||
{% else %}
|
||||
<a href="{{ pathto('index') }}" class="icon icon-home"> {{ project }}
|
||||
{% endif %}
|
||||
|
||||
{% if logo %}
|
||||
{# Not strictly valid HTML, but it's the only way to display/scale it properly, without weird scripting or heaps of work #}
|
||||
<img src="{{ pathto('_static/' + logo, 1) }}" class="logo" />
|
||||
{% endif %}
|
||||
</a>
|
||||
|
||||
{% include "searchbox.html" %}
|
||||
|
||||
{% endblock %}
|
||||
</div>
|
||||
|
||||
<div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="main navigation">
|
||||
{% block menu %}
|
||||
{#
|
||||
The singlehtml builder doesn't handle this toctree call when the
|
||||
toctree is empty. Skip building this for now.
|
||||
#}
|
||||
{% if 'singlehtml' not in builder %}
|
||||
{% set global_toc = toctree(maxdepth=theme_navigation_depth|int, collapse=theme_collapse_navigation, includehidden=True) %}
|
||||
{% endif %}
|
||||
{% if global_toc %}
|
||||
{{ global_toc }}
|
||||
{% else %}
|
||||
<!-- Local TOC -->
|
||||
<div class="local-toc">{{ toc }}</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
</div>
|
||||
|
||||
{% if theme_display_version %}
|
||||
{%- set nav_version = version %}
|
||||
{% if READTHEDOCS and current_version %}
|
||||
{%- set nav_version = current_version %}
|
||||
{% endif %}
|
||||
{% if nav_version %}
|
||||
<div class="version">
|
||||
{{ nav_version }}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<section data-toggle="wy-nav-shift" class="wy-nav-content-wrap">
|
||||
|
||||
{# MOBILE NAV, TRIGGLES SIDE NAV ON TOGGLE #}
|
||||
<nav class="wy-nav-top" role="navigation" aria-label="top navigation">
|
||||
{% block mobile_nav %}
|
||||
<i data-toggle="wy-nav-top" class="fa fa-bars"></i>
|
||||
<a href="{{ pathto('index') }}">{{ project }}</a>
|
||||
{% endblock %}
|
||||
</nav>
|
||||
|
||||
|
||||
{# PAGE CONTENT #}
|
||||
<div class="wy-nav-content">
|
||||
<div class="rst-content">
|
||||
{% include "breadcrumbs.html" %}
|
||||
<div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
|
||||
<div itemprop="articleBody">
|
||||
{% block body %}{% endblock %}
|
||||
</div>
|
||||
<div class="articleComments">
|
||||
{% block comments %}{% endblock %}
|
||||
</div>
|
||||
</div>
|
||||
{% include "footer.html" %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</section>
|
||||
|
||||
</div>
|
||||
{% include "versions.html" %}
|
||||
|
||||
{% if not embedded %}
|
||||
|
||||
<script type="text/javascript">
|
||||
var DOCUMENTATION_OPTIONS = {
|
||||
URL_ROOT:'{{ url_root }}',
|
||||
VERSION:'{{ release|e }}',
|
||||
COLLAPSE_INDEX:false,
|
||||
FILE_SUFFIX:'{{ '' if no_search_suffix else file_suffix }}',
|
||||
HAS_SOURCE: {{ has_source|lower }},
|
||||
SOURCELINK_SUFFIX: '{{ sourcelink_suffix }}'
|
||||
};
|
||||
</script>
|
||||
{%- for scriptfile in script_files %}
|
||||
<script type="text/javascript" src="{{ pathto(scriptfile, 1) }}"></script>
|
||||
{%- endfor %}
|
||||
|
||||
{% endif %}
|
||||
|
||||
{# RTD hosts this file, so just load on non RTD builds #}
|
||||
{% if not READTHEDOCS %}
|
||||
<script type="text/javascript" src="{{ pathto('_static/js/theme.js', 1) }}"></script>
|
||||
{% endif %}
|
||||
|
||||
{# STICKY NAVIGATION #}
|
||||
{% if theme_sticky_navigation %}
|
||||
<script type="text/javascript">
|
||||
jQuery(function () {
|
||||
SphinxRtdTheme.StickyNav.enable();
|
||||
});
|
||||
</script>
|
||||
{% endif %}
|
||||
|
||||
{%- block footer %} {% endblock %}
|
||||
|
||||
</body>
|
||||
</html>
|
||||
209
doc/_themes/pretix_theme/layout_old.html
vendored
Normal file
@@ -0,0 +1,209 @@
|
||||
{#
|
||||
basic/layout.html
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
Master layout template for Sphinx themes.
|
||||
|
||||
:copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
#}
|
||||
{%- block doctype -%}
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
{%- endblock %}
|
||||
{%- set reldelim1 = reldelim1 is not defined and ' »' or reldelim1 %}
|
||||
{%- set reldelim2 = reldelim2 is not defined and ' |' or reldelim2 %}
|
||||
{%- set render_sidebar = (not embedded) and (not theme_nosidebar|tobool) and
|
||||
(sidebars != []) %}
|
||||
{%- set url_root = pathto('', 1) %}
|
||||
{# XXX necessary? #}
|
||||
{%- if url_root == '#' %}{% set url_root = '' %}{% endif %}
|
||||
{%- if not embedded and docstitle %}
|
||||
{%- set titlesuffix = " — "|safe + docstitle|e %}
|
||||
{%- else %}
|
||||
{%- set titlesuffix = "" %}
|
||||
{%- endif %}
|
||||
|
||||
{%- macro relbar() %}
|
||||
<div class="related">
|
||||
<h3>{{ _('Navigation') }}</h3>
|
||||
<ul>
|
||||
{%- for rellink in rellinks %}
|
||||
<li class="right" {% if loop.first %}style="margin-right: 10px"{% endif %}>
|
||||
<a href="{{ pathto(rellink[0]) }}" title="{{ rellink[1]|striptags|e }}"
|
||||
{{ accesskey(rellink[2]) }}>{{ rellink[3] }}</a>
|
||||
{%- if not loop.first %}{{ reldelim2 }}{% endif %}</li>
|
||||
{%- endfor %}
|
||||
{%- block rootrellink %}
|
||||
<li><a href="{{ pathto(master_doc) }}">{{ shorttitle|e }}</a>{{ reldelim1 }}</li>
|
||||
{%- endblock %}
|
||||
{%- for parent in parents %}
|
||||
<li><a href="{{ parent.link|e }}" {% if loop.last %}{{ accesskey("U") }}{% endif %}>{{ parent.title }}</a>{{ reldelim1 }}</li>
|
||||
{%- endfor %}
|
||||
{%- block relbaritems %} {% endblock %}
|
||||
</ul>
|
||||
</div>
|
||||
{%- endmacro %}
|
||||
|
||||
{%- macro sidebar() %}
|
||||
{%- if render_sidebar %}
|
||||
<div class="sphinxsidebar">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
{%- block sidebarlogo %}
|
||||
{%- if logo %}
|
||||
<p class="logo"><a href="{{ pathto(master_doc) }}">
|
||||
<img class="logo" src="{{ pathto('_static/' + logo, 1) }}" alt="Logo"/>
|
||||
</a></p>
|
||||
{%- endif %}
|
||||
{%- endblock %}
|
||||
{%- if sidebars != None %}
|
||||
{#- new style sidebar: explicitly include/exclude templates #}
|
||||
{%- for sidebartemplate in sidebars %}
|
||||
{%- include sidebartemplate %}
|
||||
{%- endfor %}
|
||||
{%- else %}
|
||||
{#- old style sidebars: using blocks -- should be deprecated #}
|
||||
{%- block sidebartoc %}
|
||||
{%- include "localtoc.html" %}
|
||||
{%- endblock %}
|
||||
{%- block sidebarrel %}
|
||||
{%- include "relations.html" %}
|
||||
{%- endblock %}
|
||||
{%- block sidebarsourcelink %}
|
||||
{%- include "sourcelink.html" %}
|
||||
{%- endblock %}
|
||||
{%- if customsidebar %}
|
||||
{%- include customsidebar %}
|
||||
{%- endif %}
|
||||
{%- block sidebarsearch %}
|
||||
{%- include "searchbox.html" %}
|
||||
{%- endblock %}
|
||||
{%- endif %}
|
||||
</div>
|
||||
</div>
|
||||
{%- endif %}
|
||||
{%- endmacro %}
|
||||
|
||||
{%- macro script() %}
|
||||
<script type="text/javascript">
|
||||
var DOCUMENTATION_OPTIONS = {
|
||||
URL_ROOT: '{{ url_root }}',
|
||||
VERSION: '{{ release|e }}',
|
||||
COLLAPSE_INDEX: false,
|
||||
FILE_SUFFIX: '{{ '' if no_search_suffix else file_suffix }}',
|
||||
HAS_SOURCE: {{ has_source|lower }},
|
||||
SOURCELINK_SUFFIX: '{{ sourcelink_suffix }}'
|
||||
};
|
||||
</script>
|
||||
{%- for scriptfile in script_files %}
|
||||
<script type="text/javascript" src="{{ pathto(scriptfile, 1) }}"></script>
|
||||
{%- endfor %}
|
||||
{%- endmacro %}
|
||||
|
||||
{%- macro css() %}
|
||||
<link rel="stylesheet" href="{{ pathto('_static/' + style, 1) }}" type="text/css" />
|
||||
<link rel="stylesheet" href="{{ pathto('_static/pygments.css', 1) }}" type="text/css" />
|
||||
{%- for cssfile in css_files %}
|
||||
<link rel="stylesheet" href="{{ pathto(cssfile, 1) }}" type="text/css" />
|
||||
{%- endfor %}
|
||||
{%- endmacro %}
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset={{ encoding }}" />
|
||||
{{ metatags }}
|
||||
{%- block htmltitle %}
|
||||
<title>{{ title|striptags|e }}{{ titlesuffix }}</title>
|
||||
{%- endblock %}
|
||||
{{ css() }}
|
||||
{%- if not embedded %}
|
||||
{{ script() }}
|
||||
{%- if use_opensearch %}
|
||||
<link rel="search" type="application/opensearchdescription+xml"
|
||||
title="{% trans docstitle=docstitle|e %}Search within {{ docstitle }}{% endtrans %}"
|
||||
href="{{ pathto('_static/opensearch.xml', 1) }}"/>
|
||||
{%- endif %}
|
||||
{%- if favicon %}
|
||||
<link rel="shortcut icon" href="{{ pathto('_static/' + favicon, 1) }}"/>
|
||||
{%- endif %}
|
||||
{%- if theme_canonical_url %}
|
||||
<link rel="canonical" href="{{ theme_canonical_url }}{{ pagename }}.html"/>
|
||||
{%- endif %}
|
||||
{%- endif %}
|
||||
{%- block linktags %}
|
||||
{%- if hasdoc('about') %}
|
||||
<link rel="author" title="{{ _('About these documents') }}" href="{{ pathto('about') }}" />
|
||||
{%- endif %}
|
||||
{%- if hasdoc('genindex') %}
|
||||
<link rel="index" title="{{ _('Index') }}" href="{{ pathto('genindex') }}" />
|
||||
{%- endif %}
|
||||
{%- if hasdoc('search') %}
|
||||
<link rel="search" title="{{ _('Search') }}" href="{{ pathto('search') }}" />
|
||||
{%- endif %}
|
||||
{%- if hasdoc('copyright') %}
|
||||
<link rel="copyright" title="{{ _('Copyright') }}" href="{{ pathto('copyright') }}" />
|
||||
{%- endif %}
|
||||
<link rel="top" title="{{ docstitle|e }}" href="{{ pathto('index') }}" />
|
||||
{%- if parents %}
|
||||
<link rel="up" title="{{ parents[-1].title|striptags|e }}" href="{{ parents[-1].link|e }}" />
|
||||
{%- endif %}
|
||||
{%- if next %}
|
||||
<link rel="next" title="{{ next.title|striptags|e }}" href="{{ next.link|e }}" />
|
||||
{%- endif %}
|
||||
{%- if prev %}
|
||||
<link rel="prev" title="{{ prev.title|striptags|e }}" href="{{ prev.link|e }}" />
|
||||
{%- endif %}
|
||||
{%- endblock %}
|
||||
{%- block extrahead %} {% endblock %}
|
||||
</head>
|
||||
<body>
|
||||
{%- block header %}{% endblock %}
|
||||
|
||||
{%- block relbar1 %}{{ relbar() }}{% endblock %}
|
||||
|
||||
{%- block content %}
|
||||
{%- block sidebar1 %} {# possible location for sidebar #} {% endblock %}
|
||||
|
||||
<div class="document">
|
||||
{%- block document %}
|
||||
<div class="documentwrapper">
|
||||
{%- if render_sidebar %}
|
||||
<div class="bodywrapper">
|
||||
{%- endif %}
|
||||
<div class="body">
|
||||
{% block body %} {% endblock %}
|
||||
</div>
|
||||
{%- if render_sidebar %}
|
||||
</div>
|
||||
{%- endif %}
|
||||
</div>
|
||||
{%- endblock %}
|
||||
|
||||
{%- block sidebar2 %}{{ sidebar() }}{% endblock %}
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
{%- endblock %}
|
||||
|
||||
{%- block relbar2 %}{{ relbar() }}{% endblock %}
|
||||
|
||||
{%- block footer %}
|
||||
<div class="footer">
|
||||
{%- if show_copyright %}
|
||||
{%- if hasdoc('copyright') %}
|
||||
{% trans path=pathto('copyright'), copyright=copyright|e %}© <a href="{{ path }}">Copyright</a> {{ copyright }}.{% endtrans %}
|
||||
{%- else %}
|
||||
{% trans copyright=copyright|e %}© Copyright {{ copyright }}.{% endtrans %}
|
||||
{%- endif %}
|
||||
{%- endif %}
|
||||
{%- if last_updated %}
|
||||
{% trans last_updated=last_updated|e %}Last updated on {{ last_updated }}.{% endtrans %}
|
||||
{%- endif %}
|
||||
{%- if show_sphinx %}
|
||||
{% trans sphinx_version=sphinx_version|e %}Created using <a href="http://sphinx-doc.org/">Sphinx</a> {{ sphinx_version }}.{% endtrans %}
|
||||
{%- endif %}
|
||||
</div>
|
||||
<p>asdf asdf asdf asdf 22</p>
|
||||
{%- endblock %}
|
||||
</body>
|
||||
</html>
|
||||
|
||||
50
doc/_themes/pretix_theme/search.html
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
{#
|
||||
basic/search.html
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
Template for the search page.
|
||||
|
||||
:copyright: Copyright 2007-2013 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
#}
|
||||
{%- extends "layout.html" %}
|
||||
{% set title = _('Search') %}
|
||||
{% set script_files = script_files + ['_static/searchtools.js'] %}
|
||||
{% block footer %}
|
||||
<script type="text/javascript">
|
||||
jQuery(function() { Search.loadIndex("{{ pathto('searchindex.js', 1) }}"); });
|
||||
</script>
|
||||
{# this is used when loading the search index using $.ajax fails,
|
||||
such as on Chrome for documents on localhost #}
|
||||
<script type="text/javascript" id="searchindexloader"></script>
|
||||
{{ super() }}
|
||||
{% endblock %}
|
||||
{% block body %}
|
||||
<noscript>
|
||||
<div id="fallback" class="admonition warning">
|
||||
<p class="last">
|
||||
{% trans %}Please activate JavaScript to enable the search
|
||||
functionality.{% endtrans %}
|
||||
</p>
|
||||
</div>
|
||||
</noscript>
|
||||
|
||||
{% if search_performed %}
|
||||
<h2>{{ _('Search Results') }}</h2>
|
||||
{% if not search_results %}
|
||||
<p>{{ _('Your search did not match any documents. Please make sure that all words are spelled correctly and that you\'ve selected enough categories.') }}</p>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
<div id="search-results">
|
||||
{% if search_results %}
|
||||
<ul>
|
||||
{% for href, caption, context in search_results %}
|
||||
<li>
|
||||
<a href="{{ pathto(item.href) }}">{{ caption }}</a>
|
||||
<p class="context">{{ context|e }}</p>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
9
doc/_themes/pretix_theme/searchbox.html
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
{%- if builder != 'singlehtml' %}
|
||||
<div role="search">
|
||||
<form id="rtd-search-form" class="wy-form" action="{{ pathto('search') }}" method="get">
|
||||
<input type="text" name="q" placeholder="{{ _('Search docs') }}" />
|
||||
<input type="hidden" name="check_keywords" value="yes" />
|
||||
<input type="hidden" name="area" value="default" />
|
||||
</form>
|
||||
</div>
|
||||
{%- endif %}
|
||||
2
doc/_themes/pretix_theme/static/css/badge_only.css
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
.fa:before{-webkit-font-smoothing:antialiased}.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;content:""}.clearfix:after{clear:both}@font-face{font-family:FontAwesome;font-weight:normal;font-style:normal;src:url("../font/fontawesome_webfont.eot");src:url("../font/fontawesome_webfont.eot?#iefix") format("embedded-opentype"),url("../font/fontawesome_webfont.woff") format("woff"),url("../font/fontawesome_webfont.ttf") format("truetype"),url("../font/fontawesome_webfont.svg#FontAwesome") format("svg")}.fa:before{display:inline-block;font-family:FontAwesome;font-style:normal;font-weight:normal;line-height:1;text-decoration:inherit}a .fa{display:inline-block;text-decoration:inherit}li .fa{display:inline-block}li .fa-large:before,li .fa-large:before{width:1.875em}ul.fas{list-style-type:none;margin-left:2em;text-indent:-0.8em}ul.fas li .fa{width:0.8em}ul.fas li .fa-large:before,ul.fas li .fa-large:before{vertical-align:baseline}.fa-book:before{content:""}.icon-book:before{content:""}.fa-caret-down:before{content:""}.icon-caret-down:before{content:""}.fa-caret-up:before{content:""}.icon-caret-up:before{content:""}.fa-caret-left:before{content:""}.icon-caret-left:before{content:""}.fa-caret-right:before{content:""}.icon-caret-right:before{content:""}.rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;border-top:solid 10px #343131;font-family:"Lato","proxima-nova","Helvetica Neue",Arial,sans-serif;z-index:400}.rst-versions a{color:#2980B9;text-decoration:none}.rst-versions .rst-badge-small{display:none}.rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27AE60;*zoom:1}.rst-versions .rst-current-version:before,.rst-versions .rst-current-version:after{display:table;content:""}.rst-versions .rst-current-version:after{clear:both}.rst-versions .rst-current-version .fa{color:#fcfcfc}.rst-versions .rst-current-version .fa-book{float:left}.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version.rst-out-of-date{background-color:#E74C3C;color:#fff}.rst-versions .rst-current-version.rst-active-old-version{background-color:#F1C40F;color:#000}.rst-versions.shift-up .rst-other-versions{display:block}.rst-versions .rst-other-versions{font-size:90%;padding:12px;color:gray;display:none}.rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:solid 1px #413d3d}.rst-versions .rst-other-versions dd{display:inline-block;margin:0}.rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc}.rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px}.rst-versions.rst-badge .icon-book{float:none}.rst-versions.rst-badge .fa-book{float:none}.rst-versions.rst-badge.shift-up .rst-current-version{text-align:right}.rst-versions.rst-badge.shift-up .rst-current-version .fa-book{float:left}.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge .rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width: 768px){.rst-versions{width:85%;display:none}.rst-versions.shift{display:block}}
|
||||
/*# sourceMappingURL=badge_only.css.map */
|
||||
6065
doc/_themes/pretix_theme/static/css/pretix.css
vendored
Normal file
4
doc/_themes/pretix_theme/static/js/modernizr.min.js
vendored
Normal file
169
doc/_themes/pretix_theme/static/js/theme.js
vendored
Normal file
@@ -0,0 +1,169 @@
|
||||
require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({"sphinx-rtd-theme":[function(require,module,exports){
|
||||
var jQuery = (typeof(window) != 'undefined') ? window.jQuery : require('jquery');
|
||||
|
||||
// Sphinx theme nav state
|
||||
function ThemeNav () {
|
||||
|
||||
var nav = {
|
||||
navBar: null,
|
||||
win: null,
|
||||
winScroll: false,
|
||||
winResize: false,
|
||||
linkScroll: false,
|
||||
winPosition: 0,
|
||||
winHeight: null,
|
||||
docHeight: null,
|
||||
isRunning: false
|
||||
};
|
||||
|
||||
nav.enable = function () {
|
||||
var self = this;
|
||||
|
||||
if (!self.isRunning) {
|
||||
self.isRunning = true;
|
||||
jQuery(function ($) {
|
||||
self.init($);
|
||||
|
||||
self.reset();
|
||||
self.win.on('hashchange', self.reset);
|
||||
|
||||
// Set scroll monitor
|
||||
self.win.on('scroll', function () {
|
||||
if (!self.linkScroll) {
|
||||
self.winScroll = true;
|
||||
}
|
||||
});
|
||||
setInterval(function () { if (self.winScroll) self.onScroll(); }, 25);
|
||||
|
||||
// Set resize monitor
|
||||
self.win.on('resize', function () {
|
||||
self.winResize = true;
|
||||
});
|
||||
setInterval(function () { if (self.winResize) self.onResize(); }, 25);
|
||||
self.onResize();
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
nav.init = function ($) {
|
||||
var doc = $(document),
|
||||
self = this;
|
||||
|
||||
this.navBar = $('div.wy-side-scroll:first');
|
||||
this.win = $(window);
|
||||
|
||||
// Set up javascript UX bits
|
||||
$(document)
|
||||
// Shift nav in mobile when clicking the menu.
|
||||
.on('click', "[data-toggle='wy-nav-top']", function() {
|
||||
$("[data-toggle='wy-nav-shift']").toggleClass("shift");
|
||||
$("[data-toggle='rst-versions']").toggleClass("shift");
|
||||
})
|
||||
|
||||
// Nav menu link click operations
|
||||
.on('click', ".wy-menu-vertical .current ul li a", function() {
|
||||
var target = $(this);
|
||||
// Close menu when you click a link.
|
||||
$("[data-toggle='wy-nav-shift']").removeClass("shift");
|
||||
$("[data-toggle='rst-versions']").toggleClass("shift");
|
||||
// Handle dynamic display of l3 and l4 nav lists
|
||||
self.toggleCurrent(target);
|
||||
self.hashChange();
|
||||
})
|
||||
.on('click', "[data-toggle='rst-current-version']", function() {
|
||||
$("[data-toggle='rst-versions']").toggleClass("shift-up");
|
||||
})
|
||||
|
||||
// Make tables responsive
|
||||
$("table.docutils:not(.field-list)")
|
||||
.wrap("<div class='wy-table-responsive'></div>");
|
||||
|
||||
// Add expand links to all parents of nested ul
|
||||
$('.wy-menu-vertical ul').not('.simple').siblings('a').each(function () {
|
||||
var link = $(this);
|
||||
expand = $('<span class="toctree-expand"></span>');
|
||||
expand.on('click', function (ev) {
|
||||
self.toggleCurrent(link);
|
||||
ev.stopPropagation();
|
||||
return false;
|
||||
});
|
||||
link.prepend(expand);
|
||||
});
|
||||
};
|
||||
|
||||
nav.reset = function () {
|
||||
// Get anchor from URL and open up nested nav
|
||||
var anchor = encodeURI(window.location.hash);
|
||||
if (anchor) {
|
||||
try {
|
||||
var link = $('.wy-menu-vertical')
|
||||
.find('[href="' + anchor + '"]');
|
||||
// If we didn't find a link, it may be because we clicked on
|
||||
// something that is not in the sidebar (eg: when using
|
||||
// sphinxcontrib.httpdomain it generates headerlinks but those
|
||||
// aren't picked up and placed in the toctree). So let's find
|
||||
// the closest header in the document and try with that one.
|
||||
if (link.length === 0) {
|
||||
var doc_link = $('.document a[href="' + anchor + '"]');
|
||||
var closest_section = doc_link.closest('div.section');
|
||||
// Try again with the closest section entry.
|
||||
link = $('.wy-menu-vertical')
|
||||
.find('[href="#' + closest_section.attr("id") + '"]');
|
||||
|
||||
}
|
||||
$('.wy-menu-vertical li.toctree-l1 li.current')
|
||||
.removeClass('current');
|
||||
link.closest('li.toctree-l2').addClass('current');
|
||||
link.closest('li.toctree-l3').addClass('current');
|
||||
link.closest('li.toctree-l4').addClass('current');
|
||||
}
|
||||
catch (err) {
|
||||
console.log("Error expanding nav for anchor", err);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
nav.onScroll = function () {
|
||||
this.winScroll = false;
|
||||
var newWinPosition = this.win.scrollTop(),
|
||||
winBottom = newWinPosition + this.winHeight,
|
||||
navPosition = this.navBar.scrollTop(),
|
||||
newNavPosition = navPosition + (newWinPosition - this.winPosition);
|
||||
if (newWinPosition < 0 || winBottom > this.docHeight) {
|
||||
return;
|
||||
}
|
||||
this.navBar.scrollTop(newNavPosition);
|
||||
this.winPosition = newWinPosition;
|
||||
};
|
||||
|
||||
nav.onResize = function () {
|
||||
this.winResize = false;
|
||||
this.winHeight = this.win.height();
|
||||
this.docHeight = $(document).height();
|
||||
};
|
||||
|
||||
nav.hashChange = function () {
|
||||
this.linkScroll = true;
|
||||
this.win.one('hashchange', function () {
|
||||
this.linkScroll = false;
|
||||
});
|
||||
};
|
||||
|
||||
nav.toggleCurrent = function (elem) {
|
||||
var parent_li = elem.closest('li');
|
||||
parent_li.siblings('li.current').removeClass('current');
|
||||
parent_li.siblings().find('li.current').removeClass('current');
|
||||
parent_li.find('> ul li.current').removeClass('current');
|
||||
parent_li.toggleClass('current');
|
||||
}
|
||||
|
||||
return nav;
|
||||
};
|
||||
|
||||
module.exports.ThemeNav = ThemeNav();
|
||||
|
||||
if (typeof(window) != 'undefined') {
|
||||
window.SphinxRtdTheme = { StickyNav: module.exports.ThemeNav };
|
||||
}
|
||||
|
||||
},{"jquery":"jquery"}]},{},["sphinx-rtd-theme"]);
|
||||
14
doc/_themes/pretix_theme/theme.conf
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
[theme]
|
||||
inherit = basic
|
||||
stylesheet = css/pretix.css
|
||||
|
||||
[options]
|
||||
typekit_id = hiw1hhg
|
||||
analytics_id =
|
||||
sticky_navigation = False
|
||||
logo_only =
|
||||
collapse_navigation = False
|
||||
display_version = True
|
||||
navigation_depth = 4
|
||||
prev_next_buttons_location = bottom
|
||||
canonical_url =
|
||||
37
doc/_themes/pretix_theme/versions.html
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
{% if READTHEDOCS %}
|
||||
{# Add rst-badge after rst-versions for small badge style. #}
|
||||
<div class="rst-versions" data-toggle="rst-versions" role="note" aria-label="versions">
|
||||
<span class="rst-current-version" data-toggle="rst-current-version">
|
||||
<span class="fa fa-book"> Read the Docs</span>
|
||||
v: {{ current_version }}
|
||||
<span class="fa fa-caret-down"></span>
|
||||
</span>
|
||||
<div class="rst-other-versions">
|
||||
<dl>
|
||||
<dt>{{ _('Versions') }}</dt>
|
||||
{% for slug, url in versions %}
|
||||
<dd><a href="{{ url }}">{{ slug }}</a></dd>
|
||||
{% endfor %}
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>{{ _('Downloads') }}</dt>
|
||||
{% for type, url in downloads %}
|
||||
<dd><a href="{{ url }}">{{ type }}</a></dd>
|
||||
{% endfor %}
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>{{ _('On Read the Docs') }}</dt>
|
||||
<dd>
|
||||
<a href="//{{ PRODUCTION_DOMAIN }}/projects/{{ slug }}/?fromdocs={{ slug }}">{{ _('Project Home') }}</a>
|
||||
</dd>
|
||||
<dd>
|
||||
<a href="//{{ PRODUCTION_DOMAIN }}/builds/{{ slug }}/?fromdocs={{ slug }}">{{ _('Builds') }}</a>
|
||||
</dd>
|
||||
</dl>
|
||||
<hr/>
|
||||
{% trans %}Free document hosting provided by <a href="http://www.readthedocs.org">Read the Docs</a>.{% endtrans %}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
@@ -10,9 +10,10 @@ at the following locations. It will try to read the file from the specified path
|
||||
the following order. The file that is found *last* will override the settings from
|
||||
the files found before.
|
||||
|
||||
1. ``/etc/pretix/pretix.cfg``
|
||||
2. ``~/.pretix.cfg``
|
||||
3. ``pretix.cfg`` in the current working directory
|
||||
1. ``PREFIX_CONFIG_FILE`` environment variable
|
||||
2. ``/etc/pretix/pretix.cfg``
|
||||
3. ``~/.pretix.cfg``
|
||||
4. ``pretix.cfg`` in the current working directory
|
||||
|
||||
The file is expected to be in the INI format as specified in the `Python documentation`_.
|
||||
|
||||
@@ -102,6 +103,10 @@ Example::
|
||||
``user``, ``password``, ``host``, ``port``
|
||||
Connection details for the database connection. Empty by default.
|
||||
|
||||
``galera``
|
||||
Indicates if the database backend is a MySQL/MariaDB Galera cluster and
|
||||
turns on some optimizations/special case handlers. Default: ``False``
|
||||
|
||||
URLs
|
||||
----
|
||||
|
||||
@@ -151,6 +156,8 @@ Example::
|
||||
``admins``
|
||||
Comma-separated list of email addresses that should receive a report about every error code 500 thrown by pretix.
|
||||
|
||||
.. _`django-settings`:
|
||||
|
||||
Django settings
|
||||
---------------
|
||||
|
||||
@@ -175,6 +182,11 @@ Example::
|
||||
|
||||
.. WARNING:: Never set this to ``True`` in production!
|
||||
|
||||
``profile``
|
||||
Enable code profiling for a random subset of requests. Disabled by default, see
|
||||
:ref:`perf-monitoring` for details.
|
||||
|
||||
.. _`metrics-settings`:
|
||||
|
||||
Metrics
|
||||
-------
|
||||
@@ -247,7 +259,7 @@ Sentry
|
||||
------
|
||||
|
||||
pretix has native support for sentry, a tool that you can use to track errors in the
|
||||
application. If you want to use sentry, you need to set a DSN in the configuration file.
|
||||
application. If you want to use sentry, you need to set a DSN in the configuration file::
|
||||
|
||||
[sentry]
|
||||
dsn=https://<key>:<secret>@sentry.io/<project>
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
.. _`admindocs`:
|
||||
|
||||
Administrator documentation
|
||||
===========================
|
||||
|
||||
This documentation is for everyone who wants to install pretix on a server.
|
||||
|
||||
Contents:
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
installation/index
|
||||
config
|
||||
maintainance
|
||||
|
||||
@@ -111,7 +111,7 @@ Fill the configuration file ``/etc/pretix/pretix.cfg`` with the following conten
|
||||
datadir=/data
|
||||
|
||||
[database]
|
||||
; Replace mysql with psycopg2 for PostgreSQL
|
||||
; Replace mysql with postgresql_psycopg2 for PostgreSQL
|
||||
backend=mysql
|
||||
name=pretix
|
||||
user=pretix
|
||||
@@ -141,9 +141,9 @@ See :ref:`email configuration <mail-settings>` to learn more about configuring m
|
||||
Docker image and service
|
||||
------------------------
|
||||
|
||||
First of all, download the latest pretix image by running::
|
||||
First of all, download the latest stable pretix image by running::
|
||||
|
||||
$ docker pull pretix/standalone:latest
|
||||
$ docker pull pretix/standalone:stable
|
||||
|
||||
We recommend starting the docker container using systemd to make sure it runs correctly after a reboot. Create a file
|
||||
named ``/etc/systemd/system/pretix.service`` with the following content::
|
||||
@@ -222,6 +222,8 @@ Yay, you are done! You should now be able to reach pretix at https://pretix.your
|
||||
*admin@localhost* with a password of *admin*. Don't forget to change that password! Create an organizer first, then
|
||||
create an event and start selling tickets!
|
||||
|
||||
You should probably read :ref:`maintainance` next.
|
||||
|
||||
Updates
|
||||
-------
|
||||
|
||||
@@ -229,11 +231,13 @@ Updates
|
||||
|
||||
Updates are fairly simple, but require at least a short downtime::
|
||||
|
||||
# docker pull pretix/standalone
|
||||
# docker pull pretix/standalone:stable
|
||||
# systemctl restart pretix.service
|
||||
# docker exec -it pretix.service pretix upgrade
|
||||
|
||||
Restarting the service can take a few seconds, especially if the update requires changes to the database.
|
||||
Replace ``stable`` above with a specific version number like ``1.0`` or with ``latest`` for the development
|
||||
version, if you want to.
|
||||
|
||||
Install a plugin
|
||||
----------------
|
||||
@@ -242,11 +246,11 @@ To install a plugin, you need to build your own docker image. To do so, create a
|
||||
named ``Dockerfile`` in it. The Dockerfile could look like this (replace ``pretix-passbook`` with the plugins of your
|
||||
choice)::
|
||||
|
||||
FROM pretix/standalone
|
||||
FROM pretix/standalone:stable
|
||||
USER root
|
||||
RUN pip3 install pretix-passbook
|
||||
USER pretixuser
|
||||
RUN make production
|
||||
RUN cd /pretix/src && make production
|
||||
|
||||
Then, go to that directory and build the image::
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ General remarks
|
||||
|
||||
Requirements
|
||||
------------
|
||||
To use pretix, you wull need the following things:
|
||||
To use pretix, you will need the following things:
|
||||
|
||||
* **pretix** and the python packages it depends on
|
||||
|
||||
|
||||
@@ -38,10 +38,10 @@ Unix user
|
||||
|
||||
As we do not want to run pretix as root, we first create a new unprivileged user::
|
||||
|
||||
# sudo adduser pretix --disabled-password --home /var/pretix
|
||||
# adduser pretix --disabled-password --home /var/pretix
|
||||
|
||||
In this guide, all code lines prepended with a ``#`` symbol are commands that you need to execute on your server as
|
||||
``root`` user; all lines prepended with a ``$`` symbol should be run by the unprivileged user.
|
||||
``root`` user (e.g. using ``sudo``); all lines prepended with a ``$`` symbol should be run by the unprivileged user.
|
||||
|
||||
Database
|
||||
--------
|
||||
@@ -82,7 +82,7 @@ Fill the configuration file ``/etc/pretix/pretix.cfg`` with the following conten
|
||||
datadir=/var/pretix/data
|
||||
|
||||
[database]
|
||||
; Replace mysql with psycopg2 for PostgreSQL
|
||||
; Replace mysql with postgresql_psycopg2 for PostgreSQL
|
||||
backend=mysql
|
||||
name=pretix
|
||||
user=pretix
|
||||
@@ -100,8 +100,8 @@ Fill the configuration file ``/etc/pretix/pretix.cfg`` with the following conten
|
||||
sessions=true
|
||||
|
||||
[celery]
|
||||
backend=redis://127.0.0.1?virtual_host=1
|
||||
broker=redis://127.0.0.1?virtual_host=2
|
||||
backend=redis://127.0.0.1/1
|
||||
broker=redis://127.0.0.1/2
|
||||
|
||||
See :ref:`email configuration <mail-settings>` to learn more about configuring mail features.
|
||||
|
||||
@@ -119,7 +119,10 @@ python installation::
|
||||
We now install pretix, its direct dependencies and gunicorn. Replace ``mysql`` with ``postgres`` in the following
|
||||
command if you're running PostgreSQL::
|
||||
|
||||
(venv)$ pip install "pretix[mysql]" gunicorn
|
||||
(venv)$ pip3 install "pretix[mysql]" gunicorn
|
||||
|
||||
If you are running Python 3.4, you also need to ``pip3 install typing``. This is not required on 3.5 or newer.
|
||||
You can find out your Python version using ``python -V``.
|
||||
|
||||
We also need to create a data directory::
|
||||
|
||||
@@ -127,8 +130,8 @@ We also need to create a data directory::
|
||||
|
||||
Finally, we compile static files and translation data and create the database structure::
|
||||
|
||||
(venv)$ python -m pretix rebuild
|
||||
(venv)$ python -m pretix migrate
|
||||
(venv)$ python -m pretix rebuild
|
||||
|
||||
|
||||
Start pretix as a service
|
||||
@@ -150,7 +153,7 @@ named ``/etc/systemd/system/pretix-web.service`` with the following content::
|
||||
--name pretix --workers 5 \
|
||||
--max-requests 1200 --max-requests-jitter 50 \
|
||||
--log-level=info --bind=127.0.0.1:8345
|
||||
WorkingDirectory=/var/pretix/source/src
|
||||
WorkingDirectory=/var/pretix
|
||||
Restart=on-failure
|
||||
|
||||
[Install]
|
||||
@@ -168,7 +171,7 @@ For background tasks we need a second service ``/etc/systemd/system/pretix-worke
|
||||
Environment="VIRTUAL_ENV=/var/pretix/venv"
|
||||
Environment="PATH=/var/pretix/venv/bin:/usr/local/bin:/usr/bin:/bin"
|
||||
ExecStart=/var/pretix/venv/bin/celery -A pretix.celery_app worker -l info
|
||||
WorkingDirectory=/var/pretix/source/src
|
||||
WorkingDirectory=/var/pretix
|
||||
Restart=on-failure
|
||||
|
||||
[Install]
|
||||
@@ -187,7 +190,7 @@ Cronjob
|
||||
You need to set up a cronjob that runs the management command ``runperiodic``. The exact interval is not important
|
||||
but should be something between every minute and every hour. You could for example configure cron like this::
|
||||
|
||||
15,45 * * * * export PATH=/var/pretix/venv/bin:$PATH && cd /var/pretix/source/src && python -m pretix runperiodic
|
||||
15,45 * * * * export PATH=/var/pretix/venv/bin:$PATH && cd /var/pretix && python -m pretix runperiodic
|
||||
|
||||
The cronjob should run as the ``pretix`` user (``crontab -e -u pretix``).
|
||||
|
||||
@@ -210,6 +213,9 @@ The following snippet is an example on how to configure a nginx proxy for pretix
|
||||
ssl_certificate /path/to/cert.chain.pem;
|
||||
ssl_certificate_key /path/to/key.pem;
|
||||
|
||||
add_header Referrer-Options same-origin;
|
||||
add_header X-Content-Type-Options nosniff;
|
||||
|
||||
location / {
|
||||
proxy_pass http://localhost:8345/;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
@@ -223,14 +229,25 @@ The following snippet is an example on how to configure a nginx proxy for pretix
|
||||
access_log off;
|
||||
}
|
||||
|
||||
location ^~ /media/cachedfiles {
|
||||
deny all;
|
||||
return 404;
|
||||
}
|
||||
location ^~ /media/invoices {
|
||||
deny all;
|
||||
return 404;
|
||||
}
|
||||
|
||||
location /static/ {
|
||||
alias /var/pretix/source/src/pretix/static.dist/;
|
||||
alias /var/pretix/venv/lib/python3.5/site-packages/pretix/static.dist/;
|
||||
access_log off;
|
||||
expires 365d;
|
||||
add_header Cache-Control "public";
|
||||
}
|
||||
}
|
||||
|
||||
.. note:: Remember to replace the ``python3.5`` in the ``/static/`` path in the config
|
||||
above with your python version.
|
||||
|
||||
We recommend reading about setting `strong encryption settings`_ for your web server.
|
||||
|
||||
@@ -241,6 +258,8 @@ Yay, you are done! You should now be able to reach pretix at https://pretix.your
|
||||
*admin@localhost* with a password of *admin*. Don't forget to change that password! Create an organizer first, then
|
||||
create an event and start selling tickets!
|
||||
|
||||
You should probably read :ref:`maintainance` next.
|
||||
|
||||
Updates
|
||||
-------
|
||||
|
||||
|
||||
99
doc/admin/maintainance.rst
Normal file
@@ -0,0 +1,99 @@
|
||||
.. highlight:: ini
|
||||
|
||||
.. _`maintainance`:
|
||||
|
||||
Backups and Monitoring
|
||||
======================
|
||||
|
||||
If you host your own pretix instance, you also need to care about the availability
|
||||
of your service and the safety of your data yourself. This page gives you some
|
||||
information that you might need to do so properly.
|
||||
|
||||
Backups
|
||||
-------
|
||||
|
||||
There are essentially two things which you should create backups of:
|
||||
|
||||
Database
|
||||
Your SQL database (MySQL or PostgreSQL). This is critical and you should **absolutely
|
||||
always create automatic backups of your database**. There are tons of tutorials on the
|
||||
internet on how to do this, and the exact process depends on the choice of your database.
|
||||
For MySQL, see ``mysqldump`` and for PostgreSQL, see the ``pg_dump`` tool. You probably
|
||||
want to create a cronjob that does the backups for you on a regular schedule.
|
||||
|
||||
Data directory
|
||||
The data directory of your pretix configuration might contain some things that you should
|
||||
back up. If you did not specify a secret in your config file, back up the ``.secret`` text
|
||||
file in the data directory. If you lose your secret, all currently active user sessions,
|
||||
password reset links and similar things will be rendered invalid. Also, you probably want
|
||||
to backup the ``media`` subdirectory of the data directory which contains all user-uploaded
|
||||
and generated files. This includes files you could in theory regenerate (ticket downloads)
|
||||
but also files that you might be legally required to keep (invoice PDFs) or files that you
|
||||
would need to re-upload (event logos, product pictures, etc.). It is up to you if you
|
||||
create regular backups of this data, but we strongly advise you to do so. You can create
|
||||
backups e.g. using ``rsync``. There is a lot of information on the internet on how to create
|
||||
backups of folders on a Linux machine.
|
||||
|
||||
There is no need to create backups of the redis database, if you use it. We only use it for
|
||||
non-critical, temporary or cached data.
|
||||
|
||||
Uptime monitoring
|
||||
-----------------
|
||||
|
||||
To monitor whether your pretix instance is running, you can issue a GET request to
|
||||
``https://pretix.mydomain.com/healthcheck/``. This endpoint tests if the connection to the
|
||||
database, to the configured cache and to redis (if used) is working correctly. If everything
|
||||
appears to work fine, an empty response with status code ``200`` is returned.
|
||||
If there is a problem, a status code in the ``5xx`` range will be returned.
|
||||
|
||||
.. _`perf-monitoring`:
|
||||
|
||||
Performance monitoring
|
||||
----------------------
|
||||
|
||||
If you want to generate detailed performance statistics of your pretix installation, there is an
|
||||
endpoint at ``https://pretix.mydomain.com/metrics`` (no slash at the end) which returns a
|
||||
number of values in the text format understood by monitoring tools like Prometheus_. This data
|
||||
is only collected and exposed if you enable it in the :ref:`metrics-settings` section of your
|
||||
pretix configuration. You can also configure basic auth credentials there to protect your
|
||||
statistics against unauthorized access. The data is temporarily collected in redis, so the
|
||||
performance impact of this feature depends on the connection to your redis database.
|
||||
|
||||
Currently, mostly response times of HTTP requests and background tasks are exposed.
|
||||
|
||||
If you want to go even further, you can set the ``profile`` option in the :ref:`django-settings`
|
||||
section to a value between 0 and 1. If you set it for example to 0.1, then 10% of your requests
|
||||
(randomly selected) will be run with cProfile_ activated. The profiling results will be saved
|
||||
to your data directory. As this might impact performance significantly and writes a lot of data
|
||||
to disk, we recommend to only enable it for a small number of requests -- and only if you are
|
||||
really interested in the results.
|
||||
|
||||
Available metrics
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
The metrics available in pretix follow the standard `metric types`_ from the Prometheus world.
|
||||
Currently, the following metrics are exported:
|
||||
|
||||
pretix_view_requests_total
|
||||
Counter. Counts requests to Django views, labeled with the resolved ``url_name``, the used
|
||||
HTTP ``method`` and the ``status_code`` returned.
|
||||
|
||||
pretix_view_durations_seconds
|
||||
Histogram. Measures duration of requests to Django views, labeled with the resolved
|
||||
``url_name``, the used HTTP ``method`` and the ``status_code`` returned.
|
||||
|
||||
pretix_task_runs_total
|
||||
Counter. Counts executions of background tasks, labeled with the ``task_name`` and the
|
||||
``status``. The latter can be ``success``, ``error`` or ``expected-error``.
|
||||
|
||||
pretix_task_duration_seconds
|
||||
Histogram. Measures duration of successful background task executions, labeled with the
|
||||
``task_name``.
|
||||
|
||||
pretix_model_instances
|
||||
Gauge. Measures number of instances of a certain model within the database, labeled with
|
||||
the ``model`` name.
|
||||
|
||||
.. _metric types: https://prometheus.io/docs/concepts/metric_types/
|
||||
.. _Prometheus: https://prometheus.io/
|
||||
.. _cProfile: https://docs.python.org/3/library/profile.html
|
||||
145
doc/api/fundamentals.rst
Normal file
@@ -0,0 +1,145 @@
|
||||
Basic concepts
|
||||
==============
|
||||
|
||||
This page describes basic concepts and definition that you need to know to interact
|
||||
with pretix' REST API, such as authentication, pagination and similar definitions.
|
||||
|
||||
Obtaining an API token
|
||||
----------------------
|
||||
|
||||
To authenticate your API requests, you need to obtain an API token. You can create a
|
||||
token in the pretix web interface on the level of organizer teams. Create a new team
|
||||
or choose an existing team that has the level of permissions the token should have and
|
||||
create a new token using the form below the list of team members:
|
||||
|
||||
.. image:: img/token_form.png
|
||||
|
||||
You can enter a description for the token to distinguish from other tokens later on.
|
||||
Once you click "Add", you will be provided with an API token in the success message.
|
||||
Copy this token, as you won't be able to retrieve it again.
|
||||
|
||||
.. image:: img/token_success.png
|
||||
|
||||
Authentication
|
||||
--------------
|
||||
|
||||
You need to include the API token with every request to pretix' API in the ``Authorization`` header
|
||||
like the following:
|
||||
|
||||
.. sourcecode:: http
|
||||
:emphasize-lines: 3
|
||||
|
||||
GET /api/v1/organizers/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Authorization: Token e1l6gq2ye72thbwkacj7jbri7a7tvxe614ojv8ybureain92ocub46t5gab5966k
|
||||
|
||||
.. note:: The API currently also supports authentication via browser sessions, i.e. the
|
||||
same way that you authenticate with pretix when using the browser interface.
|
||||
Using this type of authentication is *not* officially supported for use by
|
||||
third-party clients and might change or be removed at any time. We plan on
|
||||
adding OAuth2 support in the future for user-level authentication. If you want
|
||||
to use session authentication, be sure to comply with Django's `CSRF policies`_.
|
||||
|
||||
Compatibility
|
||||
-------------
|
||||
|
||||
We currently see pretix' API as a beta-stage feature. We therefore do not give any guarantees
|
||||
for compatibility between feature releases of pretix (such as 1.5 and 1.6). However, as always,
|
||||
we try not to break things when we don't need to. Any backwards-incompatible changes will be
|
||||
prominently noted in the release notes.
|
||||
|
||||
We treat the following types of changes as *backwards-compatible* so we ask you to make sure
|
||||
that your clients can deal with them properly:
|
||||
|
||||
* Support of new API endpoints
|
||||
* Support of new HTTP methods for a given API endpoint
|
||||
* Support of new query parameters for a given API endpoint
|
||||
* New fields contained in API responses
|
||||
|
||||
We treat the following types of changes as *backwards-incompatible*:
|
||||
|
||||
* Type changes of fields in API responses
|
||||
* New required input fields for an API endpoint
|
||||
* New required type for input fields of an API endpoint
|
||||
* Removal of endpoints, API methods or fields
|
||||
|
||||
Pagination
|
||||
----------
|
||||
|
||||
Most lists of objects returned by pretix' API will be paginated. The response will take
|
||||
the form of:
|
||||
|
||||
.. sourcecode:: javascript
|
||||
|
||||
{
|
||||
"count": 117,
|
||||
"next": "https://pretix.eu/api/v1/organizers/?page=2",
|
||||
"previous": null,
|
||||
"results": […],
|
||||
}
|
||||
|
||||
As you can see, the response contains the total number of results in the field ``count``.
|
||||
The fields ``next`` and ``previous`` contain links to the next and previous page of results,
|
||||
respectively, or ``null`` if there is no such page. You can use those URLs to retrieve the
|
||||
respective page.
|
||||
|
||||
The field ``results`` contains a list of objects representing the first results. For most
|
||||
objects, every page contains 50 results.
|
||||
|
||||
Errors
|
||||
------
|
||||
|
||||
Error responses (of type 400-499) are returned in one of the following forms, depending on
|
||||
the type of error. General errors look like:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 405 Method Not Allowed
|
||||
Content-Type: application/json
|
||||
Content-Length: 42
|
||||
|
||||
{"detail": "Method 'DELETE' not allowed."}
|
||||
|
||||
Field specific input errors include the name of the offending fields as keys in the response:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 400 Bad Request
|
||||
Content-Type: application/json
|
||||
Content-Length: 94
|
||||
|
||||
{"amount": ["A valid integer is required."], "description": ["This field may not be blank."]}
|
||||
|
||||
|
||||
Data types
|
||||
----------
|
||||
|
||||
All structured API responses are returned in JSON format using standard JSON data types such
|
||||
as integers, floating point numbers, strings, lists, objects and booleans. Most fields can
|
||||
be ``null`` as well.
|
||||
|
||||
The following table shows some data types that have no native JSON representation and how
|
||||
we serialize them to JSON.
|
||||
|
||||
===================== ============================ ===================================
|
||||
Internal pretix type JSON representation Examples
|
||||
===================== ============================ ===================================
|
||||
Datetime String in ISO 8601 format ``"2017-12-27T10:00:00Z"``
|
||||
with timezone (normally UTC) ``"2017-12-27T10:00:00.596934Z"``,
|
||||
``"2017-12-27T10:00:00+02:00"``
|
||||
Date String in ISO 8601 format ``2017-12-27``
|
||||
Multi-lingual string Object of strings ``{"en": "red", "de": "rot", "de_Informal": "rot"}``
|
||||
Money String with decimal number ``"23.42"``
|
||||
Currency String with ISO 4217 code ``"EUR"``, ``"USD"``
|
||||
===================== ============================ ===================================
|
||||
|
||||
Query parameters
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
Most list endpoints allow a filtering of the results using query parameters. In this case, booleans should be passed
|
||||
as the string values ``true`` and ``false``.
|
||||
|
||||
If the ``ordering`` parameter is documented for a resource, you can use it to sort the result set by one of the allowed
|
||||
fields. Prepend a ``-`` to the field name to reverse the sort order.
|
||||
|
||||
.. _CSRF policies: https://docs.djangoproject.com/en/1.11/ref/csrf/#ajax
|
||||
BIN
doc/api/img/token_form.png
Normal file
|
After Width: | Height: | Size: 9.6 KiB |
BIN
doc/api/img/token_success.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
17
doc/api/index.rst
Normal file
@@ -0,0 +1,17 @@
|
||||
.. _`rest-api`:
|
||||
|
||||
REST API
|
||||
========
|
||||
|
||||
This part of the documentation contains information about the REST-style API
|
||||
exposed by pretix since version 1.5 that can be used by third-party programs
|
||||
to interact with pretix and its data structures.
|
||||
|
||||
Currently, the API provides mostly read-only capabilities, but it will be extended
|
||||
in functionality over time.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
fundamentals
|
||||
resources/index
|
||||
108
doc/api/resources/categories.rst
Normal file
@@ -0,0 +1,108 @@
|
||||
Item categories
|
||||
===============
|
||||
|
||||
Resource description
|
||||
--------------------
|
||||
|
||||
Categories provide grouping for items (better known as products).
|
||||
The category resource contains the following public fields:
|
||||
|
||||
.. rst-class:: rest-resource-table
|
||||
|
||||
===================================== ========================== =======================================================
|
||||
Field Type Description
|
||||
===================================== ========================== =======================================================
|
||||
id integer Internal ID of the category
|
||||
name multi-lingual string The category's visible name
|
||||
description multi-lingual string A public description (might include markdown, can
|
||||
be ``null``)
|
||||
position integer An integer, used for sorting the categories
|
||||
is_addon boolean If ``True``, items within this category are not on sale
|
||||
on their own but the category provides a source for
|
||||
defining add-ons for other products.
|
||||
===================================== ========================== =======================================================
|
||||
|
||||
|
||||
Endpoints
|
||||
---------
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/categories/
|
||||
|
||||
Returns a list of all categories within a given event.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/sampleconf/categories/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: text/javascript
|
||||
|
||||
{
|
||||
"count": 1,
|
||||
"next": null,
|
||||
"previous": null,
|
||||
"results": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": {"en": "Tickets"},
|
||||
"description": {"en": "Tickets are what you need to get in."},
|
||||
"position": 1,
|
||||
"is_addon": false
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
:query integer page: The page number in case of a multi-page result set, default is 1
|
||||
:query boolean is_addon: If set to ``true`` or ``false``, only categories with this value for the field ``is_addon`` will be
|
||||
returned.
|
||||
:query string ordering: Manually set the ordering of results. Valid fields to be used are ``id`` and ``position``.
|
||||
Default: ``position``
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/categories/(id)/
|
||||
|
||||
Returns information on one category, identified by its ID.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/sampleconf/categories/1/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: text/javascript
|
||||
|
||||
{
|
||||
"id": 1,
|
||||
"name": {"en": "Tickets"},
|
||||
"description": {"en": "Tickets are what you need to get in."},
|
||||
"position": 1,
|
||||
"is_addon": false
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:param id: The ``id`` field of the category to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
|
||||
122
doc/api/resources/events.rst
Normal file
@@ -0,0 +1,122 @@
|
||||
Events
|
||||
======
|
||||
|
||||
Resource description
|
||||
--------------------
|
||||
|
||||
The event resource contains the following public fields:
|
||||
|
||||
.. rst-class:: rest-resource-table
|
||||
|
||||
===================================== ========================== =======================================================
|
||||
Field Type Description
|
||||
===================================== ========================== =======================================================
|
||||
name multi-lingual string The event's full name
|
||||
slug string A short form of the name, used e.g. in URLs.
|
||||
live boolean If ``true``, the event ticket shop is publicly
|
||||
available.
|
||||
currency string The currency this event is handled in.
|
||||
date_from datetime The event's start date
|
||||
date_to datetime The event's end date (or ``null``)
|
||||
date_admission datetime The event's admission date (or ``null``)
|
||||
is_public boolean If ``true``, the event shows up in places like the
|
||||
organizer's public list of events
|
||||
presale_start datetime The date at which the ticket shop opens (or ``null``)
|
||||
presale_end datetime The date at which the ticket shop closes (or ``null``)
|
||||
location multi-lingual string The event location (or ``null``)
|
||||
has_subevents boolean ``True`` if the event series feature is active for this
|
||||
event
|
||||
===================================== ========================== =======================================================
|
||||
|
||||
|
||||
Endpoints
|
||||
---------
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/
|
||||
|
||||
Returns a list of all events within a given organizer the authenticated user/token has access to.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: text/javascript
|
||||
|
||||
{
|
||||
"count": 1,
|
||||
"next": null,
|
||||
"previous": null,
|
||||
"results": [
|
||||
{
|
||||
"name": {"en": "Sample Conference"},
|
||||
"slug": "sampleconf",
|
||||
"live": false,
|
||||
"currency": "EUR",
|
||||
"date_from": "2017-12-27T10:00:00Z",
|
||||
"date_to": null,
|
||||
"date_admission": null,
|
||||
"is_public": null,
|
||||
"presale_start": null,
|
||||
"presale_end": null,
|
||||
"location": null,
|
||||
"has_subevents": false
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
:query page: The page number in case of a multi-page result set, default is 1
|
||||
:param organizer: The ``slug`` field of a valid organizer
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer does not exist **or** you have no permission to view it.
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/
|
||||
|
||||
Returns information on one event, identified by its slug.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/sampleconf/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: text/javascript
|
||||
|
||||
{
|
||||
"name": {"en": "Sample Conference"},
|
||||
"slug": "sampleconf",
|
||||
"live": false,
|
||||
"currency": "EUR",
|
||||
"date_from": "2017-12-27T10:00:00Z",
|
||||
"date_to": null,
|
||||
"date_admission": null,
|
||||
"is_public": false,
|
||||
"presale_start": null,
|
||||
"presale_end": null,
|
||||
"location": null,
|
||||
"has_subevents": false
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view it.
|
||||
17
doc/api/resources/index.rst
Normal file
@@ -0,0 +1,17 @@
|
||||
Resources and endpoints
|
||||
=======================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
organizers
|
||||
events
|
||||
subevents
|
||||
categories
|
||||
items
|
||||
questions
|
||||
quotas
|
||||
orders
|
||||
invoices
|
||||
vouchers
|
||||
waitinglist
|
||||
194
doc/api/resources/invoices.rst
Normal file
@@ -0,0 +1,194 @@
|
||||
Invoices
|
||||
========
|
||||
|
||||
Resource description
|
||||
--------------------
|
||||
|
||||
The invoice resource contains the following public fields:
|
||||
|
||||
.. rst-class:: rest-resource-table
|
||||
|
||||
===================================== ========================== =======================================================
|
||||
Field Type Description
|
||||
===================================== ========================== =======================================================
|
||||
number string Invoice number (with prefix)
|
||||
order string Order code of the order this invoice belongs to
|
||||
is_cancellation boolean ``True``, if this invoice is the cancellation of a
|
||||
different invoice.
|
||||
invoice_from string Sender address
|
||||
invoice_to string Receiver address
|
||||
date date Invoice date
|
||||
refers string Invoice number of an invoice this invoice refers to
|
||||
(for example a cancellation refers to the invoice it
|
||||
cancels) or ``null``.
|
||||
locale string Invoice locale
|
||||
introductory_text string Text to be printed above the product list
|
||||
additional_text string Text to be printed below the product list
|
||||
payment_provider_text string Text to be printed below the product list with
|
||||
payment information
|
||||
footer_text string Text to be printed in the page footer area
|
||||
lines list of objects The actual invoice contents
|
||||
├ description string Text representing the invoice line (e.g. product name)
|
||||
├ gross_value money (string) Price including VAT
|
||||
├ tax_value money (string) VAT amount
|
||||
└ tax_rate decimal (string) Used VAT rate
|
||||
===================================== ========================== =======================================================
|
||||
|
||||
|
||||
.. versionchanged:: 1.6
|
||||
|
||||
The attribute ``invoice_no`` has been dropped in favor of ``number`` which includes the number including the prefix,
|
||||
since the prefix can now vary. Also, invoices now need to be identified by their ``number`` instead of the raw
|
||||
number.
|
||||
|
||||
|
||||
Endpoints
|
||||
---------
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/invoices/
|
||||
|
||||
Returns a list of all invoices within a given event.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/sampleconf/invoices/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: text/javascript
|
||||
|
||||
{
|
||||
"count": 1,
|
||||
"next": null,
|
||||
"previous": null,
|
||||
"results": [
|
||||
{
|
||||
"number": "SAMPLECONF-00001",
|
||||
"order": "ABC12",
|
||||
"is_cancellation": false,
|
||||
"invoice_from": "Big Events LLC\nDemo street 12\nDemo town",
|
||||
"invoice_to": "Sample company\nJohn Doe\nTest street 12\n12345 Testington\nTestikistan\nVAT ID: EU123456789",
|
||||
"date": "2017-12-01",
|
||||
"refers": null,
|
||||
"locale": "en",
|
||||
"introductory_text": "thank you for your purchase of the following items:",
|
||||
"additional_text": "We are looking forward to see you on our conference!",
|
||||
"payment_provider_text": "Please transfer the money to our account ABC…",
|
||||
"footer_text": "Big Events LLC - Registration No. 123456 - VAT ID: EU0987654321",
|
||||
"lines": [
|
||||
{
|
||||
"description": "Budget Ticket",
|
||||
"gross_value": "23.00",
|
||||
"tax_value": "0.00",
|
||||
"tax_rate": "0.00"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
:query integer page: The page number in case of a multi-page result set, default is 1
|
||||
:query boolean is_cancellation: If set to ``true`` or ``false``, only invoices with this value for the field
|
||||
``is_cancellation`` will be returned.
|
||||
:query string order: If set, only invoices belonging to the order with the given order code will be returned.
|
||||
:query string refers: If set, only invoices refering to the given invoice will be returned.
|
||||
:query string locale: If set, only invoices with the given locale will be returned.
|
||||
:query string ordering: Manually set the ordering of results. Valid fields to be used are ``date`` and
|
||||
``nr`` (equals to ``number``). Default: ``nr``
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/invoices/(number)/
|
||||
|
||||
Returns information on one invoice, identified by its invoice number.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/sampleconf/invoices/SAMPLECONF-00001/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: text/javascript
|
||||
|
||||
{
|
||||
"number": "SAMPLECONF-00001",
|
||||
"order": "ABC12",
|
||||
"is_cancellation": false,
|
||||
"invoice_from": "Big Events LLC\nDemo street 12\nDemo town",
|
||||
"invoice_to": "Sample company\nJohn Doe\nTest street 12\n12345 Testington\nTestikistan\nVAT ID: EU123456789",
|
||||
"date": "2017-12-01",
|
||||
"refers": null,
|
||||
"locale": "en",
|
||||
"introductory_text": "thank you for your purchase of the following items:",
|
||||
"additional_text": "We are looking forward to see you on our conference!",
|
||||
"payment_provider_text": "Please transfer the money to our account ABC…",
|
||||
"footer_text": "Big Events LLC - Registration No. 123456 - VAT ID: EU0987654321",
|
||||
"lines": [
|
||||
{
|
||||
"description": "Budget Ticket",
|
||||
"gross_value": "23.00",
|
||||
"tax_value": "0.00",
|
||||
"tax_rate": "0.00"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:param invoice_no: The ``invoice_no`` field of the invoice to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/invoices/(invoice_no)/download/
|
||||
|
||||
Download an invoice in PDF format.
|
||||
|
||||
Note that in some cases the PDF file might not yet have been created. In that case, you will receive a status
|
||||
code :http:statuscode:`409` and you are expected to retry the request after a short period of waiting.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/sampleconf/invoices/00001/download/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/pdf
|
||||
|
||||
...
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:param invoice_no: The ``invoice_no`` field of the invoice to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
|
||||
:statuscode 409: The file is not yet ready and will now be prepared. Retry the request after waiting vor a few
|
||||
seconds.
|
||||
228
doc/api/resources/items.rst
Normal file
@@ -0,0 +1,228 @@
|
||||
Items
|
||||
=====
|
||||
|
||||
Resource description
|
||||
--------------------
|
||||
|
||||
Items (better known as products) are the things that can be sold using pretix.
|
||||
The item resource contains the following public fields:
|
||||
|
||||
.. rst-class:: rest-resource-table
|
||||
|
||||
===================================== ========================== =======================================================
|
||||
Field Type Description
|
||||
===================================== ========================== =======================================================
|
||||
id integer Internal ID of the item
|
||||
name multi-lingual string The item's visible name
|
||||
default_price money (string) The item price that is applied if the price is not
|
||||
overwritten by variations or other options.
|
||||
category integer The ID of the category this item belongs to
|
||||
(or ``null``).
|
||||
active boolean If ``False``, the item is hidden from all public lists
|
||||
and will not be sold.
|
||||
description multi-lingual string A public description of the item. May contain Markdown
|
||||
syntax or can be ``null``.
|
||||
free_price boolean If ``True``, customers can change the price at which
|
||||
they buy the product (however, the price can't be set
|
||||
lower than the price defined by ``default_price`` or
|
||||
otherwise).
|
||||
tax_rate decimal (string) The VAT rate to be applied for this item.
|
||||
admission boolean ``True`` for items that grant admission to the event
|
||||
(such as primary tickets) and ``False`` for others
|
||||
(such as add-ons or merchandise).
|
||||
position integer An integer, used for sorting
|
||||
picture string A product picture to be displayed in the shop
|
||||
available_from datetime The first date time at which this item can be bought
|
||||
(or ``null``).
|
||||
available_until datetime The last date time at which this item can be bought
|
||||
(or ``null``).
|
||||
require_voucher boolean If ``True``, this item can only be bought using a
|
||||
voucher that is specifically assigned to this item.
|
||||
hide_without_voucher boolean If ``True``, this item is only shown during the voucher
|
||||
redemption process, but not in the normal shop
|
||||
frontend.
|
||||
allow_cancel boolean If ``False``, customers cannot cancel orders containing
|
||||
this item.
|
||||
min_per_order integer This product can only be bought if it is included at
|
||||
least this many times in the order (or ``null`` for no
|
||||
limitation).
|
||||
max_per_order integer This product can only be bought if it is included at
|
||||
most this many times in the order (or ``null`` for no
|
||||
limitation).
|
||||
has_variations boolean Shows whether or not this item has variations
|
||||
(read-only).
|
||||
variations list of objects A list with one object for each variation of this item.
|
||||
Can be empty.
|
||||
├ id integer Internal ID of the variation
|
||||
├ default_price money (string) The price set directly for this variation or ``null``
|
||||
├ price money (string) The price used for this variation. This is either the
|
||||
same as ``default_price`` if that value is set or equal
|
||||
to the item's ``default_price``.
|
||||
├ active boolean If ``False``, this variation will not be sold or shown.
|
||||
├ description multi-lingual string A public description of the variation. May contain
|
||||
Markdown syntax or can be ``null``.
|
||||
└ position integer An integer, used for sorting
|
||||
addons list of objects Definition of add-ons that can be chosen for this item
|
||||
├ addon_category integer Internal ID of the item category the add-on can be
|
||||
chosen from.
|
||||
├ min_count integer The minimal number of add-ons that need to be chosen.
|
||||
├ max_count integer The maxima number of add-ons that can be chosen.
|
||||
└ position integer An integer, used for sorting
|
||||
===================================== ========================== =======================================================
|
||||
|
||||
|
||||
Endpoints
|
||||
---------
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/items/
|
||||
|
||||
Returns a list of all items within a given event.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/sampleconf/items/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: text/javascript
|
||||
|
||||
{
|
||||
"count": 1,
|
||||
"next": null,
|
||||
"previous": null,
|
||||
"results": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": {"en": "Standard ticket"},
|
||||
"default_price": "23.00",
|
||||
"category": null,
|
||||
"active": true,
|
||||
"description": null,
|
||||
"free_price": false,
|
||||
"tax_rate": "0.00",
|
||||
"admission": false,
|
||||
"position": 0,
|
||||
"picture": null,
|
||||
"available_from": null,
|
||||
"available_until": null,
|
||||
"require_voucher": false,
|
||||
"hide_without_voucher": false,
|
||||
"allow_cancel": true,
|
||||
"min_per_order": null,
|
||||
"max_per_order": null,
|
||||
"has_variations": false,
|
||||
"variations": [
|
||||
{
|
||||
"value": {"en": "Student"},
|
||||
"default_price": "10.00",
|
||||
"price": "10.00",
|
||||
"active": true,
|
||||
"description": null,
|
||||
"position": 0
|
||||
},
|
||||
{
|
||||
"value": {"en": "Regular"},
|
||||
"default_price": null,
|
||||
"price": "23.00",
|
||||
"active": true,
|
||||
"description": null,
|
||||
"position": 1
|
||||
}
|
||||
],
|
||||
"addons": []
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
:query integer page: The page number in case of a multi-page result set, default is 1
|
||||
:query boolean active: If set to ``true`` or ``false``, only items with this value for the field ``active`` will be
|
||||
returned.
|
||||
:query integer category: If set to the ID of a category, only items within that category will be returned.
|
||||
:query boolean admission: If set to ``true`` or ``false``, only items with this value for the field ``admission``
|
||||
will be returned.
|
||||
:query string tax_rate: If set to a decimal value, only items with this tax rate will be returned.
|
||||
:query boolean free_price: If set to ``true`` or ``false``, only items with this value for the field ``free_price``
|
||||
will be returned.
|
||||
:query string ordering: Manually set the ordering of results. Valid fields to be used are ``id`` and ``position``.
|
||||
Default: ``position``
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/items/(id)/
|
||||
|
||||
Returns information on one item, identified by its ID.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/sampleconf/items/1/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: text/javascript
|
||||
|
||||
{
|
||||
"id": 1,
|
||||
"name": {"en": "Standard ticket"},
|
||||
"default_price": "23.00",
|
||||
"category": null,
|
||||
"active": true,
|
||||
"description": null,
|
||||
"free_price": false,
|
||||
"tax_rate": "0.00",
|
||||
"admission": false,
|
||||
"position": 0,
|
||||
"picture": null,
|
||||
"available_from": null,
|
||||
"available_until": null,
|
||||
"require_voucher": false,
|
||||
"hide_without_voucher": false,
|
||||
"allow_cancel": true,
|
||||
"min_per_order": null,
|
||||
"max_per_order": null,
|
||||
"has_variations": false,
|
||||
"variations": [
|
||||
{
|
||||
"value": {"en": "Student"},
|
||||
"default_price": "10.00",
|
||||
"price": "10.00",
|
||||
"active": true,
|
||||
"description": null,
|
||||
"position": 0
|
||||
},
|
||||
{
|
||||
"value": {"en": "Regular"},
|
||||
"default_price": null,
|
||||
"price": "23.00",
|
||||
"active": true,
|
||||
"description": null,
|
||||
"position": 1
|
||||
}
|
||||
],
|
||||
"addons": []
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:param id: The ``id`` field of the item to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
|
||||
530
doc/api/resources/orders.rst
Normal file
@@ -0,0 +1,530 @@
|
||||
Orders
|
||||
======
|
||||
|
||||
Order resource
|
||||
--------------
|
||||
|
||||
The order resource contains the following public fields:
|
||||
|
||||
.. rst-class:: rest-resource-table
|
||||
|
||||
===================================== ========================== =======================================================
|
||||
Field Type Description
|
||||
===================================== ========================== =======================================================
|
||||
code string Order code
|
||||
status string Order status, one of:
|
||||
|
||||
* ``n`` – pending
|
||||
* ``p`` – paid
|
||||
* ``e`` – expired
|
||||
* ``c`` – canceled
|
||||
* ``r`` – refunded
|
||||
secret string The secret contained in the link sent to the customer
|
||||
email string The customer email address
|
||||
locale string The locale used for communication with this customer
|
||||
datetime datetime Time of order creation
|
||||
expires datetime The order will expire, if it is still pending by this time
|
||||
payment_date date Date of payment receival
|
||||
payment_provider string Payment provider used for this order
|
||||
payment_fee money (string) Payment fee included in this order's total
|
||||
payment_fee_tax_rate decimal (string) VAT rate applied to the payment fee
|
||||
payment_fee_tax_value money (string) VAT value included in the payment fee
|
||||
total money (string) Total value of this order
|
||||
comment string Internal comment on this order
|
||||
invoice_address object Invoice address information (can be ``null``)
|
||||
├ last_modified datetime Last modification date of the address
|
||||
├ company string Customer company name
|
||||
├ name string Customer name
|
||||
├ street string Customer street
|
||||
├ zipcode string Customer ZIP code
|
||||
├ city string Customer city
|
||||
├ country string Customer country
|
||||
└ vat_id string Customer VAT ID
|
||||
position list of objects List of order positions (see below)
|
||||
downloads list of objects List of ticket download options for order-wise ticket
|
||||
downloading. This might be a multi-page PDF or a ZIP
|
||||
file of tickets for outputs that do not support
|
||||
multiple tickets natively. See also order position
|
||||
download options.
|
||||
├ output string Ticket output provider (e.g. ``pdf``, ``passbook``)
|
||||
└ url string Download URL
|
||||
===================================== ========================== =======================================================
|
||||
|
||||
|
||||
.. versionchanged:: 1.6
|
||||
|
||||
The ``invoice_address.country`` attribute contains a two-letter country code for all new orders. For old orders,
|
||||
a custom text might still be returned.
|
||||
|
||||
|
||||
Order position resource
|
||||
-----------------------
|
||||
|
||||
.. rst-class:: rest-resource-table
|
||||
|
||||
===================================== ========================== =======================================================
|
||||
Field Type Description
|
||||
===================================== ========================== =======================================================
|
||||
id integer Internal ID of the order positon
|
||||
code string Order code of the order the position belongs to
|
||||
positionid integer Number of the position within the order
|
||||
item integer ID of the purchased item
|
||||
variation integer ID of the purchased variation (or ``null``)
|
||||
price money (string) Price of this position
|
||||
attendee_name string Specified attendee name for this position (or ``null``)
|
||||
attendee_email string Specified attendee email address for this position (or ``null``)
|
||||
voucher integer Internal ID of the voucher used for this position (or ``null``)
|
||||
tax_rate decimal (string) VAT rate applied for this position
|
||||
tax_value money (string) VAT included in this position
|
||||
secret string Secret code printed on the tickets for validation
|
||||
addon_to integer Internal ID of the position this position is an add-on for (or ``null``)
|
||||
subevent integer ID of the date inside an event series this position belongs to (or ``null``).
|
||||
checkins list of objects List of check-ins with this ticket
|
||||
└ datetime datetime Time of check-in
|
||||
downloads list of objects List of ticket download options
|
||||
├ output string Ticket output provider (e.g. ``pdf``, ``passbook``)
|
||||
└ url string Download URL
|
||||
answers list of objects Answers to user-defined questions
|
||||
├ question integer Internal ID of the answered question
|
||||
├ answer string Text representation of the answer
|
||||
└ options list of integers Internal IDs of selected option(s)s (only for choice types)
|
||||
===================================== ========================== =======================================================
|
||||
|
||||
|
||||
Order endpoints
|
||||
---------------
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/orders/
|
||||
|
||||
Returns a list of all orders within a given event.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/sampleconf/orders/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: text/javascript
|
||||
|
||||
{
|
||||
"count": 1,
|
||||
"next": null,
|
||||
"previous": null,
|
||||
"results": [
|
||||
{
|
||||
"code": "ABC12",
|
||||
"status": "p",
|
||||
"secret": "k24fiuwvu8kxz3y1",
|
||||
"email": "tester@example.org",
|
||||
"locale": "en",
|
||||
"datetime": "2017-12-01T10:00:00Z",
|
||||
"expires": "2017-12-10T10:00:00Z",
|
||||
"payment_date": "2017-12-05",
|
||||
"payment_provider": "banktransfer",
|
||||
"payment_fee": "0.00",
|
||||
"payment_fee_tax_rate": "0.00",
|
||||
"payment_fee_tax_value": "0.00",
|
||||
"total": "23.00",
|
||||
"comment": "",
|
||||
"invoice_address": {
|
||||
"last_modified": "2017-12-01T10:00:00Z",
|
||||
"company": "Sample company",
|
||||
"name": "John Doe",
|
||||
"street": "Test street 12",
|
||||
"zipcode": "12345",
|
||||
"city": "Testington",
|
||||
"country": "Testikistan",
|
||||
"vat_id": "EU123456789"
|
||||
},
|
||||
"positions": [
|
||||
{
|
||||
"id": 23442,
|
||||
"order": "ABC12",
|
||||
"positionid": 1,
|
||||
"item": 1345,
|
||||
"variation": null,
|
||||
"price": "23.00",
|
||||
"attendee_name": "Peter",
|
||||
"attendee_email": null,
|
||||
"voucher": null,
|
||||
"tax_rate": "0.00",
|
||||
"tax_value": "0.00",
|
||||
"secret": "z3fsn8jyufm5kpk768q69gkbyr5f4h6w",
|
||||
"addon_to": null,
|
||||
"subevent": null,
|
||||
"checkins": [
|
||||
{
|
||||
"datetime": "2017-12-25T12:45:23Z"
|
||||
}
|
||||
],
|
||||
"answers": [
|
||||
{
|
||||
"question": 12,
|
||||
"answer": "Foo",
|
||||
"options": []
|
||||
}
|
||||
],
|
||||
"downloads": [
|
||||
{
|
||||
"output": "pdf",
|
||||
"url": "https://pretix.eu/api/v1/organizers/bigevents/events/sampleconf/orderpositions/23442/download/pdf/"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"downloads": [
|
||||
{
|
||||
"output": "pdf",
|
||||
"url": "https://pretix.eu/api/v1/organizers/bigevents/events/sampleconf/orders/ABC12/download/pdf/"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
:query integer page: The page number in case of a multi-page result set, default is 1
|
||||
:query string ordering: Manually set the ordering of results. Valid fields to be used are ``datetime``, ``code`` and
|
||||
``status``. Default: ``datetime``
|
||||
:query string code: Only return orders that match the given order code
|
||||
:query string status: Only return orders in the given order status (see above)
|
||||
:query string email: Only return orders created with the given email address
|
||||
:query string locale: Only return orders with the given customer locale
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/orders/(code)/
|
||||
|
||||
Returns information on one order, identified by its order code.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/sampleconf/orders/ABC12/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: text/javascript
|
||||
|
||||
{
|
||||
"code": "ABC12",
|
||||
"status": "p",
|
||||
"secret": "k24fiuwvu8kxz3y1",
|
||||
"email": "tester@example.org",
|
||||
"locale": "en",
|
||||
"datetime": "2017-12-01T10:00:00Z",
|
||||
"expires": "2017-12-10T10:00:00Z",
|
||||
"payment_date": "2017-12-05",
|
||||
"payment_provider": "banktransfer",
|
||||
"payment_fee": "0.00",
|
||||
"payment_fee_tax_rate": "0.00",
|
||||
"payment_fee_tax_value": "0.00",
|
||||
"total": "23.00",
|
||||
"comment": "",
|
||||
"invoice_address": {
|
||||
"last_modified": "2017-12-01T10:00:00Z",
|
||||
"company": "Sample company",
|
||||
"name": "John Doe",
|
||||
"street": "Test street 12",
|
||||
"zipcode": "12345",
|
||||
"city": "Testington",
|
||||
"country": "Testikistan",
|
||||
"vat_id": "EU123456789"
|
||||
},
|
||||
"positions": [
|
||||
{
|
||||
"id": 23442,
|
||||
"order": "ABC12",
|
||||
"positionid": 1,
|
||||
"item": 1345,
|
||||
"variation": null,
|
||||
"price": "23.00",
|
||||
"attendee_name": "Peter",
|
||||
"attendee_email": null,
|
||||
"voucher": null,
|
||||
"tax_rate": "0.00",
|
||||
"tax_value": "0.00",
|
||||
"secret": "z3fsn8jyufm5kpk768q69gkbyr5f4h6w",
|
||||
"addon_to": null,
|
||||
"subevent": null,
|
||||
"checkins": [
|
||||
{
|
||||
"datetime": "2017-12-25T12:45:23Z"
|
||||
}
|
||||
],
|
||||
"answers": [
|
||||
{
|
||||
"question": 12,
|
||||
"answer": "Foo",
|
||||
"options": []
|
||||
}
|
||||
],
|
||||
"downloads": [
|
||||
{
|
||||
"output": "pdf",
|
||||
"url": "https://pretix.eu/api/v1/organizers/bigevents/events/sampleconf/orderpositions/23442/download/pdf/"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"downloads": [
|
||||
{
|
||||
"output": "pdf",
|
||||
"url": "https://pretix.eu/api/v1/organizers/bigevents/events/sampleconf/orders/ABC12/download/pdf/"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:param code: The ``code`` field of the order to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/orders/(code)/download/(output)/
|
||||
|
||||
Download tickets for an order, identified by its order code. Depending on the chosen output, the response might
|
||||
be a ZIP file, PDF file or something else. The order details response contains a list of output options for this
|
||||
partictular order.
|
||||
|
||||
Tickets can be only downloaded if the order is paid and if ticket downloads are active. Note that in some cases the
|
||||
ticket file might not yet have been created. In that case, you will receive a status code :http:statuscode:`409` and
|
||||
you are expected to retry the request after a short period of waiting.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/sampleconf/orders/ABC12/download/pdf/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/pdf
|
||||
|
||||
...
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:param code: The ``code`` field of the order to fetch
|
||||
:param output: The internal name of the output provider to use
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource
|
||||
**or** downlodas are not available for this order at this time. The response content will
|
||||
contain more details.
|
||||
:statuscode 409: The file is not yet ready and will now be prepared. Retry the request after waiting vor a few
|
||||
seconds.
|
||||
|
||||
|
||||
Order position endpoints
|
||||
------------------------
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/orderpositions/
|
||||
|
||||
Returns a list of all order positions within a given event.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/sampleconf/orderpositions/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: text/javascript
|
||||
|
||||
{
|
||||
"count": 1,
|
||||
"next": null,
|
||||
"previous": null,
|
||||
"results": [
|
||||
{
|
||||
"id": 23442,
|
||||
"order": "ABC12",
|
||||
"positionid": 1,
|
||||
"item": 1345,
|
||||
"variation": null,
|
||||
"price": "23.00",
|
||||
"attendee_name": "Peter",
|
||||
"attendee_email": null,
|
||||
"voucher": null,
|
||||
"tax_rate": "0.00",
|
||||
"tax_value": "0.00",
|
||||
"secret": "z3fsn8jyufm5kpk768q69gkbyr5f4h6w",
|
||||
"addon_to": null,
|
||||
"subevent": null,
|
||||
"checkins": [
|
||||
{
|
||||
"datetime": "2017-12-25T12:45:23Z"
|
||||
}
|
||||
],
|
||||
"answers": [
|
||||
{
|
||||
"question": 12,
|
||||
"answer": "Foo",
|
||||
"options": []
|
||||
}
|
||||
],
|
||||
"downloads": [
|
||||
{
|
||||
"output": "pdf",
|
||||
"url": "https://pretix.eu/api/v1/organizers/bigevents/events/sampleconf/orderpositions/23442/download/pdf/"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
:query integer page: The page number in case of a multi-page result set, default is 1
|
||||
:query string ordering: Manually set the ordering of results. Valid fields to be used are ``order__code``,
|
||||
``order__datetime``, ``positionid``, ``attendee_name``, and ``order__status``. Default:
|
||||
``order__datetime,positionid``
|
||||
:query string order: Only return positions of the order with the given order code
|
||||
:query integer item: Only return positions with the purchased item matching the given ID.
|
||||
:query integer variation: Only return positions with the purchased item variation matching the given ID.
|
||||
:query string attendee_name: Only return positions with the given value in the attendee_name field. Also, add-on
|
||||
products positions are shown if they refer to an attendee with the given name.
|
||||
:query string secret: Only return positions with the given ticket secret.
|
||||
:query string order__status: Only return positions with the given order status.
|
||||
:query bollean has_checkin: If set to ``true`` or ``false``, only return positions that have or have not been
|
||||
checked in already.
|
||||
:query integer subevent: Only return positions of the sub-event with the given ID
|
||||
:query integer addon_to: Only return positions that are add-ons to the position with the given ID.
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/orderpositions/(id)/
|
||||
|
||||
Returns information on one order position, identified by its internal ID.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/sampleconf/orderpositions/23442/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: text/javascript
|
||||
|
||||
{
|
||||
"id": 23442,
|
||||
"order": "ABC12",
|
||||
"positionid": 1,
|
||||
"item": 1345,
|
||||
"variation": null,
|
||||
"price": "23.00",
|
||||
"attendee_name": "Peter",
|
||||
"attendee_email": null,
|
||||
"voucher": null,
|
||||
"tax_rate": "0.00",
|
||||
"tax_value": "0.00",
|
||||
"secret": "z3fsn8jyufm5kpk768q69gkbyr5f4h6w",
|
||||
"addon_to": null,
|
||||
"subevent": null,
|
||||
"checkins": [
|
||||
{
|
||||
"datetime": "2017-12-25T12:45:23Z"
|
||||
}
|
||||
],
|
||||
"answers": [
|
||||
{
|
||||
"question": 12,
|
||||
"answer": "Foo",
|
||||
"options": []
|
||||
}
|
||||
],
|
||||
"downloads": [
|
||||
{
|
||||
"output": "pdf",
|
||||
"url": "https://pretix.eu/api/v1/organizers/bigevents/events/sampleconf/orderpositions/23442/download/pdf/"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:param id: The ``id`` field of the order position to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/orderpositions/(id)/download/(output)/
|
||||
|
||||
Download tickets for one order position, identified by its internal ID.
|
||||
Depending on the chosen output, the response might be a ZIP file, PDF file or something else. The order details
|
||||
response contains a list of output options for this partictular order position.
|
||||
|
||||
Tickets can be only downloaded if the order is paid and if ticket downloads are active. Also, depending on event
|
||||
configuration downloads might be only unavailable for add-on products or non-admission products.
|
||||
Note that in some cases the ticket file might not yet have been created. In that case, you will receive a status
|
||||
code :http:statuscode:`409` and you are expected to retry the request after a short period of waiting.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/sampleconf/orderpositions/23442/download/pdf/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: application/pdf
|
||||
|
||||
...
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:param id: The ``id`` field of the order position to fetch
|
||||
:param output: The internal name of the output provider to use
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource
|
||||
**or** downlodas are not available for this order position at this time. The response content will
|
||||
contain more details.
|
||||
:statuscode 409: The file is not yet ready and will now be prepared. Retry the request after waiting vor a few
|
||||
seconds.
|
||||
90
doc/api/resources/organizers.rst
Normal file
@@ -0,0 +1,90 @@
|
||||
Organizers
|
||||
==========
|
||||
|
||||
Resource description
|
||||
--------------------
|
||||
|
||||
An organizers is an entity running any number of events. In pretix, every event belongs to one
|
||||
organizer and various settings, such as teams and permissions, are managed on organizer level.
|
||||
|
||||
The organizer resource contains the following public fields:
|
||||
|
||||
.. rst-class:: rest-resource-table
|
||||
|
||||
===================================== ========================== =======================================================
|
||||
Field Type Description
|
||||
===================================== ========================== =======================================================
|
||||
name string The organizer's full name, i.e. the name of an
|
||||
organization or company.
|
||||
slug string A short form of the name, used e.g. in URLs.
|
||||
===================================== ========================== =======================================================
|
||||
|
||||
|
||||
Endpoints
|
||||
---------
|
||||
|
||||
.. http:get:: /api/v1/organizers/
|
||||
|
||||
Returns a list of all organizers the authenticated user/token has access to.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: text/javascript
|
||||
|
||||
{
|
||||
"count": 1,
|
||||
"next": null,
|
||||
"previous": null,
|
||||
"results": [
|
||||
{
|
||||
"name": "Big Events LLC",
|
||||
"slug": "Big Events",
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
:query page: The page number in case of a multi-page result set, default is 1
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/
|
||||
|
||||
Returns information on one organizer account, identified by its slug.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: text/javascript
|
||||
|
||||
{
|
||||
"name": "Big Events LLC",
|
||||
"slug": "Big Events",
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer does not exist **or** you have no permission to view it.
|
||||
146
doc/api/resources/questions.rst
Normal file
@@ -0,0 +1,146 @@
|
||||
Questions
|
||||
=========
|
||||
|
||||
Resource description
|
||||
--------------------
|
||||
|
||||
Questions define additional fields that need to be filled out by customers during checkout.
|
||||
The question resource contains the following public fields:
|
||||
|
||||
.. rst-class:: rest-resource-table
|
||||
|
||||
===================================== ========================== =======================================================
|
||||
Field Type Description
|
||||
===================================== ========================== =======================================================
|
||||
id integer Internal ID of the question
|
||||
question multi-lingual string The field label shown to the customer
|
||||
type string The expected type of answer. Valid options:
|
||||
|
||||
* ``N`` – number
|
||||
* ``S`` – one-line string
|
||||
* ``T`` – multi-line string
|
||||
* ``B`` – boolean
|
||||
* ``C`` – choice from a list
|
||||
* ``M`` – multiple choice from a list
|
||||
* ``F`` – file upload
|
||||
required boolean If ``True``, the question needs to be filled out.
|
||||
position integer An integer, used for sorting
|
||||
items list of integers List of item IDs this question is assigned to.
|
||||
options list of objects In case of question type ``C`` or ``M``, this lists the
|
||||
available objects.
|
||||
├ id integer Internal ID of the option
|
||||
└ answer multi-lingual string The displayed value of this option
|
||||
===================================== ========================== =======================================================
|
||||
|
||||
|
||||
Endpoints
|
||||
---------
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/questions/
|
||||
|
||||
Returns a list of all questions within a given event.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/sampleconf/questions/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: text/javascript
|
||||
|
||||
{
|
||||
"count": 1,
|
||||
"next": null,
|
||||
"previous": null,
|
||||
"results": [
|
||||
{
|
||||
"id": 1,
|
||||
"question": {"en": "T-Shirt size"},
|
||||
"type": "C",
|
||||
"required": false,
|
||||
"items": [1, 2],
|
||||
"position": 1,
|
||||
"options": [
|
||||
{
|
||||
"id": 1,
|
||||
"answer": {"en": "S"}
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"answer": {"en": "M"}
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"answer": {"en": "L"}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
:query integer page: The page number in case of a multi-page result set, default is 1
|
||||
:query string ordering: Manually set the ordering of results. Valid fields to be used are ``id`` and ``position``.
|
||||
Default: ``position``
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/questions/(id)/
|
||||
|
||||
Returns information on one question, identified by its ID.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/sampleconf/questions/1/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: text/javascript
|
||||
|
||||
{
|
||||
"id": 1,
|
||||
"question": {"en": "T-Shirt size"},
|
||||
"type": "C",
|
||||
"required": false,
|
||||
"items": [1, 2],
|
||||
"position": 1,
|
||||
"options": [
|
||||
{
|
||||
"id": 1,
|
||||
"answer": {"en": "S"}
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"answer": {"en": "M"}
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"answer": {"en": "L"}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:param id: The ``id`` field of the question to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
|
||||
147
doc/api/resources/quotas.rst
Normal file
@@ -0,0 +1,147 @@
|
||||
Quotas
|
||||
======
|
||||
|
||||
Resource description
|
||||
--------------------
|
||||
|
||||
Questions define how many times an item can be sold.
|
||||
The quota resource contains the following public fields:
|
||||
|
||||
.. rst-class:: rest-resource-table
|
||||
|
||||
===================================== ========================== =======================================================
|
||||
Field Type Description
|
||||
===================================== ========================== =======================================================
|
||||
id integer Internal ID of the quota
|
||||
name string The internal name of the quota
|
||||
size integer The size of the quota or ``null`` for unlimited
|
||||
items list of integers List of item IDs this quota acts on.
|
||||
variations list of integers List of item variation IDs this quota acts on.
|
||||
subevent integer ID of the date inside an event series this quota belongs to (or ``null``).
|
||||
===================================== ========================== =======================================================
|
||||
|
||||
|
||||
Endpoints
|
||||
---------
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/quotas/
|
||||
|
||||
Returns a list of all quotas within a given event.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/sampleconf/quotas/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: text/javascript
|
||||
|
||||
{
|
||||
"count": 1,
|
||||
"next": null,
|
||||
"previous": null,
|
||||
"results": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Ticket Quota",
|
||||
"size": 200,
|
||||
"items": [1, 2],
|
||||
"variations": [1, 4, 5, 7],
|
||||
"subevent": null
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
:query integer page: The page number in case of a multi-page result set, default is 1
|
||||
:query string ordering: Manually set the ordering of results. Valid fields to be used are ``id`` and ``position``.
|
||||
Default: ``position``
|
||||
:query integer subevent: Only return quotas of the sub-event with the given ID
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/quotas/(id)/
|
||||
|
||||
Returns information on one quota, identified by its ID.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/sampleconf/quotas/1/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: text/javascript
|
||||
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Ticket Quota",
|
||||
"size": 200,
|
||||
"items": [1, 2],
|
||||
"variations": [1, 4, 5, 7],
|
||||
"subevent": null
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:param id: The ``id`` field of the quota to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/quotas/(id)/availability/
|
||||
|
||||
Returns availability information on one quota, identified by its ID.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/sampleconf/quotas/1/availability/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: text/javascript
|
||||
|
||||
{
|
||||
"available": true,
|
||||
"available_number": 419,
|
||||
"total_size": 1000,
|
||||
"pending_orders": 25,
|
||||
"paid_orders": 423,
|
||||
"cart_positions": 7,
|
||||
"blocking_vouchers": 126,
|
||||
"waiting_list": 0
|
||||
}
|
||||
|
||||
Note that ``total_size`` and ``available_number`` are ``null`` in case of unlimited quotas.
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:param id: The ``id`` field of the quota to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
|
||||
137
doc/api/resources/subevents.rst
Normal file
@@ -0,0 +1,137 @@
|
||||
Event series dates / Sub-events
|
||||
===============================
|
||||
|
||||
Resource description
|
||||
--------------------
|
||||
|
||||
Events can represent whole event series if the ``has_subevents`` property of the event is active.
|
||||
In this case, many other resources are additionally connected to an event date (also called sub-event).
|
||||
The sub-event resource contains the following public fields:
|
||||
|
||||
.. rst-class:: rest-resource-table
|
||||
|
||||
===================================== ========================== =======================================================
|
||||
Field Type Description
|
||||
===================================== ========================== =======================================================
|
||||
id integer Internal ID of the sub-event
|
||||
name multi-lingual string The sub-event's full name
|
||||
active boolean If ``true``, the sub-event ticket shop is publicly
|
||||
available.
|
||||
date_from datetime The sub-event's start date
|
||||
date_to datetime The sub-event's end date (or ``null``)
|
||||
date_admission datetime The sub-event's admission date (or ``null``)
|
||||
presale_start datetime The sub-date at which the ticket shop opens (or ``null``)
|
||||
presale_end datetime The sub-date at which the ticket shop closes (or ``null``)
|
||||
location multi-lingual string The sub-event location (or ``null``)
|
||||
item_price_overrides list of objects List of items for which this sub-event overrides the
|
||||
default price
|
||||
├ item integer The internal item ID
|
||||
└ price money (string) The price or ``null`` for the default price
|
||||
variation_price_overrides list of objects List of variations for which this sub-event overrides
|
||||
the default price
|
||||
├ variation integer The internal variation ID
|
||||
└ price money (string) The price or ``null`` for the default price
|
||||
===================================== ========================== =======================================================
|
||||
|
||||
|
||||
Endpoints
|
||||
---------
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/subevents/
|
||||
|
||||
Returns a list of all sub-events of an event.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/sampleconf/subevents/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: text/javascript
|
||||
|
||||
{
|
||||
"count": 1,
|
||||
"next": null,
|
||||
"previous": null,
|
||||
"results": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": {"en": "First Sample Conference"},
|
||||
"active": false,
|
||||
"date_from": "2017-12-27T10:00:00Z",
|
||||
"date_to": null,
|
||||
"date_admission": null,
|
||||
"presale_start": null,
|
||||
"presale_end": null,
|
||||
"location": null,
|
||||
"item_price_overrides": [
|
||||
{
|
||||
"item": 2,
|
||||
"price": "12.00"
|
||||
}
|
||||
],
|
||||
"variation_price_overrides": []
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
:query page: The page number in case of a multi-page result set, default is 1
|
||||
:param organizer: The ``slug`` field of a valid organizer
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer does not exist **or** you have no permission to view it.
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/subevents/(id)/
|
||||
|
||||
Returns information on one sub-event, identified by its ID.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/sampleconf/subevents/1/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: text/javascript
|
||||
|
||||
{
|
||||
"id": 1,
|
||||
"name": {"en": "First Sample Conference"},
|
||||
"active": false,
|
||||
"date_from": "2017-12-27T10:00:00Z",
|
||||
"date_to": null,
|
||||
"date_admission": null,
|
||||
"presale_start": null,
|
||||
"presale_end": null,
|
||||
"location": null,
|
||||
"item_price_overrides": [
|
||||
{
|
||||
"item": 2,
|
||||
"price": "12.00"
|
||||
}
|
||||
],
|
||||
"variation_price_overrides": []
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:param id: The ``slug`` field of the sub-event to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view it.
|
||||
164
doc/api/resources/vouchers.rst
Normal file
@@ -0,0 +1,164 @@
|
||||
Vouchers
|
||||
========
|
||||
|
||||
Resource description
|
||||
--------------------
|
||||
|
||||
The voucher resource contains the following public fields:
|
||||
|
||||
.. rst-class:: rest-resource-table
|
||||
|
||||
===================================== ========================== =======================================================
|
||||
Field Type Description
|
||||
===================================== ========================== =======================================================
|
||||
id integer Internal ID of the voucher
|
||||
code string The voucher code that is required to redeem the voucher
|
||||
max_usages integer The maximum number of times this voucher can be
|
||||
redeemed (default: 1).
|
||||
redeemed integer The number of times this voucher already has been
|
||||
redeemed.
|
||||
valid_until datetime The voucher expiration date (or ``null``).
|
||||
block_quota boolean If ``True``, quota is blocked for this voucher.
|
||||
allow_ignore_quota boolean If ``True``, this voucher can be redeemed even if a
|
||||
product is sold out and even if quota is not blocked
|
||||
for this voucher.
|
||||
price_mode string Determines how this voucher affects product prices.
|
||||
Possible values:
|
||||
|
||||
* ``none`` – No effect on price
|
||||
* ``set`` – The product price is set to the given ``value``
|
||||
* ``subtract`` – The product price is determined by the original price *minus* the given ``value``
|
||||
* ``percent`` – The product price is determined by the original price reduced by the percentage given in ``value``
|
||||
value decimal (string) The value (see ``price_mode``)
|
||||
item integer An ID of an item this voucher is restricted to (or ``null``)
|
||||
variation integer An ID of a variation this voucher is restricted to (or ``null``)
|
||||
quota integer An ID of a quota this voucher is restricted to (or
|
||||
``null``). This is an exclusive alternative to
|
||||
``item`` and ``variation``: A voucher can be
|
||||
attached either to a specific product or to all
|
||||
products within one quota or it can be available
|
||||
for all items without restriction.
|
||||
tag string A string that is used for grouping vouchers
|
||||
comment string An internal comment on the voucher
|
||||
subevent integer ID of the date inside an event series this voucher belongs to (or ``null``).
|
||||
===================================== ========================== =======================================================
|
||||
|
||||
|
||||
Endpoints
|
||||
---------
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/vouchers/
|
||||
|
||||
Returns a list of all vouchers within a given event.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/sampleconf/vouchers/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: text/javascript
|
||||
|
||||
{
|
||||
"count": 1,
|
||||
"next": null,
|
||||
"previous": null,
|
||||
"results": [
|
||||
{
|
||||
"id": 1,
|
||||
"code": "43K6LKM37FBVR2YG",
|
||||
"max_usages": 1,
|
||||
"redeemed": 0,
|
||||
"valid_until": null,
|
||||
"block_quota": false,
|
||||
"allow_ignore_quota": false,
|
||||
"price_mode": "set",
|
||||
"value": "12.00",
|
||||
"item": 1,
|
||||
"variation": null,
|
||||
"quota": null,
|
||||
"tag": "testvoucher",
|
||||
"comment": "",
|
||||
"subevent": null
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
:query integer page: The page number in case of a multi-page result set, default is 1
|
||||
:query string code: Only show the voucher with the given voucher code.
|
||||
:query integer max_usages: Only show vouchers with the given maximal number of usages.
|
||||
:query integer redeemed: Only show vouchers with the given number of redemptions. Note that this doesn't tell you if
|
||||
the voucher can still be redeemed, as this also depends on ``max_usages``. See the
|
||||
``active`` query parameter as well.
|
||||
:query boolean block_quota: If set to ``true`` or ``false``, only vouchers with this value in the field
|
||||
``block_quota`` will be shown.
|
||||
:query boolean allow_ignore_quota: If set to ``true`` or ``false``, only vouchers with this value in the field
|
||||
``allow_ignore_quota`` will be shown.
|
||||
:query string price_mode: If set, only vouchers with this value in the field ``price_mode`` will be shown (see
|
||||
above).
|
||||
:query string value: If set, only vouchers with this value in the field ``value`` will be shown.
|
||||
:query integer item: If set, only vouchers attached to the item with the given ID will be shown.
|
||||
:query integer variation: If set, only vouchers attached to the variation with the given ID will be shown.
|
||||
:query integer quota: If set, only vouchers attached to the quota with the given ID will be shown.
|
||||
:query string tag: If set, only vouchers with the given tag will be shown.
|
||||
:query integer subevent: Only return vouchers of the sub-event with the given ID
|
||||
:query string ordering: Manually set the ordering of results. Valid fields to be used are ``id``, ``code``,
|
||||
``max_usages``, ``valid_until``, and ``value``. Default: ``id``
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/vouchers/(id)/
|
||||
|
||||
Returns information on one voucher, identified by its internal ID.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/sampleconf/vouchers/1/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: text/javascript
|
||||
|
||||
{
|
||||
"id": 1,
|
||||
"code": "43K6LKM37FBVR2YG",
|
||||
"max_usages": 1,
|
||||
"redeemed": 0,
|
||||
"valid_until": null,
|
||||
"block_quota": false,
|
||||
"allow_ignore_quota": false,
|
||||
"price_mode": "set",
|
||||
"value": "12.00",
|
||||
"item": 1,
|
||||
"variation": null,
|
||||
"quota": null,
|
||||
"tag": "testvoucher",
|
||||
"comment": "",
|
||||
"subevent": null
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:param id: The ``id`` field of the voucher to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
|
||||
123
doc/api/resources/waitinglist.rst
Normal file
@@ -0,0 +1,123 @@
|
||||
Waiting list entries
|
||||
====================
|
||||
|
||||
Resource description
|
||||
--------------------
|
||||
|
||||
The waiting list entry resource contains the following public fields:
|
||||
|
||||
.. rst-class:: rest-resource-table
|
||||
|
||||
===================================== ========================== =======================================================
|
||||
Field Type Description
|
||||
===================================== ========================== =======================================================
|
||||
id integer Internal ID of the waiting list entry
|
||||
created datetime Creation date of the waiting list entry
|
||||
email string Email address of the user on the waiting list
|
||||
voucher integer Internal ID of the voucher sent to this user. If
|
||||
this field is set, the user has been sent a voucher
|
||||
and is no longer waiting. If it is ``null``, the
|
||||
user is still waiting.
|
||||
item integer An ID of an item the user is waiting to be available
|
||||
again
|
||||
variation integer An ID of a variation the user is waiting to be
|
||||
available again (or ``null``)
|
||||
locale string Locale of the waiting user
|
||||
subevent integer ID of the date inside an event series this entry belongs to (or ``null``).
|
||||
===================================== ========================== =======================================================
|
||||
|
||||
|
||||
Endpoints
|
||||
---------
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/waitinglistentries/
|
||||
|
||||
Returns a list of all waiting list entries within a given event.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/sampleconf/waitinglistentries/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: text/javascript
|
||||
|
||||
{
|
||||
"count": 1,
|
||||
"next": null,
|
||||
"previous": null,
|
||||
"results": [
|
||||
{
|
||||
"id": 1,
|
||||
"created": "2017-12-01T10:00:00Z",
|
||||
"email": "waiting@example.org",
|
||||
"voucher": null,
|
||||
"item": 2,
|
||||
"variation": null,
|
||||
"locale": "en",
|
||||
"subevent": null
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
:query integer page: The page number in case of a multi-page result set, default is 1
|
||||
:query string email: Only show waiting list entries created with the given email address.
|
||||
:query string locale: Only show waiting list entries created with the given locale.
|
||||
:query boolean has_voucher: If set to ``true`` or ``false``, only waiting list entries are returned that have or
|
||||
have not been sent a voucher.
|
||||
:query integer item: If set, only entries of users waiting for the item with the given ID will be shown.
|
||||
:query integer variation: If set, only entries of users waiting for the variation with the given ID will be shown.
|
||||
:query integer subevent: Only return entries of the sub-event with the given ID
|
||||
:query string ordering: Manually set the ordering of results. Valid fields to be used are ``id``, ``created``,
|
||||
``email``, ``item``. Default: ``created``
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/events/(event)/waitinglistentries/(id)/
|
||||
|
||||
Returns information on one waiting list entry, identified by its internal ID.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/events/sampleconf/waitinglistentries/1/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: text/javascript
|
||||
|
||||
{
|
||||
"id": 1,
|
||||
"created": "2017-12-01T10:00:00Z",
|
||||
"email": "waiting@example.org",
|
||||
"voucher": null,
|
||||
"item": 2,
|
||||
"variation": null,
|
||||
"locale": "en",
|
||||
"subevent": null
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:param event: The ``slug`` field of the event to fetch
|
||||
:param id: The ``id`` field of the waiting list entry to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view this resource.
|
||||
40
doc/conf.py
@@ -19,10 +19,12 @@ import os
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
from datetime import date
|
||||
|
||||
sys.path.insert(0, os.path.abspath('../src'))
|
||||
|
||||
import django
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "pretix.settings")
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "pretix.testutils.settings")
|
||||
django.setup()
|
||||
|
||||
# -- General configuration ------------------------------------------------
|
||||
@@ -51,20 +53,21 @@ source_suffix = '.rst'
|
||||
#source_encoding = 'utf-8-sig'
|
||||
|
||||
# The master toctree document.
|
||||
master_doc = 'index'
|
||||
master_doc = 'contents'
|
||||
|
||||
# General information about the project.
|
||||
project = 'pretix'
|
||||
copyright = '2014-2016, Raphael Michel'
|
||||
copyright = '2014-{}, Raphael Michel'.format(date.today().year)
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = '0.0.0'
|
||||
from pretix import __version__
|
||||
version = '.'.join(__version__.split('.')[:2])
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '0.0.0'
|
||||
release = __version__
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
@@ -114,7 +117,9 @@ pygments_style = 'sphinx'
|
||||
# Theme options are theme-specific and customize the look and feel of a theme
|
||||
# further. For a list of options available for each theme, see the
|
||||
# documentation.
|
||||
#html_theme_options = {}
|
||||
html_theme_options = {
|
||||
'logo_only': True,
|
||||
}
|
||||
|
||||
# Add any paths that contain custom themes here, relative to this directory.
|
||||
#html_theme_path = []
|
||||
@@ -128,7 +133,7 @@ pygments_style = 'sphinx'
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top
|
||||
# of the sidebar.
|
||||
#html_logo = None
|
||||
html_logo = 'images/logo-white.svg'
|
||||
|
||||
# The name of an image file (within the static path) to use as favicon of the
|
||||
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
|
||||
@@ -138,7 +143,11 @@ pygments_style = 'sphinx'
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
html_static_path = ['_static']
|
||||
html_static_path = [
|
||||
'_static',
|
||||
os.path.abspath('../src/pretix/static/fonts/'),
|
||||
os.path.abspath('../src/pretix/static/fontawesome/fonts/'),
|
||||
]
|
||||
|
||||
# Add any extra paths that contain custom files (such as robots.txt or
|
||||
# .htaccess) here, relative to this directory. These files are copied
|
||||
@@ -158,7 +167,9 @@ html_static_path = ['_static']
|
||||
|
||||
# Additional templates that should be rendered to pages, maps page names to
|
||||
# template names.
|
||||
#html_additional_pages = {}
|
||||
html_additional_pages = {
|
||||
'index': 'index.html'
|
||||
}
|
||||
|
||||
# If false, no module index is generated.
|
||||
html_domain_indices = False
|
||||
@@ -170,7 +181,7 @@ html_use_index = False
|
||||
#html_split_index = False
|
||||
|
||||
# If true, links to the reST sources are added to the pages.
|
||||
#html_show_sourcelink = True
|
||||
html_show_sourcelink = True
|
||||
|
||||
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
|
||||
#html_show_sphinx = True
|
||||
@@ -189,11 +200,8 @@ html_use_index = False
|
||||
# Output file base name for HTML help builder.
|
||||
htmlhelp_basename = 'pretixdoc'
|
||||
|
||||
on_rtd = os.environ.get('READTHEDOCS', None) == 'True'
|
||||
if not on_rtd: # only import and set the theme if we're building docs locally
|
||||
import sphinx_rtd_theme
|
||||
html_theme = 'sphinx_rtd_theme'
|
||||
html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
|
||||
html_theme = 'pretix_theme'
|
||||
html_theme_path = [os.path.abspath('_themes')]
|
||||
|
||||
|
||||
# -- Options for LaTeX output ---------------------------------------------
|
||||
@@ -213,7 +221,7 @@ latex_elements = {
|
||||
# (source start file, target name, title,
|
||||
# author, documentclass [howto, manual, or own class]).
|
||||
latex_documents = [
|
||||
('index', 'pretix.tex', 'pretix Documentation',
|
||||
('contents', 'pretix.tex', 'pretix Documentation',
|
||||
'Raphael Michel', 'manual'),
|
||||
]
|
||||
|
||||
|
||||
12
doc/contents.rst
Normal file
@@ -0,0 +1,12 @@
|
||||
Table of contents
|
||||
=================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 3
|
||||
|
||||
user/index
|
||||
admin/index
|
||||
api/index
|
||||
development/index
|
||||
plugins/index
|
||||
|
||||
@@ -96,3 +96,52 @@ correctly ensure that:
|
||||
* The ``request.event`` attribute contains the correct ``Event`` object
|
||||
* The ``request.organizer`` attribute contains the correct ``Organizer`` object
|
||||
* The locale is set correctly
|
||||
|
||||
REST API viewsets
|
||||
-----------------
|
||||
|
||||
Our REST API is built upon `Django REST Framework`_ (DRF). DRF has two important concepts that are different from
|
||||
standard Django request handling: There are `ViewSets`_ to group related views in a single class and `Routers`_ to
|
||||
automatically build URL configurations from them.
|
||||
|
||||
To integrate a custom viewset with pretix' REST API, you can just register with one of our routers within the
|
||||
``urls.py`` module of your plugin::
|
||||
|
||||
|
||||
from pretix.api.urls import event_router, router, orga_router
|
||||
|
||||
router.register('global_viewset', MyViewSet)
|
||||
orga_router.register('orga_level_viewset', MyViewSet)
|
||||
event_router.register('event_level_viewset', MyViewSet)
|
||||
|
||||
Routes registered with ``router`` are inserted into the global API space at ``/api/v1/``. Routes registered with
|
||||
``orga_router`` will be included at ``/api/v1/organizers/(organizer)/`` and routes registered with ``event_router``
|
||||
will be included at ``/api/v1/organizers/(organizer)/events/(event)/``.
|
||||
|
||||
In case of ``orga_router`` and ``event_router``, permission checking is done for you similarly as with custom views
|
||||
in the control panel. However, you need to make sure on your own only to return the correct subset of data! ``request
|
||||
.event`` and ``request.organizer`` are available as usual.
|
||||
|
||||
To require a special permission like ``can_view_orders``, you do not need to inherit from a special ViewSet base
|
||||
class, you can just set the ``permission`` attribute on your viewset::
|
||||
|
||||
class MyViewSet(ModelViewSet):
|
||||
permission = 'can_view_orders'
|
||||
...
|
||||
|
||||
If you want to check the permission only for some methods of your viewset, you have to do it yourself. Note here that
|
||||
API authentications can be done via user sessions or API tokens and you should therefore check something like the
|
||||
following::
|
||||
|
||||
|
||||
perm_holder = (request.auth if isinstance(request.auth, TeamAPIToken) else request.user)
|
||||
if perm_holder.has_event_permission(request.event.organizer, request.event, 'can_view_orders'):
|
||||
...
|
||||
|
||||
|
||||
.. warning:: It is important that you do this in the ``yourplugin.urls`` module, otherwise pretix will not find your
|
||||
routes early enough during system startup.
|
||||
|
||||
.. _Django REST Framework: http://www.django-rest-framework.org/
|
||||
.. _ViewSets: http://www.django-rest-framework.org/api-guide/viewsets/
|
||||
.. _Routers: http://www.django-rest-framework.org/api-guide/routers/
|
||||
|
||||
@@ -11,7 +11,7 @@ Core
|
||||
----
|
||||
|
||||
.. automodule:: pretix.base.signals
|
||||
:members: periodic_task, event_live_issues
|
||||
:members: periodic_task, event_live_issues, event_copy_data
|
||||
|
||||
Order events
|
||||
""""""""""""
|
||||
@@ -19,13 +19,13 @@ Order events
|
||||
There are multiple signals that will be sent out in the ordering cycle:
|
||||
|
||||
.. automodule:: pretix.base.signals
|
||||
:members: order_paid, order_placed
|
||||
:members: validate_cart, order_paid, order_placed
|
||||
|
||||
Frontend
|
||||
--------
|
||||
|
||||
.. automodule:: pretix.presale.signals
|
||||
:members: html_head, footer_links, front_page_top, front_page_bottom
|
||||
:members: html_head, html_footer, footer_links, front_page_top, front_page_bottom, contact_form_fields, question_form_fields, checkout_confirm_messages
|
||||
|
||||
|
||||
.. automodule:: pretix.presale.signals
|
||||
@@ -47,7 +47,7 @@ Backend
|
||||
-------
|
||||
|
||||
.. automodule:: pretix.control.signals
|
||||
:members: nav_event, html_head, quota_detail_html
|
||||
:members: nav_event, html_head, quota_detail_html, nav_topbar, nav_global, nav_organizer
|
||||
|
||||
|
||||
.. automodule:: pretix.base.signals
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
Plugin hooks
|
||||
============
|
||||
Plugin development
|
||||
==================
|
||||
|
||||
Contents:
|
||||
|
||||
@@ -10,5 +10,6 @@ Contents:
|
||||
exporter
|
||||
ticketoutput
|
||||
payment
|
||||
invoice
|
||||
customview
|
||||
general
|
||||
|
||||
95
doc/development/api/invoice.rst
Normal file
@@ -0,0 +1,95 @@
|
||||
.. highlight:: python
|
||||
:linenothreshold: 5
|
||||
|
||||
Writing an invoice renderer plugin
|
||||
==================================
|
||||
|
||||
An invoice renderer controls how invoice files are built.
|
||||
The creation of such a plugin is very similar to creating an export output.
|
||||
|
||||
Please read :ref:`Creating a plugin <pluginsetup>` first, if you haven't already.
|
||||
|
||||
Output registration
|
||||
-------------------
|
||||
|
||||
The invoice renderer API does not make a lot of usage from signals, however, it
|
||||
does use a signal to get a list of all available ticket outputs. Your plugin
|
||||
should listen for this signal and return the subclass of ``pretix.base.invoice.BaseInvoiceRenderer``
|
||||
that we'll provide in this plugin::
|
||||
|
||||
from django.dispatch import receiver
|
||||
|
||||
from pretix.base.signals import register_invoice_renderers
|
||||
|
||||
|
||||
@receiver(register_invoice_renderers, dispatch_uid="output_custom")
|
||||
def register_infoice_renderers(sender, **kwargs):
|
||||
from .invoice import MyInvoiceRenderer
|
||||
return MyInvoiceRenderer
|
||||
|
||||
|
||||
The renderer class
|
||||
------------------
|
||||
|
||||
.. class:: pretix.base.invoice.BaseInvoiceRenderer
|
||||
|
||||
The central object of each invoice renderer is the subclass of ``BaseInvoiceRenderer``.
|
||||
|
||||
.. py:attribute:: BaseInvoiceRenderer.event
|
||||
|
||||
The default constructor sets this property to the event we are currently
|
||||
working for.
|
||||
|
||||
.. autoattribute:: identifier
|
||||
|
||||
This is an abstract attribute, you **must** override this!
|
||||
|
||||
.. autoattribute:: verbose_name
|
||||
|
||||
This is an abstract attribute, you **must** override this!
|
||||
|
||||
.. automethod:: generate
|
||||
|
||||
Helper class for reportlab-base renderers
|
||||
-----------------------------------------
|
||||
|
||||
All PDF rendering that ships with pretix is based on reportlab. We recommend to read the
|
||||
`reportlab User Guide`_ to understand all the concepts used here.
|
||||
|
||||
If you want to implement a renderer that also uses report lab, this helper class might be
|
||||
convenient to you:
|
||||
|
||||
|
||||
.. class:: pretix.base.invoice.BaseReportlabInvoiceRenderer
|
||||
|
||||
.. py:attribute:: BaseReportlabInvoiceRenderer.pagesize
|
||||
|
||||
.. py:attribute:: BaseReportlabInvoiceRenderer.left_margin
|
||||
|
||||
.. py:attribute:: BaseReportlabInvoiceRenderer.right_margin
|
||||
|
||||
.. py:attribute:: BaseReportlabInvoiceRenderer.top_margin
|
||||
|
||||
.. py:attribute:: BaseReportlabInvoiceRenderer.bottom_margin
|
||||
|
||||
.. py:attribute:: BaseReportlabInvoiceRenderer.doc_template_class
|
||||
|
||||
.. py:attribute:: BaseReportlabInvoiceRenderer.invoice
|
||||
|
||||
.. automethod:: _init
|
||||
|
||||
.. automethod:: _get_stylesheet
|
||||
|
||||
.. automethod:: _register_fonts
|
||||
|
||||
.. automethod:: _on_first_page
|
||||
|
||||
.. automethod:: _on_other_page
|
||||
|
||||
.. automethod:: _get_first_page_frames
|
||||
|
||||
.. automethod:: _get_other_page_frames
|
||||
|
||||
.. automethod:: _build_doc
|
||||
|
||||
.. _reportlab User Guide: https://www.reportlab.com/docs/reportlab-userguide.pdf
|
||||
@@ -1,8 +1,10 @@
|
||||
.. highlight:: python
|
||||
:linenothreshold: 5
|
||||
|
||||
Plugin basics
|
||||
=============
|
||||
.. _`pluginsetup`:
|
||||
|
||||
Creating a plugin
|
||||
=================
|
||||
|
||||
It is possible to extend pretix with custom Python code using the official plugin
|
||||
API. Every plugin has to be implemented as an independent Django 'app' living
|
||||
@@ -14,10 +16,15 @@ The communication between pretix and the plugins happens mostly using Django's
|
||||
``pretix.control`` and ``pretix.presale`` expose a number of signals which are documented
|
||||
on the next pages.
|
||||
|
||||
.. _`pluginsetup`:
|
||||
|
||||
To create a new plugin, create a new python package which must be a valid `Django app`_
|
||||
and must contain plugin metadata, as described below.
|
||||
There is some boilerplate that you will need for every plugin to get started. To save your
|
||||
time, we created a `cookiecutter`_ template that you can use like this::
|
||||
|
||||
$ pip install cookiecutter
|
||||
$ cookiecutter https://github.com/pretix/pretix-plugin-cookiecutter
|
||||
|
||||
This will ask you some questions and then create a project folder for your plugin.
|
||||
|
||||
The following pages go into detail about the several types of plugins currently
|
||||
supported. While these instructions don't assume that you know a lot about pretix,
|
||||
@@ -30,38 +37,40 @@ Plugin metadata
|
||||
The plugin metadata lives inside a ``PretixPluginMeta`` class inside your app's
|
||||
configuration class. The metadata class must define the following attributes:
|
||||
|
||||
``name`` (``str``):
|
||||
The human-readable name of your plugin
|
||||
.. rst-class:: rest-resource-table
|
||||
|
||||
``author`` (``str``):
|
||||
Your name
|
||||
|
||||
``version`` (``str``):
|
||||
A human-readable version code of your plugin
|
||||
|
||||
``description`` (``str``):
|
||||
A more verbose description of what your plugin does.
|
||||
================== ==================== ===========================================================
|
||||
Attribute Type Description
|
||||
================== ==================== ===========================================================
|
||||
name string The human-readable name of your plugin
|
||||
author string Your name
|
||||
version string A human-readable version code of your plugin
|
||||
description string A more verbose description of what your plugin does.
|
||||
visible boolean (optional) ``True`` by default, can hide a plugin so it cannot be normally activated.
|
||||
restricted boolean (optional) ``False`` by default, restricts a plugin such that it can only be enabled
|
||||
for an event by system administrators / superusers.
|
||||
================== ==================== ===========================================================
|
||||
|
||||
A working example would be::
|
||||
|
||||
# file: pretix/plugins/timerestriction/__init__.py
|
||||
from django.apps import AppConfig
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
|
||||
class PaypalApp(AppConfig):
|
||||
name = 'pretix.plugins.paypal'
|
||||
verbose_name = _("Stripe")
|
||||
name = 'pretix_paypal'
|
||||
verbose_name = _("PayPal")
|
||||
|
||||
class PretixPluginMeta:
|
||||
name = _("PayPal")
|
||||
author = _("the pretix team")
|
||||
version = '1.0.0'
|
||||
visible = True
|
||||
restricted = False
|
||||
description = _("This plugin allows you to receive payments via PayPal")
|
||||
|
||||
|
||||
default_app_config = 'pretix.plugins.paypal.PaypalApp'
|
||||
|
||||
default_app_config = 'pretix_paypal.PaypalApp'
|
||||
|
||||
The ``AppConfig`` class may implement a property ``compatiblity_errors``, that checks
|
||||
whether the pretix installation meets all requirements of the plugin. If so,
|
||||
@@ -78,11 +87,10 @@ make use of the `entry point`_ feature of setuptools. To register a plugin that
|
||||
in a separate python package, your ``setup.py`` should contain something like this::
|
||||
|
||||
setup(
|
||||
…
|
||||
|
||||
args...,
|
||||
entry_points="""
|
||||
[pretix.plugin]
|
||||
sampleplugin=sampleplugin:PretixPluginMeta
|
||||
pretix_paypal=pretix_paypal:PretixPluginMeta
|
||||
"""
|
||||
)
|
||||
|
||||
@@ -100,7 +108,7 @@ pages. We suggest that you put your signal receivers into a ``signals`` submodul
|
||||
of your plugin. You should extend your ``AppConfig`` (see above) by the following
|
||||
method to make your receivers available::
|
||||
|
||||
class TimeRestrictionApp(AppConfig):
|
||||
class PaypalApp(AppConfig):
|
||||
…
|
||||
|
||||
def ready(self):
|
||||
@@ -122,3 +130,4 @@ your Django app label.
|
||||
.. _signal dispatcher: https://docs.djangoproject.com/en/1.7/topics/signals/
|
||||
.. _namespace packages: http://legacy.python.org/dev/peps/pep-0420/
|
||||
.. _entry point: https://pythonhosted.org/setuptools/setuptools.html#dynamic-discovery-of-services-and-plugins
|
||||
.. _cookiecutter: https://cookiecutter.readthedocs.io/en/latest/
|
||||
|
||||
@@ -58,10 +58,14 @@ The output class
|
||||
|
||||
.. autoattribute:: is_enabled
|
||||
|
||||
.. autoattribute:: multi_download_enabled
|
||||
|
||||
.. autoattribute:: settings_form_fields
|
||||
|
||||
.. automethod:: settings_content_render
|
||||
|
||||
.. automethod:: generate
|
||||
|
||||
.. automethod:: generate_order
|
||||
|
||||
.. autoattribute:: download_button_text
|
||||
|
||||
@@ -1,18 +1,16 @@
|
||||
Implementation concepts
|
||||
=======================
|
||||
|
||||
Basic terminology
|
||||
-----------------
|
||||
Concepts and Terminology
|
||||
========================
|
||||
|
||||
The components
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
The project pretix is split into several components. The main three of them are:
|
||||
The project pretix is split into several components. The main components are:
|
||||
|
||||
**base**
|
||||
This is the foundation below all other components. It is primarily
|
||||
responsible for the data structures and database communication. It also hosts
|
||||
several utilities which are used by multiple other components.
|
||||
several utilities which are used by multiple other components and important parts of
|
||||
the business logic.
|
||||
|
||||
**control**
|
||||
This is the web-based backend software which allows organizers to
|
||||
@@ -20,7 +18,13 @@ The project pretix is split into several components. The main three of them are:
|
||||
|
||||
**presale**
|
||||
This is the ticket-shop itself, containing all of the parts visible to the
|
||||
end user.
|
||||
end user. Also called "frontend" in parts of this documentation.
|
||||
|
||||
**api**
|
||||
A RESTful API exposed to integrate with third-party software.
|
||||
|
||||
**plugins**
|
||||
A set of pretix plugins that ship bundled with pretix.
|
||||
|
||||
Users and events
|
||||
^^^^^^^^^^^^^^^^
|
||||
@@ -61,6 +65,7 @@ limit:
|
||||
* The number of orders placed for an item that are either already paid or within their granted payment period
|
||||
* The number of non-expired items currently in the shopping cart of users
|
||||
* The number of vouchers defined as "quota blocking" (see blow)
|
||||
* The number of people on the waiting list
|
||||
|
||||
The quota system tries very hard to be as friendly as possible to your event attendees while still making sure
|
||||
your limit is never exceeded. For example, when the payment period of an order expires without the order being
|
||||
|
||||
@@ -9,7 +9,8 @@ constructive and friendly feedback on your changes.
|
||||
First of all, you'll need pretix running locally on your machine. Head over to :ref:`devsetup` to learn how to do this.
|
||||
If you run into any problems on your way, please do not hesitate to ask us anytime!
|
||||
|
||||
Please note that we have a :ref:`coc` in place that applies to all communication around the project.
|
||||
Please note that we bound ourselves to a :ref:`coc` that applies to all communication around the project. You can be
|
||||
assured that we will not tolerate any form of harassment.
|
||||
|
||||
Sending a patch
|
||||
---------------
|
||||
@@ -18,8 +19,9 @@ If you improved pretix in any way, we'd be very happy if you contribute it
|
||||
back to the main code base! The easiest way to do so is to `create a pull request`_
|
||||
on our `GitHub repository`_.
|
||||
|
||||
Before you do so, please `squash all your changes`_ into one single commit. Please
|
||||
use the test suite to check whether your changes break any existing features and run
|
||||
We recommend that you create a feature branch for every issue you work on so the changes can
|
||||
be reviewed individually.
|
||||
Please use the test suite to check whether your changes break any existing features and run
|
||||
the code style checks to confirm you are consistent with pretix's coding style. You'll
|
||||
find instructions on this in the :ref:`checksandtests` section of the development setup guide.
|
||||
|
||||
@@ -34,4 +36,3 @@ Again: If you get stuck, do not hesitate to contact any of us, or Raphael person
|
||||
|
||||
.. _create a pull request: https://help.github.com/articles/creating-a-pull-request/
|
||||
.. _GitHub repository: https://github.com/pretix/pretix
|
||||
.. _squash all your changes: https://davidwalsh.name/squash-commits-git
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
Contribution guide
|
||||
==================
|
||||
Contributing to pretix
|
||||
======================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
@@ -1,39 +1,33 @@
|
||||
Coding style
|
||||
============
|
||||
Coding style and quality
|
||||
========================
|
||||
|
||||
Python code
|
||||
-----------
|
||||
* Basically, we want all python code to follow the `PEP 8`_ standard. There are a few exceptions where
|
||||
we see things differently or just aren't that strict. The ``setup.cfg`` file in the project's source
|
||||
folder contains definitions that allow `flake8`_ to check for violations automatically. See :ref:`checksandtests`
|
||||
for more information. Use four spaces for indentation.
|
||||
|
||||
* Basically: Follow `PEP 8`_.
|
||||
* We sort our imports by a certain schema, but you don't have to do this by hand. Again, ``setup.cfg`` contains
|
||||
some definitions that allow the command ``isort -rc <directory>`` to automatically sort the imports in your source
|
||||
files.
|
||||
|
||||
Use `flake8`_ to check for conformance problems. The project includes a setup.cfg file
|
||||
with a default configuration for flake8 that excludes migrations and other non-relevant
|
||||
code parts. It also silences a few checks, e.g. ``N802`` (function names should be lowercase)
|
||||
and increases the maximum line length to more than 79 characters. **However** you should
|
||||
still name all your functions lowercase [#f1]_ and keep your lines short when possible.
|
||||
* For templates and models, please take a look at the `Django Coding Style`_. We like Django's `class-based views`_ and
|
||||
kindly ask you to use them where appropriate.
|
||||
|
||||
* Our build server will reject all code violating other flake8 checks than the following:
|
||||
* Please remember to always mark all strings ever displayed to any user for `translation`_.
|
||||
|
||||
* E123: closing bracket does not match indentation of opening bracket’s line
|
||||
* F403: ``from module import *`` used; unable to detect undefined names
|
||||
* F401: module imported but unused
|
||||
* N802: function names should be lowercase
|
||||
* We expect all new code to come with proper tests. When writing new tests, please write them using `pytest-style`_
|
||||
test functions and raw ``assert`` statements. Use `fixtures`_ to prevent repetitive code. Some old parts of pretix'
|
||||
test suite are in the style of Python's unit test module. If you extend those files, you might continue in this style,
|
||||
but please use pytest style for any new test files.
|
||||
|
||||
So please make sure that you *always* follow all other rules and break these rules *only when
|
||||
it makes sense*.
|
||||
|
||||
* Use ``isort -rc pretix`` in the source directory to order your imports.
|
||||
|
||||
* Indent your code with four spaces.
|
||||
|
||||
* For templates and models, follow the `Django Coding Style`_.
|
||||
|
||||
* Use Django's class-based views
|
||||
|
||||
* Always mark all strings ever displayed to any user for translation.
|
||||
* Please keep the first line of your commit messages short. When referencing an issue, please phrase it like
|
||||
``Fix #123 -- Problems with order creation`` or ``Refs #123 -- Fix this part of that bug``.
|
||||
|
||||
|
||||
.. _PEP 8: http://legacy.python.org/dev/peps/pep-0008/
|
||||
.. _flake8: https://pypi.python.org/pypi/flake8
|
||||
.. _Django Coding Style: https://docs.djangoproject.com/en/dev/internals/contributing/writing-code/coding-style/
|
||||
.. [#f1] But Python's very own ``unittest`` module forces us to use ``setUp`` as a method name...
|
||||
.. _translation: https://docs.djangoproject.com/en/1.11/topics/i18n/translation/
|
||||
.. _class-based views: https://docs.djangoproject.com/en/1.11/topics/class-based-views/
|
||||
.. _pytest-style: https://docs.pytest.org/en/latest/assert.html
|
||||
.. _fixtures: https://docs.pytest.org/en/latest/fixture.html
|
||||
|
||||
@@ -2,6 +2,9 @@ Sending Email
|
||||
=============
|
||||
|
||||
pretix allows event organizers to configure how they want to send emails to their users in multiple ways.
|
||||
Therefore, all emails should be sent through the following function:
|
||||
Therefore, all emails should be sent through the following function.
|
||||
|
||||
If the email you send is related to an order, you should also take a look at the
|
||||
:py:meth:`~pretix.base.models.Order.send_mail` of the order model.
|
||||
|
||||
.. autofunction:: pretix.base.services.mail.mail
|
||||
|
||||
@@ -6,116 +6,18 @@ One of pretix's major selling points is its multi-language capability. We make h
|
||||
way to translate *user-generated content*. In our case, we need to translate strings like product names
|
||||
or event descriptions, so we need event organizers to be able to fill in all fields in multiple languages.
|
||||
|
||||
.. note:: Implementing object-level translation in a relational database is a task that requires some difficult
|
||||
trade-off. We decided for a design that is not elegant on the database level (as it violates the `1NF`_) and
|
||||
makes searching in the respective database fields very hard, but allows for a simple design on the ORM level
|
||||
and adds only minimal performance overhead.
|
||||
For this purpose, we use ``django-i18nfield`` which started out as part of pretix and then got refactored into
|
||||
its own library. It has comprehensive documentation on how to work with its `strings`_, `database fields`_ and
|
||||
`forms`_.
|
||||
|
||||
All classes and functions introduced in this document are located in ``pretix.base.i18n`` if not stated otherwise.
|
||||
|
||||
Database storage
|
||||
----------------
|
||||
|
||||
pretix provides two custom model field types that allow you to work with localized strings: ``I18nCharField`` and
|
||||
``I18nTextField``. Both of them are stored in the database as a ``TextField`` internally, they only differ in the
|
||||
default form widget that is used by ``ModelForm``.
|
||||
|
||||
As pretix does not use these fields in places that need to be searched, the negative performance impact when searching
|
||||
and indexing these fields in negligible, as mentioned above. Lookups are currently not even implemented on these
|
||||
fields. In the database, the strings will be stored as a JSON-encoded mapping of language codes to strings.
|
||||
|
||||
Whenever you interact with those fields, you will either provide or receive an instance of the following class:
|
||||
|
||||
.. autoclass:: pretix.base.i18n.LazyI18nString
|
||||
:members: __init__, localize, __str__
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
The following examples are given to illustrate how you can work with ``LazyI18nString``.
|
||||
|
||||
.. testsetup:: *
|
||||
|
||||
from pretix.base.i18n import LazyI18nString, language
|
||||
|
||||
To create a LazyI18nString, we can cast a simple string:
|
||||
|
||||
.. doctest::
|
||||
|
||||
>>> naive = LazyI18nString('Naive untranslated string')
|
||||
>>> naive
|
||||
<LazyI18nString: 'Naive untranslated string'>
|
||||
|
||||
Or we can provide a dictionary with multiple translations:
|
||||
|
||||
.. doctest::
|
||||
|
||||
>>> translated = LazyI18nString({'en': 'English String', 'de': 'Deutscher String'})
|
||||
|
||||
We can use ``localize`` to get the string in a specific language:
|
||||
|
||||
.. doctest::
|
||||
|
||||
>>> translated.localize('de')
|
||||
'Deutscher String'
|
||||
|
||||
>>> translated.localize('en')
|
||||
'English String'
|
||||
|
||||
If we try a locale that does not exist for the string, we might get a it either in a similar locale or in the system's default language:
|
||||
|
||||
.. doctest::
|
||||
|
||||
>>> translated.localize('de-AT')
|
||||
'Deutscher String'
|
||||
|
||||
>>> translated.localize('zh')
|
||||
'English String'
|
||||
|
||||
>>> naive.localize('de')
|
||||
'Naive untranslated string'
|
||||
|
||||
If we cast a ``LazyI18nString`` to ``str``, ``localize`` will be called with the currently active language:
|
||||
|
||||
.. doctest::
|
||||
|
||||
>>> from django.utils import translation
|
||||
>>> str(translated)
|
||||
'English String'
|
||||
>>> translation.activate('de')
|
||||
>>> str(translated)
|
||||
'Deutscher String'
|
||||
|
||||
You can also use our handy context manager to set the locale temporarily:
|
||||
|
||||
.. doctest::
|
||||
|
||||
>>> translation.activate('en')
|
||||
>>> with language('de'):
|
||||
... str(translated)
|
||||
'Deutscher String'
|
||||
>>> str(translated)
|
||||
'English String'
|
||||
|
||||
Forms
|
||||
-----
|
||||
|
||||
We provide i18n-aware versions of the respective form fields and widgets: ``I18nFormField`` with the ``I18nTextInput``
|
||||
and ``I18nTextarea`` widgets. They transparently allow you to use ``LazyI18nString`` values in forms and render text
|
||||
inputs for multiple languages.
|
||||
|
||||
.. autoclass:: pretix.base.i18n.I18nFormField
|
||||
|
||||
To easily limit the displayed languages to the languages relevant to an event, there is a custom ``ModelForm`` subclass
|
||||
that deals with this for you:
|
||||
|
||||
.. autoclass:: pretix.base.forms.I18nModelForm
|
||||
|
||||
There are equivalents for ``BaseModelFormSet`` and ``BaseInlineFormSet``:
|
||||
|
||||
.. autoclass:: pretix.base.forms.I18nFormSet
|
||||
|
||||
.. autoclass:: pretix.base.forms.I18nInlineFormSet
|
||||
For backwards-compatibility with older parts of pretix' code base and older plugins, ``pretix.base.forms`` still
|
||||
contains a number of forms that are equivalent in name and usage to their counterparts in ``i18nfield.forms`` with
|
||||
the difference that they take an ``event`` keyword argument and then set the ``locales`` argument based on
|
||||
``event.settings.get('locales')``.
|
||||
|
||||
Useful utilities
|
||||
----------------
|
||||
@@ -135,4 +37,6 @@ action that causes the mail to be sent.
|
||||
|
||||
.. _translation features: https://docs.djangoproject.com/en/1.9/topics/i18n/translation/
|
||||
.. _GNU gettext: https://www.gnu.org/software/gettext/
|
||||
.. _1NF: https://en.wikipedia.org/wiki/First_normal_form
|
||||
.. _strings: https://django-i18nfield.readthedocs.io/en/latest/strings.html
|
||||
.. _database fields: https://django-i18nfield.readthedocs.io/en/latest/quickstart.html
|
||||
.. _forms: https://django-i18nfield.readthedocs.io/en/latest/forms.html
|
||||
|
||||
@@ -20,13 +20,13 @@ Organizers and events
|
||||
.. autoclass:: pretix.base.models.Organizer
|
||||
:members:
|
||||
|
||||
.. autoclass:: pretix.base.models.OrganizerPermission
|
||||
:members:
|
||||
|
||||
.. autoclass:: pretix.base.models.Event
|
||||
:members:
|
||||
:members: get_date_from_display, get_time_from_display, get_date_to_display, get_date_range_display, presale_has_ended, presale_is_running, get_cache, lock, get_plugins, get_mail_backend, payment_term_last, get_payment_providers, get_invoice_renderers, active_subevents, invoice_renderer, settings
|
||||
|
||||
.. autoclass:: pretix.base.models.EventPermission
|
||||
.. autoclass:: pretix.base.models.SubEvent
|
||||
:members: get_date_from_display, get_time_from_display, get_date_to_display, get_date_range_display, presale_has_ended, presale_is_running
|
||||
|
||||
.. autoclass:: pretix.base.models.Team
|
||||
:members:
|
||||
|
||||
.. autoclass:: pretix.base.models.RequiredAction
|
||||
@@ -45,6 +45,15 @@ Items
|
||||
.. autoclass:: pretix.base.models.ItemVariation
|
||||
:members:
|
||||
|
||||
.. autoclass:: pretix.base.models.SubEventItem
|
||||
:members:
|
||||
|
||||
.. autoclass:: pretix.base.models.SubEventItemVariation
|
||||
:members:
|
||||
|
||||
.. autoclass:: pretix.base.models.ItemAddOn
|
||||
:members:
|
||||
|
||||
.. autoclass:: pretix.base.models.Question
|
||||
:members:
|
||||
|
||||
@@ -67,7 +76,7 @@ Carts and Orders
|
||||
:members:
|
||||
|
||||
.. autoclass:: pretix.base.models.QuestionAnswer
|
||||
:members:
|
||||
:members:
|
||||
|
||||
.. autoclass:: pretix.base.models.Checkin
|
||||
:members:
|
||||
@@ -92,5 +101,3 @@ Vouchers
|
||||
|
||||
.. autoclass:: pretix.base.models.Voucher
|
||||
:members:
|
||||
|
||||
.. _cleanerversion: https://github.com/swisscom/cleanerversion
|
||||
|
||||
@@ -2,7 +2,10 @@ Settings storage
|
||||
================
|
||||
|
||||
pretix is highly configurable and therefore needs to store a lot of per-event and per-organizer settings.
|
||||
Those settings are stored in the database and accessed through a ``SettingsProxy`` instance. You can obtain
|
||||
For this purpose, we use `django-hierarkey`_ which started out as part of pretix and then got refactored into
|
||||
its own library. It has a comprehensive `documentation`_ which you should read if you work with settings in pretix.
|
||||
|
||||
The settings are stored in the database and accessed through a ``HierarkeyProxy`` instance. You can obtain
|
||||
such an instance from any event or organizer model instance by just accessing ``event.settings`` or
|
||||
``organizer.settings``, respectively.
|
||||
|
||||
@@ -17,12 +20,10 @@ includes serializers for serializing the following types:
|
||||
|
||||
In code, we recommend to always use the ``.get()`` method on the settings object to access a value, but for
|
||||
convenience in templates you can also access settings values at ``settings[name]`` and ``settings.name``.
|
||||
|
||||
.. autoclass:: pretix.base.settings.SettingsProxy
|
||||
:members: get, set, delete, freeze
|
||||
See the hierarkey `documentation`_ for more information.
|
||||
|
||||
To avoid naming conflicts, plugins are requested to prefix all settings they use with the name of the plugin
|
||||
or something unique, e.g. ``payment.paypal.api_key``. To reduce redundant typing of this prefix, we provide
|
||||
or something unique, e.g. ``payment_paypal_api_key``. To reduce redundant typing of this prefix, we provide
|
||||
another helper class:
|
||||
|
||||
.. autoclass:: pretix.base.settings.SettingsSandbox
|
||||
@@ -33,10 +34,10 @@ you will just be passed a sandbox object with a prefix generated from your provi
|
||||
Forms
|
||||
-----
|
||||
|
||||
We also provide a base class for forms that allow the modification of settings:
|
||||
Hierarkey also provides a base class for forms that allow the modification of settings. pretix contains a
|
||||
subclass that also adds suport for internationalized fields:
|
||||
|
||||
.. autoclass:: pretix.base.forms.SettingsForm
|
||||
:members: save
|
||||
|
||||
You can simply use it like this::
|
||||
|
||||
@@ -51,3 +52,17 @@ You can simply use it like this::
|
||||
help_text=_("The number of days after placing an order the user has to pay to "
|
||||
"preserve his reservation."),
|
||||
)
|
||||
|
||||
Defaults in plugins
|
||||
-------------------
|
||||
|
||||
Plugins can add custom hardcoded defaults in the following way::
|
||||
|
||||
from pretix.base.settings import settings_hierarkey
|
||||
|
||||
settings_hierarkey.add_default('key', 'value', type)
|
||||
|
||||
Make sure that you include this code in a module that is imported at app loading time.
|
||||
|
||||
.. _django-hierarkey: https://github.com/raphaelm/django-hierarkey
|
||||
.. _documentation: https://django-hierarkey.readthedocs.io/en/latest/
|
||||
@@ -1,17 +1,15 @@
|
||||
Developer documentation
|
||||
=======================
|
||||
|
||||
Contents:
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
concepts
|
||||
setup
|
||||
structure
|
||||
contribution/index
|
||||
implementation/index
|
||||
api/index
|
||||
structure
|
||||
|
||||
.. TODO::
|
||||
Document settings objects, ItemVariation objects, form fields.
|
||||
Document settings objects, ItemVariation objects, form fields.
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
.. _`devsetup`:
|
||||
|
||||
The development setup
|
||||
=====================
|
||||
Development setup
|
||||
=================
|
||||
|
||||
This tutorial helps you to get started hacking with pretix on your own computer. You need this to
|
||||
be able to contribute to pretix, but it might also be helpful if you want to write your own plugins.
|
||||
If you want to install pretix on a server for actual usage, go to the :ref:`admindocs` instead.
|
||||
|
||||
Obtain a copy of the source code
|
||||
--------------------------------
|
||||
@@ -12,9 +16,12 @@ You can just clone our git repository::
|
||||
|
||||
External Dependencies
|
||||
---------------------
|
||||
Your should install the following on your system:
|
||||
|
||||
* Python 3.4 or newer
|
||||
* ``pip`` for Python 3 (Debian package: ``python3-pip``)
|
||||
* ``pyvenv`` for Python 3 (Debian package: ``python3-venv``)
|
||||
* ``python-dev`` for Python 3 (Debian package: ``python3-dev``)
|
||||
* ``libffi`` (Debian package: ``libffi-dev``)
|
||||
* ``libssl`` (Debian package: ``libssl-dev``)
|
||||
* ``libxml2`` (Debian package ``libxml2-dev``)
|
||||
@@ -39,7 +46,7 @@ automatically). If you are working on Ubuntu or Debian, we strongly recommend up
|
||||
your pip and setuptools installation inside the virtual environment, otherwise some of
|
||||
the dependencies might fail::
|
||||
|
||||
pip3 install -U pip setuptools==28.6.1
|
||||
pip3 install -U pip setuptools
|
||||
|
||||
Working with the code
|
||||
---------------------
|
||||
@@ -48,7 +55,7 @@ The first thing you need are all the main application's dependencies::
|
||||
cd src/
|
||||
pip3 install -r requirements.txt -r requirements/dev.txt
|
||||
|
||||
If you are working with Python 3.4, you will also need (you can skip this for Python 3.5)::
|
||||
If you are working with Python 3.4, you will also need (you can skip this for Python 3.5+)::
|
||||
|
||||
pip3 install -r requirements/py34.txt
|
||||
|
||||
@@ -80,17 +87,28 @@ and head to http://localhost:8000/
|
||||
|
||||
As we did not implement an overall front page yet, you need to go directly to
|
||||
http://localhost:8000/control/ for the admin view or, if you imported the test
|
||||
data as suggested above, to the event page at http://localhost:8000/bigevents/2017/
|
||||
data as suggested above, to the event page at http://localhost:8000/bigevents/2018/
|
||||
|
||||
.. note:: If you want the development server to listen on a different interface or
|
||||
port (for example because you develop on `pretixdroid`_), you can check
|
||||
`Django's documentation`_ for more options.
|
||||
|
||||
.. _`checksandtests`:
|
||||
|
||||
Code checks and unit tests
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
Before you check in your code into git, always run the static checkers and unit tests::
|
||||
Before you check in your code into git, always run static checkers and linters. If any of these commands fail,
|
||||
your pull request will not be merged into pretix. If you have trouble figuring out *why* they fail, create your
|
||||
pull request nevertheless and ask us for help, we are happy to assist you.
|
||||
|
||||
Execute the following commands to check for code style errors::
|
||||
|
||||
flake8 .
|
||||
isort -c -rc .
|
||||
python manage.py check
|
||||
|
||||
Execute the following command to run pretix' test suite (might take a coumple of minutes)::
|
||||
|
||||
py.test
|
||||
|
||||
.. note:: If you have multiple CPU cores and want to speed up the test suite, you can install the python
|
||||
@@ -102,9 +120,10 @@ for example::
|
||||
|
||||
#!/bin/sh
|
||||
cd $GIT_DIR/../src
|
||||
source ../env/bin/activate
|
||||
flake8 --ignore=E123,E128,F403,F401,N802,W503 .
|
||||
flake8 . || exit 1
|
||||
isort -q -rc -c . || exit 1
|
||||
|
||||
This keeps you from accidentally creating commits violating the sdtyle guide.
|
||||
|
||||
Working with mails
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
@@ -146,4 +165,14 @@ To build the documentation, run the following command from the ``doc/`` director
|
||||
|
||||
make html
|
||||
|
||||
You will now find the generated documentation in the ``doc/_build/html/`` subdirectory.
|
||||
You will now find the generated documentation in the ``doc/_build/html/`` subdirectory. If you work
|
||||
with the documentation a lot, you might find it useful to use sphinx-autobuild::
|
||||
|
||||
pip3 install sphinx-autobuild
|
||||
sphinx-autobuild . _build/html -p 8081
|
||||
|
||||
Then, go to http://localhost:8081 for a version of the documentation that automatically re-builds
|
||||
whenever you change a source file.
|
||||
|
||||
.. _Django's documentation: https://docs.djangoproject.com/en/1.11/ref/django-admin/#runserver
|
||||
.. _pretixdroid: https://github.com/pretix/pretixdroid
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
Project structure
|
||||
=================
|
||||
|
||||
Python source code
|
||||
------------------
|
||||
Directory structure
|
||||
===================
|
||||
|
||||
All the source code lives in ``src/``, which has several subdirectories.
|
||||
|
||||
pretix/
|
||||
This directory contains nearly all source code.
|
||||
This directory contains nearly all source code that belongs to pretix.
|
||||
|
||||
base/
|
||||
This is the Django app containing all the models and methods which are
|
||||
@@ -19,57 +16,31 @@ pretix/
|
||||
presale/
|
||||
This is the Django app containing the front end for users buying tickets.
|
||||
|
||||
api/
|
||||
This is the Django app containing all views and serializers for pretix'
|
||||
:ref:`rest-api`.
|
||||
|
||||
helpers/
|
||||
Helpers contain a very few modules providing workarounds for low-level flaws in
|
||||
Django or installed 3rd-party packages.
|
||||
|
||||
locale/
|
||||
Contains translation file for pretix
|
||||
|
||||
multidomain/
|
||||
Additional code implementing our customized :ref:`URL handling <urlconf>`.
|
||||
|
||||
static/
|
||||
Contains all static files (CSS, JavaScript, images)
|
||||
static/
|
||||
Contains all static files (CSS/SASS, JavaScript, images) of pretix' core
|
||||
We use libsass as a preprocessor for CSS. Our own sass code is built in the same
|
||||
step as Bootstrap and FontAwesome, so their mixins etc. are fully available.
|
||||
|
||||
testutils/
|
||||
Contains helper methods that are useful to write the test suite for pretix or test
|
||||
suites for pretix plugins.
|
||||
|
||||
tests/
|
||||
This is the root directory for all test codes. It includes subdirectories ``base``,
|
||||
``control``, ``presale``, ``helpers`` and ``plugins`` to mirror the structure of the
|
||||
``pretix`` source code as well as ``testdummy``, which is a pretix plugin used during
|
||||
This is the root directory for all test codes. It includes subdirectories ``api``, ``base``,
|
||||
``control``, ``presale``, ``helpers`, ``multidomain`` and ``plugins`` to mirror the structure
|
||||
of the pretix source code as well as ``testdummy``, which is a pretix plugin used during
|
||||
testing.
|
||||
|
||||
Language files
|
||||
--------------
|
||||
The language files live in ``locale/*/LC_MESSAGES/``.
|
||||
|
||||
Static files
|
||||
------------
|
||||
|
||||
Sass source code
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
We use libsass as a preprocessor for CSS. Our own sass code is built in the same
|
||||
step as Bootstrap and FontAwesome, so their mixins etc. are fully available.
|
||||
|
||||
pretix.control
|
||||
pretixcontrol has two main SCSS files, ``pretix/control/static/pretixcontrol/scss/main.scss`` and
|
||||
``pretix/control/static/pretixcontrol/scss/auth.scss``, importing everything else.
|
||||
|
||||
pretix.presale
|
||||
pretixpresale has one main SCSS files, ``pretix/control/static/pretix/presale/scss/main.scss``,
|
||||
importing everything else.
|
||||
|
||||
3rd-party assets
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
Bootstrap
|
||||
Bootstrap lives vendored at ``static/bootstrap/``
|
||||
|
||||
Font Awesome
|
||||
Font Awesome lives vendored at ``static/fontawesome/``
|
||||
|
||||
jQuery
|
||||
jQuery lives as a single JavaScript file in ``static/jquery/js/``
|
||||
|
||||
jQuery plugin: Django formsets
|
||||
Our own modified version of `django-formset-js`_ is available as an independent
|
||||
django app and installed via ``pip``.
|
||||
|
||||
.. _django-formset-js: https://github.com/pretix/django-formset-js
|
||||
|
||||
69
doc/images/logo-white.svg
Normal file
@@ -0,0 +1,69 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="254.15625"
|
||||
height="109.59375"
|
||||
viewBox="0 0 254.15625 109.59375"
|
||||
version="1.1"
|
||||
id="svg5"
|
||||
sodipodi:docname="logo-white.svg"
|
||||
inkscape:version="0.92.1 r"><metadata
|
||||
id="metadata9">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1364"
|
||||
inkscape:window-height="676"
|
||||
id="namedview7"
|
||||
showgrid="false"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0"
|
||||
inkscape:zoom="1"
|
||||
inkscape:cx="56.462442"
|
||||
inkscape:cy="54.796875"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="72"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="svg5" />
|
||||
|
||||
id="svg2"
|
||||
version="1.1">
|
||||
<defs
|
||||
id="defs4" />
|
||||
<g
|
||||
id="layer1"
|
||||
transform="translate(-277.78125,-568.75)">
|
||||
<path
|
||||
style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;marker:none;enable-background:accumulate"
|
||||
d="m 20,20 v 34.09375 c 11.43679,0 20.71875,9.28196 20.71875,20.71875 C 40.71875,86.24928 31.43679,95.5 20,95.5 v 34.09375 h 146.6875 v -9.5 h 3 v 9.5 H 274.15625 V 95.5 c -0.0105,2e-5 -0.0208,0 -0.0312,0 -11.43678,0 -20.71875,-9.25072 -20.71875,-20.6875 0,-11.43679 9.28197,-20.71875 20.71875,-20.71875 0.0105,0 0.0208,-2e-5 0.0312,0 V 20 H 169.6875 v 9.09375 h -3 V 20 Z m 146.6875,16.09375 h 3 v 14 h -3 z m 41.44141,12.833984 c 2.79067,0 5.02343,1.92774 5.02343,4.3125 0,2.38476 -2.23276,4.363282 -5.02343,4.363282 -2.73994,0 -4.97266,-1.978522 -4.97266,-4.363282 0,-2.38476 2.23272,-4.3125 4.97266,-4.3125 z m -13.22852,4.210938 v 8.017578 h 3.95899 v 6.291016 h -3.95899 v 12.279296 c 0,2.02959 0.71015,2.791016 2.13086,2.791016 0.71035,0 1.06703,-0.10181 1.82813,-0.40625 v 5.935547 c -0.71036,0.40591 -2.38661,0.964844 -4.61915,0.964844 -6.13949,0 -8.98046,-3.753876 -8.98046,-8.472657 V 67.447266 h -2.8418 V 61.15625 h 2.8418 V 55.574219 Z M 166.6875,57.09375 h 3 v 14 h -3 z m -74.568359,3.554688 c 8.473509,0 14.207029,4.515688 14.207029,14.105468 0,8.62573 -5.02336,14.105469 -12.07617,14.105469 -1.72514,0 -3.147072,-0.20329 -3.857422,-0.40625 V 99.414062 H 80.751953 V 62.728516 c 2.58772,-1.21775 6.090268,-2.080081 11.367188,-2.080078 z m 49.863279,0 c 8.57499,0 12.63436,5.935363 12.12696,15.220703 l -15.93165,2.234375 c 0.60888,2.94289 2.18061,4.414062 5.68165,4.414062 3.24732,0 5.78445,-0.711556 7.30664,-1.472656 l 2.13086,5.886719 c -2.38476,1.16701 -5.58034,2.080078 -10.6543,2.080078 -8.93017,0 -13.64844,-6.037993 -13.64844,-14.257813 0,-8.21981 4.41329,-14.105468 12.98828,-14.105468 z m -17.92187,0.0059 c 0.8928,0.01358 1.82795,0.04496 2.80468,0.0957 l -1.67578,6.697266 c -1.77589,-0.86257 -3.50104,-0.913692 -4.76953,-0.457032 v 21.513672 h -9.64062 v -25.77539 c 2.79702,-1.376314 7.03166,-2.16926 13.28125,-2.074219 z m 79.24804,0.501953 h 9.64063 v 27.347656 h -9.64063 z m 13.23438,0 h 10.04687 l 3.29883,6.849609 h 0.10156 l 3.60157,-6.849609 h 8.98047 l -7.96485,12.632812 8.72656,14.714844 H 232.67969 L 229.17773,80.9434 h -0.10156 l -3.65234,7.560547 h -9.74219 l 8.57422,-14.105468 z m -74.9668,5.023438 c -2.84142,0 -4.41381,2.585948 -4.10937,7.355468 l 7.76367,-1.166015 c 0,-4.16064 -1.2188,-6.189454 -3.6543,-6.189453 z m -49.507811,0.09961 c -0.71035,0 -1.219131,0.101686 -1.675781,0.253906 v 16.439453 c 0.35517,0.15221 0.863828,0.253906 1.523438,0.253906 3.4503,0 4.871093,-2.840514 4.871093,-8.421874 0,-5.733571 -1.21772,-8.525391 -4.71875,-8.525391 z M 166.6875,78.09375 h 3 v 14 h -3 z m 0,21 h 3 v 14 h -3 z"
|
||||
transform="translate(257.78125,548.75)"
|
||||
id="rect3888"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.4 KiB |
@@ -1,12 +0,0 @@
|
||||
Welcome to pretix's documentation!
|
||||
==================================
|
||||
|
||||
Contents:
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
admin/index
|
||||
development/index
|
||||
plugins/index
|
||||
|
||||
201
doc/plugins/banktransfer.rst
Normal file
@@ -0,0 +1,201 @@
|
||||
Bank transfer HTTP API
|
||||
======================
|
||||
|
||||
The banktransfer plugin provides a HTTP API that `pretix-banktool`_ uses to send bank
|
||||
transactions to the pretix server. This API is integrated with the regular :ref:`rest-api`
|
||||
and therefore follows the conventions listed there.
|
||||
|
||||
Bank import job resource
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Resource description
|
||||
--------------------
|
||||
|
||||
The bank import job resource contains the following public fields:
|
||||
|
||||
.. rst-class:: rest-resource-table
|
||||
|
||||
===================================== ========================== =======================================================
|
||||
Field Type Description
|
||||
===================================== ========================== =======================================================
|
||||
id integer Internal job ID
|
||||
event string Slug of the event this job was uploaded for or ``null``
|
||||
created datetime Job creation time
|
||||
state string Job state, one of ``pending``, ``running``,
|
||||
``error`` or ``completed``
|
||||
transactions list of objects Transactions included in this job (will only appear
|
||||
after the job has started processing).
|
||||
├ state string Transaction state, one of ``imported``, ``nomatch``,
|
||||
``invalid``, ``error``, ``valid``, ``discarded``,
|
||||
``already`` (already paid)
|
||||
├ message string Error message (if any)
|
||||
├ checksum string Checksum computed from payer, reference, amount and
|
||||
date
|
||||
├ payer string Payment source
|
||||
├ reference string Payment reference
|
||||
├ amount string Payment amount
|
||||
├ date string Payment date (in **user-inputted** format)
|
||||
├ order string Associated order code (or ``null``)
|
||||
└ comment string Internal comment
|
||||
===================================== ========================== =======================================================
|
||||
|
||||
Note that the ``payer`` and ``reference`` fields are set to empty as soon as the payment is matched to an order or
|
||||
discarded to avoid storing sensitive data when not necessary. The ``checksum`` persists to implement deduplication.
|
||||
|
||||
|
||||
Endpoints
|
||||
---------
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/bankimportjobs/
|
||||
|
||||
Returns a list of all bank import jobs within a given organizer the authenticated user/token has access to.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/bankimportjobs/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: text/javascript
|
||||
|
||||
{
|
||||
"count": 1,
|
||||
"next": null,
|
||||
"previous": null,
|
||||
"results": [
|
||||
{
|
||||
"id": 1,
|
||||
"state": "completed",
|
||||
"created": "2017-06-27T08:00:29Z",
|
||||
"event": "sampleconf",
|
||||
"transactions": [
|
||||
{
|
||||
"amount": "57.00",
|
||||
"comment": "",
|
||||
"date": "26.06.2017",
|
||||
"payer": "John Doe",
|
||||
"order": null,
|
||||
"checksum": "5de03a601644dfa63420dacfd285565f8375a8f2",
|
||||
"reference": "GUTSCHRIFT\r\nSAMPLECONF-NAB12 EREF: SAMPLECONF-NAB12\r\nIBAN: DE1234556…",
|
||||
"state": "nomatch",
|
||||
"message": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
:query page: The page number in case of a multi-page result set, default is 1
|
||||
:query event: Return only jobs for the event with the given slug
|
||||
:query state: Return only jobs with the given state
|
||||
:param organizer: The ``slug`` field of a valid organizer
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer does not exist **or** you have no permission to view it.
|
||||
|
||||
.. http:get:: /api/v1/organizers/(organizer)/bankimportjobs/(id)/
|
||||
|
||||
Returns information on one job, identified by its ID.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /api/v1/organizers/bigevents/bankimportjobs/1/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Vary: Accept
|
||||
Content-Type: text/javascript
|
||||
|
||||
{
|
||||
"id": 1,
|
||||
"state": "completed",
|
||||
"created": "2017-06-27T08:00:29Z",
|
||||
"event": "sampleconf",
|
||||
"transactions": [
|
||||
{
|
||||
"amount": "57.00",
|
||||
"comment": "",
|
||||
"date": "26.06.2017",
|
||||
"payer": "John Doe",
|
||||
"order": null,
|
||||
"checksum": "5de03a601644dfa63420dacfd285565f8375a8f2",
|
||||
"reference": "GUTSCHRIFT\r\nSAMPLECONF-NAB12 EREF: SAMPLECONF-NAB12\r\nIBAN: DE1234556…",
|
||||
"state": "nomatch",
|
||||
"message": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
:param organizer: The ``slug`` field of the organizer to fetch
|
||||
:statuscode 200: no error
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer/event does not exist **or** you have no permission to view it.
|
||||
|
||||
.. http:post:: /api/v1/organizers/(organizer)/bankimportjobs/
|
||||
|
||||
Upload a new job and execute it.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
POST /api/v1/organizers/bigevents/bankimportjobs/ HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"event": "sampleconf",
|
||||
"transactions": [
|
||||
{
|
||||
"payer": "Foo",
|
||||
"reference": "SAMPLECONF-173AS",
|
||||
"amount": "23.00",
|
||||
"date": "2017-06-26"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 201 Created
|
||||
Vary: Accept
|
||||
Content-Type: text/javascript
|
||||
|
||||
{
|
||||
"id": 1,
|
||||
"state": "pending",
|
||||
"created": "2017-06-27T08:00:29Z",
|
||||
"event": "sampleconf",
|
||||
"transactions": []
|
||||
}
|
||||
|
||||
.. note:: Depending on the server configuration, the job might be executed immediately, leading to a longer API
|
||||
response time but a response with state ``completed`` or ``error``, or the job might be put into a
|
||||
background queue, leading to an immediate response of state ``pending`` with an empty list of
|
||||
transactions.
|
||||
|
||||
:param organizer: The ``slug`` field of a valid organizer
|
||||
:statuscode 201: no error
|
||||
:statuscode 400: Invalid input
|
||||
:statuscode 401: Authentication failure
|
||||
:statuscode 403: The requested organizer does not exist **or** you have no permission to perform this action.
|
||||
|
||||
.. _pretix-banktool: https://github.com/pretix/pretix-banktool
|
||||
@@ -11,3 +11,4 @@ If you want to **create** a plugin, please go to the
|
||||
|
||||
list
|
||||
pretixdroid
|
||||
banktransfer
|
||||
|
||||
@@ -15,16 +15,42 @@ ways that pretix itself is:
|
||||
* PDF ticket output
|
||||
|
||||
The following plugins are not shipped with pretix but are maintained by the
|
||||
same team:
|
||||
same team. We update them regularly to make them compatible with the latest
|
||||
pretix releases:
|
||||
|
||||
* `SEPA direct debit`_
|
||||
* `Wirecard payment`_
|
||||
* `Pages`_
|
||||
* `Passbook/Wallet ticket output`_
|
||||
* `Cartshare`_
|
||||
* `Fontpack Free fonts`_
|
||||
* `Mailing list subscription`_
|
||||
|
||||
The following closed-source plugins are available to customers of the hosted pretix.eu platform.
|
||||
Please get in touch with the pretix team if you want to have them for your self-hosted
|
||||
pretix installation:
|
||||
|
||||
* Campaign tracking
|
||||
* Integration with Google Analytics and Facebook Pixel
|
||||
* Integration with Slack
|
||||
* Integration with MailChimp
|
||||
|
||||
The following plugins are from independent third-party authors, so we can make
|
||||
no statements about their stability:
|
||||
no statements about their functionality, security, stability or compatibility:
|
||||
|
||||
* `esPass ticket output`_
|
||||
* `IcePay integration`_
|
||||
* `Average price chart`_
|
||||
* `Pay in cash upon arrival`_
|
||||
|
||||
.. _SEPA direct debit: https://github.com/pretix/pretix-sepadebit
|
||||
.. _Passbook/Wallet ticket output: https://github.com/pretix/pretix-passbook
|
||||
.. _Cartshare: https://github.com/pretix/pretix-cartshare
|
||||
.. _Pages: https://github.com/pretix/pretix-pages
|
||||
.. _esPass ticket output: https://github.com/esPass/pretix-espass
|
||||
.. _IcePay integration: https://github.com/chotee/pretix-icepay
|
||||
.. _Fontpack Free fonts: https://github.com/pretix/pretix-fontpack-free
|
||||
.. _Wirecard payment: https://github.com/pretix/pretix-wirecard
|
||||
.. _Mailing list subscription: https://github.com/pretix/pretix-newsletter-ml
|
||||
.. _Average price chart: https://github.com/rixx/pretix-avgchart
|
||||
.. _Pay in cash upon arrival: https://github.com/pc-coholic/pretix-cashpayment
|
||||
|
||||
@@ -4,6 +4,11 @@ pretixdroid HTTP API
|
||||
The pretixdroid plugin provides a HTTP API that the `pretixdroid Android app`_
|
||||
uses to communicate with the pretix server.
|
||||
|
||||
.. warning:: This API is intended **only** to serve the pretixdroid Android app. There are no backwards compatibility
|
||||
guarantees on this API. We will not add features that are not required for the Android App. There is a
|
||||
general-purpose :ref:`rest-api` that not yet provides all features that this API provides, but will do
|
||||
so in the future.
|
||||
|
||||
.. http:post:: /pretixdroid/api/(organizer)/(event)/redeem/
|
||||
|
||||
Redeems a ticket, i.e. checks the user in.
|
||||
@@ -19,6 +24,16 @@ uses to communicate with the pretix server.
|
||||
|
||||
secret=az9u4mymhqktrbupmwkvv6xmgds5dk3
|
||||
|
||||
You can optionally include the additional parameter ``datetime`` in the body containing an ISO8601-encoded
|
||||
datetime of the entry attempt. If you don't, the current date and time will be used.
|
||||
|
||||
You can optionally include the additional parameter ``force`` to indicate that the request should be logged
|
||||
regardless of previous check-ins for the same ticket. This might be useful if you made the entry decision offline.
|
||||
|
||||
You can optionally include the additional parameter ``nonce`` with a globally unique random value to identify this
|
||||
check-in. This is meant to be used to prevent duplicate check-ins when you are just retrying after a connection
|
||||
failure.
|
||||
|
||||
**Example successful response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
@@ -51,9 +66,9 @@ uses to communicate with the pretix server.
|
||||
* ``unknown_ticket`` - Secret does not match a ticket in the database
|
||||
|
||||
:query key: Secret API key
|
||||
:statuscode 200: Valid request
|
||||
:statuscode 404: Unknown organizer or event
|
||||
:statuscode 403: Invalid authorization key
|
||||
:statuscode 200: Valid request
|
||||
:statuscode 404: Unknown organizer or event
|
||||
:statuscode 403: Invalid authorization key
|
||||
|
||||
.. http:get:: /pretixdroid/api/(organizer)/(event)/search/
|
||||
|
||||
@@ -97,6 +112,46 @@ uses to communicate with the pretix server.
|
||||
:statuscode 404: Unknown organizer or event
|
||||
:statuscode 403: Invalid authorization key
|
||||
|
||||
.. http:get:: /pretixdroid/api/(organizer)/(event)/download/
|
||||
|
||||
Download data for all tickets.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
GET /pretixdroid/api/demoorga/democon/download/?key=ABCDEF HTTP/1.1
|
||||
Host: demo.pretix.eu
|
||||
Accept: application/json, text/javascript
|
||||
|
||||
**Example response**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: text/json
|
||||
|
||||
{
|
||||
"results": [
|
||||
{
|
||||
"secret": "az9u4mymhqktrbupmwkvv6xmgds5dk3",
|
||||
"order": "ABCE6",
|
||||
"item": "Standard ticket",
|
||||
"variation": null,
|
||||
"attendee_name": "Peter Higgs",
|
||||
"redeemed": false,
|
||||
"paid": true
|
||||
},
|
||||
...
|
||||
],
|
||||
"version": 2
|
||||
}
|
||||
|
||||
:query key: Secret API key
|
||||
:statuscode 200: Valid request
|
||||
:statuscode 404: Unknown organizer or event
|
||||
:statuscode 403: Invalid authorization key
|
||||
|
||||
.. http:get:: /pretixdroid/api/(organizer)/(event)/status/
|
||||
|
||||
Returns status information, such as the total number of tickets and the
|
||||
|
||||
7
doc/user/index.rst
Normal file
@@ -0,0 +1,7 @@
|
||||
User Guide
|
||||
==========
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
payments/index
|
||||
31
doc/user/payments/banktransfer.rst
Normal file
@@ -0,0 +1,31 @@
|
||||
.. _`banktransfer`:
|
||||
|
||||
Bank transfer
|
||||
=============
|
||||
|
||||
To accept payments with bank transfer, you only need to fill one important field in pretix' settings: In "Bank
|
||||
account details" you should specify everything one needs to know to transfer money to you, e.g. your IBAN and BIC,
|
||||
the name of your bank and for international transfers, preferably also your address and the bank's address.
|
||||
|
||||
pretix will automatically tell the user to include the order code in the payment reference so incoming transfers can
|
||||
automatically be matched to payments.
|
||||
|
||||
Importing payment data
|
||||
----------------------
|
||||
|
||||
The easiest way to import payment data is to download a CSV file from your online banking. Most banks provide a CSV
|
||||
export of some sort. You can go to "Import bank data" in pretix to upload a new file:
|
||||
|
||||
.. image:: img/bank1.png
|
||||
|
||||
If you upload a file for the first time, pretix will not know what information is contained in which column as every
|
||||
bank builds completely different CSV files. Therefore, pretix will ask you for that information. It will show you the
|
||||
data of the file you imported and ask you to define the column's meanings. You can select one column that contains
|
||||
the payment date and one that contains the paid amount. You can select multiple columns that contain information
|
||||
about the payer or the payment reference. All other columns will be ignored.
|
||||
|
||||
Once you continue, pretix will try to match the payments to the respective orders automatically. It will tell you how
|
||||
many orders could be processed correctly and how many could not. You can then go back to the upload page to see all
|
||||
transfers from your bank statement that are not yet matched to an order. Using the input field and the buttons on the
|
||||
left of each transaction, you can manually enter an order code to match it to or just discard it from the list, e.g.
|
||||
if the transaction is not related to the event at all.
|
||||
58
doc/user/payments/fees.rst
Normal file
@@ -0,0 +1,58 @@
|
||||
Payment method fees
|
||||
===================
|
||||
|
||||
Most external payment providers like PayPal or Stripe charge substantial fees for your service. In general, you have
|
||||
two options to deal with this:
|
||||
|
||||
1. Pay the fees yourself
|
||||
|
||||
2. Add the fees to your customer's total
|
||||
|
||||
The choice totally depends on you and what your customers expect from you. Option two might be appropriate if you
|
||||
offer different payment methods and want to encourage your customers to use the ones that come you cheaper, but you
|
||||
might also decide to go for option one to make it easier for customers who don't have the option.
|
||||
|
||||
.. warning:: Please note that EU Directive 2015/2366 bans surcharging payment fees for most common payment
|
||||
methods within the European Union. Depending on the payment method, this might affect
|
||||
selling to consumers only or to business customers as well. Depending on your country, this
|
||||
legislation might already be in place or become relevant from January 2018 the latest. This is not
|
||||
legal advice. If in doubt, consult a lawyer or refrain from charging payment fees.
|
||||
|
||||
If you go for the second option, you can configure pretix to charge the payment method fees to your user. You can
|
||||
define both an absolute fee as well as a percental fee based on the order total. If you do so, there are two
|
||||
different ways in which pretix can calculate the fee. Normally, it is fine to just go with the default setting, but
|
||||
in case you are interested, here are all the details:
|
||||
|
||||
Payment fee calculation
|
||||
-----------------------
|
||||
|
||||
If you configure a fee for a payment method, there are two possible ways for us to calculate this. Let's
|
||||
assume that your payment provider, e.g. PayPal, charges you 5 % fees and you want to charge your users the
|
||||
same 5 %, such that for a ticket with a list price of 100 € you will get your full 100 €.
|
||||
|
||||
**Method A: Calculate the fee from the subtotal and add it to the bill.**
|
||||
|
||||
For a ticket price of 100 €, this will lead to the following calculation:
|
||||
|
||||
============================================== ============
|
||||
Ticket price 100.00 €
|
||||
pretix calculates the fee as 5 % of 100 € +5.00 €
|
||||
Subtotal that will be paid by the customer 105.00 €
|
||||
PayPal calculates its fee as 5 % of 105 € -5.25 €
|
||||
End total that is on your bank account **99.75 €**
|
||||
============================================== ============
|
||||
|
||||
**Method B (default): Calculate the fee from the total value including the fee.**
|
||||
|
||||
For a ticket price of 100 €, this will lead to the following calculation:
|
||||
|
||||
===================================================== =============
|
||||
Ticket price 100.00 €
|
||||
pretix calculates the fee as 100/(100 - 5) % of 100 € +5.26 €
|
||||
Subtotal that will be paid by the customer 105.26 €
|
||||
PayPal calculates its fee as 5 % of 105 € -5.26 €
|
||||
End total that is on your bank account **100.00 €**
|
||||
===================================================== =============
|
||||
|
||||
Due to the various rounding steps performed by pretix and by the payment provider, the end total on
|
||||
your bank account might stil vary by one cent.
|
||||
BIN
doc/user/payments/img/bank1.png
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
doc/user/payments/img/bank2.png
Normal file
|
After Width: | Height: | Size: 31 KiB |
BIN
doc/user/payments/img/paypal1.png
Normal file
|
After Width: | Height: | Size: 95 KiB |
BIN
doc/user/payments/img/paypal2.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
doc/user/payments/img/paypal3.png
Normal file
|
After Width: | Height: | Size: 89 KiB |
BIN
doc/user/payments/img/paypal4.png
Normal file
|
After Width: | Height: | Size: 89 KiB |
BIN
doc/user/payments/img/paypal5.png
Normal file
|
After Width: | Height: | Size: 72 KiB |
BIN
doc/user/payments/img/paypal6.png
Normal file
|
After Width: | Height: | Size: 94 KiB |
BIN
doc/user/payments/img/paypal7.png
Normal file
|
After Width: | Height: | Size: 94 KiB |
BIN
doc/user/payments/img/paypal8.png
Normal file
|
After Width: | Height: | Size: 105 KiB |
BIN
doc/user/payments/img/paypal_pretix.png
Normal file
|
After Width: | Height: | Size: 23 KiB |
BIN
doc/user/payments/img/stripe1.png
Normal file
|
After Width: | Height: | Size: 81 KiB |
BIN
doc/user/payments/img/stripe2.png
Normal file
|
After Width: | Height: | Size: 81 KiB |
12
doc/user/payments/index.rst
Normal file
@@ -0,0 +1,12 @@
|
||||
Accepting payments
|
||||
==================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
overview
|
||||
fees
|
||||
paypal
|
||||
stripe
|
||||
banktransfer
|
||||
|
||||
34
doc/user/payments/overview.rst
Normal file
@@ -0,0 +1,34 @@
|
||||
Payment method overview
|
||||
=======================
|
||||
|
||||
pretix allows you to accept payments using a variety of payment methods to fit the needs of very different events.
|
||||
This page gives you a short overview over them and links to more detailled descriptions in some cases.
|
||||
|
||||
Payment methods are built as pretix plugins. For this reason, you might first need to enable a certain plugin at
|
||||
"Settings" → "Plugins" in your event settings. Then, you can configure them in detail at "Settings" -> "Payment".
|
||||
|
||||
If you host pretix on your own server, you might need to install a plugin first for some of the payment methods listed
|
||||
on this page as well as for additional ones.
|
||||
|
||||
:ref:`stripe`
|
||||
Stripe is a US-based company that offers you an easy way to accept credit card payments from all over the world.
|
||||
To accept payments with Stripe, you need to have a Stripe merchant account that is easy to create. Click on the link
|
||||
above to get more details about the Stripe integration into pretix.
|
||||
|
||||
:ref:`paypal`
|
||||
If you want to accept online payments via PayPal, you can do so using pretix. You will need a PayPal merchant
|
||||
account and it is a little bit complicated to obtain the required technical details, but we've got you covered.
|
||||
Click on the link above to learn more.
|
||||
|
||||
:ref:`banktransfer`
|
||||
Classical IBAN wire transfers are a common payment method in central Europe that has the large benefit that it
|
||||
often does not cause any additional fees. However, it requires you to invest some more effort as you need to
|
||||
check your bank account for incoming payments regularly. We provide some tools to make this easier for you.
|
||||
|
||||
SEPA debit
|
||||
In some Europen countries, a very popular online payment method is SEPA direct debit. If you want to offer this
|
||||
option in your pretix ticket shop, we provide a convenient plugin that allows users to enter their SEPA bank
|
||||
account details and issue a SEPA mandate. You will then need to regularly download a SEPA XML file from pretix
|
||||
and upload it to your bank's interface to actually perform the debits.
|
||||
|
||||
|
||||
50
doc/user/payments/paypal.rst
Normal file
@@ -0,0 +1,50 @@
|
||||
.. _`paypal`:
|
||||
|
||||
PayPal
|
||||
======
|
||||
|
||||
To integrate PayPal with pretix, you first need to have an active PayPal merchant account. If you do not already have a
|
||||
PayPal account, you can create one on `paypal.com`_.
|
||||
If you look into pretix' settings, you are required to fill in two keys:
|
||||
|
||||
.. image:: img/paypal_pretix.png
|
||||
|
||||
Unfortunately, it is not straightforward how to get those keys from PayPal's website. In order to do so, you
|
||||
need to go to `developer.paypal.com`_ to link the account to your pretix event.
|
||||
Click on "Log In" in the top-right corner and log in with your PayPal account.
|
||||
|
||||
.. image:: img/paypal2.png
|
||||
|
||||
Then, click on "Dashboard" in the top-right corner.
|
||||
|
||||
.. image:: img/paypal3.png
|
||||
|
||||
In the dashboard, scroll down until you see the headline "REST API Apps". Click "Create App".
|
||||
|
||||
.. image:: img/paypal4.png
|
||||
|
||||
Enter any name for the application that helps you to identify it later. Then confirm with "Create App".
|
||||
|
||||
.. image:: img/paypal5.png
|
||||
|
||||
On the next page, before you do anything else, switch the mode on the right to "Live" to get the correct keys.
|
||||
Then, copy the "Client ID" and the "Secret" and enter them into the appropriate fields in the payment settings in
|
||||
pretix.
|
||||
|
||||
.. image:: img/paypal6.png
|
||||
|
||||
Finally, we need to create a webhook. The webhook tells PayPal to notify pretix e.g. if a payment gets cancelled so
|
||||
pretix can cancel the ticket as well. If you have multiple events connected to your PayPal account, you need multiple
|
||||
webhooks. To create one, scroll a bit down and click "Add Webhook".
|
||||
|
||||
.. image:: img/paypal7.png
|
||||
|
||||
Then, enter the webhook URL that you find on the pretix settings page. It should look similar to the one in the
|
||||
screenshot but contain your event name. Tick the box "All events" and save.
|
||||
|
||||
.. image:: img/paypal8.png
|
||||
|
||||
That's it, you are ready to go!
|
||||
|
||||
.. _paypal.com: https://www.paypal.com/webapps/mpp/account-selection
|
||||
.. _developer.paypal.com: https://developer.paypal.com/
|
||||
28
doc/user/payments/stripe.rst
Normal file
@@ -0,0 +1,28 @@
|
||||
.. _stripe:
|
||||
|
||||
Stripe
|
||||
======
|
||||
|
||||
To integrate Stripe with pretix, you first need to have an active Stripe merchant account. If you do not already have a
|
||||
Stripe account, you can create one on `stripe.com`_. Then, click on "API" in the left navigation of the Stripe
|
||||
Dashboard. As you can see in the following screenshot, you will be presented with two sets of API keys, one for test
|
||||
and one for live payments. In each set, there is a secret and a publishable keys.
|
||||
|
||||
.. image:: img/stripe1.png
|
||||
|
||||
Choose one of the two sets and copy the two keys to the appropriate fields in pretix' settings. To perform actual
|
||||
payments, you will need to use the live keys, but you can use the test keys to test the payment flow before you go live.
|
||||
In test mode, you cannot use your real credit card, but only `test cards`_ like ``4242424242424242`` that you can
|
||||
find in Stripe's documentation.
|
||||
|
||||
If you want Stripe to notify pretix automatically once a payment gets cancelled, so pretix can cancel the ticket as
|
||||
well, you need to create a so-called webhook. To do so, click "Webhooks" on top of the page in the Stripe dashboard
|
||||
that you are currently on. Then, click "Add endpoint" and enter the URL that you find directly below the key
|
||||
configuration in pretix' settings.
|
||||
|
||||
.. image:: img/stripe2.png
|
||||
|
||||
Again, you can choose between live mode and test mode here.
|
||||
|
||||
.. _stripe.com: https://dashboard.stripe.com/register
|
||||
.. _test cards: https://stripe.com/docs/testing#cards
|
||||
@@ -16,3 +16,5 @@ recursive-include pretix/plugins/statistics/templates *
|
||||
recursive-include pretix/plugins/statistics/static *
|
||||
recursive-include pretix/plugins/stripe/templates *
|
||||
recursive-include pretix/plugins/stripe/static *
|
||||
recursive-include pretix/plugins/ticketoutputpdf/templates *
|
||||
recursive-include pretix/plugins/ticketoutputpdf/static *
|
||||
|
||||
@@ -23,9 +23,6 @@ user.save()
|
||||
organizer = Organizer.objects.create(
|
||||
name='BigEvents LLC', slug='bigevents'
|
||||
)
|
||||
OrganizerPermission.objects.get_or_create(
|
||||
organizer=organizer, user=user
|
||||
)
|
||||
year = now().year + 1
|
||||
event = Event.objects.create(
|
||||
organizer=organizer, name='Demo Conference {}'.format(year),
|
||||
@@ -33,9 +30,13 @@ event = Event.objects.create(
|
||||
date_from=datetime(year, 9, 4, 17, 0, 0),
|
||||
date_to=datetime(year, 9, 6, 17, 0, 0),
|
||||
)
|
||||
EventPermission.objects.get_or_create(
|
||||
event=event, user=user
|
||||
t = Team.objects.get_or_create(
|
||||
organizer=organizer, name='Admin Team',
|
||||
all_events=True, can_create_events=True, can_change_teams=True,
|
||||
can_change_organizer_settings=True, can_change_event_settings=True, can_change_items=True,
|
||||
can_view_orders=True, can_change_orders=True, can_view_vouchers=True, can_change_vouchers=True
|
||||
)
|
||||
t[0].members.add(user)
|
||||
cat_tickets = ItemCategory.objects.create(
|
||||
event=event, name='Tickets'
|
||||
)
|
||||
|
||||
@@ -1 +1 @@
|
||||
__version__ = "1.0.0b2"
|
||||
__version__ = "1.6.0"
|
||||
|
||||
0
src/pretix/api/__init__.py
Normal file
0
src/pretix/api/auth/__init__.py
Normal file
43
src/pretix/api/auth/permission.py
Normal file
@@ -0,0 +1,43 @@
|
||||
from rest_framework.permissions import SAFE_METHODS, BasePermission
|
||||
|
||||
from pretix.base.models import Event
|
||||
from pretix.base.models.organizer import Organizer, TeamAPIToken
|
||||
|
||||
|
||||
class EventPermission(BasePermission):
|
||||
model = TeamAPIToken
|
||||
|
||||
def has_permission(self, request, view):
|
||||
if not request.user.is_authenticated and not isinstance(request.auth, TeamAPIToken):
|
||||
if request.method in SAFE_METHODS and request.path.startswith('/api/v1/docs/'):
|
||||
return True
|
||||
return False
|
||||
|
||||
perm_holder = (request.auth if isinstance(request.auth, TeamAPIToken)
|
||||
else request.user)
|
||||
if 'event' in request.resolver_match.kwargs and 'organizer' in request.resolver_match.kwargs:
|
||||
request.event = Event.objects.filter(
|
||||
slug=request.resolver_match.kwargs['event'],
|
||||
organizer__slug=request.resolver_match.kwargs['organizer'],
|
||||
).select_related('organizer').first()
|
||||
if not request.event or not perm_holder.has_event_permission(request.event.organizer, request.event):
|
||||
return False
|
||||
request.organizer = request.event.organizer
|
||||
request.eventpermset = perm_holder.get_event_permission_set(request.organizer, request.event)
|
||||
|
||||
if hasattr(view, 'permission'):
|
||||
if view.permission and view.permission not in request.eventpermset:
|
||||
return False
|
||||
|
||||
elif 'organizer' in request.resolver_match.kwargs:
|
||||
request.organizer = Organizer.objects.filter(
|
||||
slug=request.resolver_match.kwargs['organizer'],
|
||||
).first()
|
||||
if not request.organizer or not perm_holder.has_organizer_permission(request.organizer):
|
||||
return False
|
||||
request.orgapermset = perm_holder.get_organizer_permission_set(request.organizer)
|
||||
|
||||
if hasattr(view, 'permission'):
|
||||
if view.permission and view.permission not in request.orgapermset:
|
||||
return False
|
||||
return True
|
||||
21
src/pretix/api/auth/token.py
Normal file
@@ -0,0 +1,21 @@
|
||||
from django.contrib.auth.models import AnonymousUser
|
||||
from rest_framework import exceptions
|
||||
from rest_framework.authentication import TokenAuthentication
|
||||
|
||||
from pretix.base.models.organizer import TeamAPIToken
|
||||
|
||||
|
||||
class TeamTokenAuthentication(TokenAuthentication):
|
||||
model = TeamAPIToken
|
||||
|
||||
def authenticate_credentials(self, key):
|
||||
model = self.get_model()
|
||||
try:
|
||||
token = model.objects.select_related('team', 'team__organizer').get(token=key)
|
||||
except model.DoesNotExist:
|
||||
raise exceptions.AuthenticationFailed('Invalid token.')
|
||||
|
||||
if not token.active:
|
||||
raise exceptions.AuthenticationFailed('Token inactive or deleted.')
|
||||
|
||||
return AnonymousUser(), token
|
||||