slthcore 0.0.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of slthcore might be problematic. Click here for more details.

Files changed (50) hide show
  1. slthcore-0.0.1/MANIFEST.in +3 -0
  2. slthcore-0.0.1/PKG-INFO +16 -0
  3. slthcore-0.0.1/requirements.txt +9 -0
  4. slthcore-0.0.1/setup.cfg +4 -0
  5. slthcore-0.0.1/setup.py +28 -0
  6. slthcore-0.0.1/slth/__init__.py +128 -0
  7. slthcore-0.0.1/slth/components.py +339 -0
  8. slthcore-0.0.1/slth/db/__init__.py +3 -0
  9. slthcore-0.0.1/slth/db/models.py +140 -0
  10. slthcore-0.0.1/slth/endpoints.py +808 -0
  11. slthcore-0.0.1/slth/exceptions.py +6 -0
  12. slthcore-0.0.1/slth/factory.py +129 -0
  13. slthcore-0.0.1/slth/forms.py +721 -0
  14. slthcore-0.0.1/slth/management/__init__.py +0 -0
  15. slthcore-0.0.1/slth/management/commands/__init__.py +0 -0
  16. slthcore-0.0.1/slth/management/commands/integration_test.py +27 -0
  17. slthcore-0.0.1/slth/management/commands/sync.py +35 -0
  18. slthcore-0.0.1/slth/migrations/0001_initial.py +41 -0
  19. slthcore-0.0.1/slth/migrations/0002_email_role_pushsubscription_error.py +78 -0
  20. slthcore-0.0.1/slth/migrations/0003_rename_photo_profile_alter_profile_options.py +23 -0
  21. slthcore-0.0.1/slth/migrations/0004_alter_profile_photo.py +18 -0
  22. slthcore-0.0.1/slth/migrations/0005_alter_profile_photo.py +19 -0
  23. slthcore-0.0.1/slth/migrations/0006_user.py +33 -0
  24. slthcore-0.0.1/slth/migrations/__init__.py +0 -0
  25. slthcore-0.0.1/slth/models.py +195 -0
  26. slthcore-0.0.1/slth/notifications.py +15 -0
  27. slthcore-0.0.1/slth/oauth.py +57 -0
  28. slthcore-0.0.1/slth/permissions.py +56 -0
  29. slthcore-0.0.1/slth/queryset.py +474 -0
  30. slthcore-0.0.1/slth/roles.py +103 -0
  31. slthcore-0.0.1/slth/selenium/__init__.py +243 -0
  32. slthcore-0.0.1/slth/selenium/browser.py +300 -0
  33. slthcore-0.0.1/slth/serializer.py +348 -0
  34. slthcore-0.0.1/slth/static/.DS_Store +0 -0
  35. slthcore-0.0.1/slth/static/css/.DS_Store +0 -0
  36. slthcore-0.0.1/slth/static/css/slth.css +82 -0
  37. slthcore-0.0.1/slth/static/js/index.min.js +1 -0
  38. slthcore-0.0.1/slth/static/js/react.min.js +40 -0
  39. slthcore-0.0.1/slth/static/js/slth.min.js +187 -0
  40. slthcore-0.0.1/slth/statistics.py +173 -0
  41. slthcore-0.0.1/slth/templates/index.html +81 -0
  42. slthcore-0.0.1/slth/templates/service-worker.js +39 -0
  43. slthcore-0.0.1/slth/tests.py +174 -0
  44. slthcore-0.0.1/slth/urls.py +28 -0
  45. slthcore-0.0.1/slth/utils.py +32 -0
  46. slthcore-0.0.1/slth/views.py +61 -0
  47. slthcore-0.0.1/slthcore.egg-info/PKG-INFO +16 -0
  48. slthcore-0.0.1/slthcore.egg-info/SOURCES.txt +48 -0
  49. slthcore-0.0.1/slthcore.egg-info/dependency_links.txt +1 -0
  50. slthcore-0.0.1/slthcore.egg-info/top_level.txt +1 -0
@@ -0,0 +1,3 @@
1
+ include requirements.txt
2
+ recursive-include slth/static *.*
3
+ recursive-include slth/templates *.*
@@ -0,0 +1,16 @@
1
+ Metadata-Version: 2.1
2
+ Name: slthcore
3
+ Version: 0.0.1
4
+ Summary: API generator based on yml file
5
+ Home-page: https://github.com/brenokcc
6
+ Author: Breno Silva
7
+ Author-email: brenokcc@yahoo.com.br
8
+ License: BSD License
9
+ Classifier: Environment :: Web Environment
10
+ Classifier: Framework :: Django
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: License :: OSI Approved :: BSD License
13
+ Classifier: Operating System :: OS Independent
14
+ Classifier: Programming Language :: Python
15
+ Classifier: Topic :: Internet :: WWW/HTTP
16
+ Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
@@ -0,0 +1,9 @@
1
+ Django==4.2.7
2
+ selenium==4.15.2
3
+ whitenoise==6.6.0
4
+ pyyaml==6.0.1
5
+ Pillow==10.3.0
6
+ pywebpush==1.14.0
7
+ psycopg2-binary==2.9.5
8
+ django-redis==5.4.0
9
+ gunicorn==22.0.0
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,28 @@
1
+ import os
2
+ from setuptools import find_packages, setup
3
+
4
+ install_requires = []
5
+
6
+ setup(
7
+ name='slthcore',
8
+ version='0.0.1',
9
+ packages=find_packages(),
10
+ install_requires=install_requires,
11
+ include_package_data=True,
12
+ license='BSD License',
13
+ description='API generator based on yml file',
14
+ long_description='',
15
+ url='https://github.com/brenokcc',
16
+ author='Breno Silva',
17
+ author_email='brenokcc@yahoo.com.br',
18
+ classifiers=[
19
+ 'Environment :: Web Environment',
20
+ 'Framework :: Django',
21
+ 'Intended Audience :: Developers',
22
+ 'License :: OSI Approved :: BSD License',
23
+ 'Operating System :: OS Independent',
24
+ 'Programming Language :: Python',
25
+ 'Topic :: Internet :: WWW/HTTP',
26
+ 'Topic :: Internet :: WWW/HTTP :: Dynamic Content',
27
+ ],
28
+ )
@@ -0,0 +1,128 @@
1
+ import re
2
+ import os
3
+ import yaml
4
+ import warnings
5
+ from pathlib import Path
6
+ from django.apps import apps
7
+ from django.db import models
8
+ from .queryset import QuerySet
9
+ from django.db.models import manager
10
+ from .serializer import Serializer
11
+ from .factory import FormFactory
12
+ import django.db.models.options as options
13
+ from django.db.models.base import ModelBase
14
+ from django.core.exceptions import FieldDoesNotExist
15
+ from django.utils.autoreload import autoreload_started
16
+
17
+ warnings.filterwarnings('ignore', module='urllib3')
18
+
19
+ FILENAME = 'application.yml'
20
+ ENDPOINTS = {}
21
+ PROXIED_MODELS = []
22
+ APPLICATON = None
23
+
24
+ if APPLICATON is None and os.path.exists(FILENAME):
25
+ with open(FILENAME) as file:
26
+ content = file.read()
27
+ for variable in re.findall(r'\$[a-zA-z0-9_]+', content):
28
+ content = content.replace(variable, os.environ.get(variable[1:], ''))
29
+ APPLICATON = yaml.safe_load(content).get('application')
30
+
31
+
32
+ class BaseManager(manager.BaseManager):
33
+ def get_queryset(self):
34
+ return super().get_queryset()
35
+
36
+ def all(self):
37
+ return self.get_queryset().all()
38
+
39
+ def __call__(self, model):
40
+ return apps.get_model(model)
41
+
42
+
43
+ class Manager(BaseManager.from_queryset(QuerySet)):
44
+ pass
45
+
46
+
47
+ models.QuerySet = QuerySet
48
+ models.Manager = Manager
49
+ setattr(options, 'DEFAULT_NAMES', options.DEFAULT_NAMES + ('icon', 'search_fields'))
50
+
51
+
52
+
53
+ class ModelMixin(object):
54
+
55
+ @classmethod
56
+ def get_field(cls, lookup):
57
+ model = cls
58
+ attrs = lookup.split('__')
59
+ while attrs:
60
+ attr_name = attrs.pop(0)
61
+ if attrs: # go deeper
62
+ field = model._meta.get_field(attr_name)
63
+ model = field.related_model
64
+ else:
65
+ try:
66
+ return model._meta.get_field(attr_name)
67
+ except FieldDoesNotExist:
68
+ pass
69
+ return None
70
+
71
+ def getroles(self, username_lookup='username'):
72
+ roles = getattr(self, '_roles', None)
73
+ if roles is None:
74
+ obj = self
75
+ for attr_name in username_lookup.split('__'):
76
+ obj = getattr(obj, attr_name)
77
+ roles = apps.get_model('api.role').objects.filter(username=obj)
78
+ setattr(self, '_roles', roles)
79
+ return roles
80
+
81
+ def getuser(self, username_lookup):
82
+ obj = self
83
+ for attr_name in username_lookup.split('__'):
84
+ obj = getattr(obj, attr_name)
85
+ return apps.get_model('auth.user').objects.get(username=obj)
86
+
87
+ def serializer(self) -> Serializer:
88
+ return Serializer(self)
89
+
90
+ def formfactory(self) -> FormFactory:
91
+ return FormFactory(self)
92
+
93
+
94
+ ___new___ = ModelBase.__new__
95
+
96
+
97
+ def __new__(mcs, name, bases, attrs, **kwargs):
98
+ if attrs['__module__'] != '__fake__':
99
+ # See .db.models.Manager
100
+ if 'objects' in attrs and isinstance(attrs['objects'], QuerySet):
101
+ queryset_class = attrs['objects']
102
+ attrs.update(objects=BaseManager.from_queryset(type(queryset_class))())
103
+ # Defining the objects Manager using .db.models.QuerySet
104
+ if 'objects' not in attrs and not all(['objects' in dir(cls) for cls in bases]):
105
+ attrs.update(objects=BaseManager.from_queryset(QuerySet)())
106
+
107
+ if ModelMixin not in bases:
108
+ bases = bases + (ModelMixin, )
109
+ cls = ___new___(mcs, name, bases, attrs, **kwargs)
110
+ if cls._meta.proxy_for_model:
111
+ PROXIED_MODELS.append(cls._meta.proxy_for_model)
112
+ return cls
113
+
114
+
115
+ ModelBase.__new__ = __new__
116
+
117
+
118
+ def api_watchdog(sender, **kwargs):
119
+ sender.extra_files.add(Path('application.yml'))
120
+
121
+ autoreload_started.connect(api_watchdog)
122
+
123
+
124
+ def meta(verbose_name=None):
125
+ def decorate(function):
126
+ function.verbose_name = verbose_name
127
+ return function
128
+ return decorate
@@ -0,0 +1,339 @@
1
+ from datetime import date, timedelta, datetime
2
+ from django.template.loader import render_to_string
3
+
4
+
5
+ SUCCESS = "success"
6
+ PRIMARY = "primary"
7
+ WARNING = "warning"
8
+ DANGER = "danger"
9
+
10
+ class Text(dict):
11
+ def __init__(self, text, color="inherite", size="inherite", bold=False, italic=False):
12
+ self["type"] = "text"
13
+ self["text"] = text
14
+ self["color"] = color
15
+ self["bold"] = bold
16
+ self["italic"] = italic
17
+
18
+ class Image(dict):
19
+ def __init__(self, src, width=None, height=None, round=False, placeholder=None):
20
+ if width is None and height is None:
21
+ width = 100
22
+ height = 100
23
+ if width and not height:
24
+ height = width
25
+ if height and not width:
26
+ width = height
27
+ self["type"] = "image"
28
+ self["src"] = src
29
+ self["width"] = width
30
+ self["height"] = height
31
+ self["round"] = round
32
+ self["placeholder"] = placeholder
33
+
34
+
35
+ class FileLink(dict):
36
+ def __init__(self, url, modal=False, icon=None):
37
+ self["type"] = "filelink"
38
+ self["url"] = url
39
+ self["modal"] = modal
40
+ self["icon"] = icon
41
+
42
+
43
+ class FileViewer(dict):
44
+ def __init__(self, url):
45
+ self["type"] = "filepreview"
46
+ self["url"] = url
47
+
48
+
49
+ class QrCode(dict):
50
+ def __init__(self, text):
51
+ self["type"] = "qrcode"
52
+ self["text"] = text
53
+
54
+
55
+ class Progress(dict):
56
+ def __init__(self, value, style="primary"):
57
+ self["type"] = "progress"
58
+ self["value"] = int(value or 0)
59
+ self["style"] = style
60
+
61
+
62
+ class Status(dict):
63
+ def __init__(self, style, label):
64
+ self["type"] = "status"
65
+ self["style"] = style
66
+ self["label"] = str(label)
67
+
68
+
69
+ class Badge(dict):
70
+ def __init__(self, color, label, icon=None):
71
+ self["type"] = "badge"
72
+ self["color"] = color
73
+ self["label"] = str(label)
74
+ self["icon"] = icon
75
+
76
+
77
+ class Shell(dict):
78
+ def __init__(self, output):
79
+ self["type"] = "shell"
80
+ self["output"] = output
81
+
82
+
83
+ class Indicators(dict):
84
+ def __init__(self, title):
85
+ self["type"] = "indicators"
86
+ self["title"] = title
87
+ self["items"] = []
88
+ self["actions"] = []
89
+
90
+ def append(self, name, value):
91
+ self["items"].append(dict(name=str(name), value=value))
92
+
93
+ def action(self, label, url, modal=False):
94
+ self["actions"].append(dict(label=str(label), url=url, modal=modal))
95
+
96
+
97
+ class Boxes(dict):
98
+ def __init__(self, title):
99
+ self["type"] = "boxes"
100
+ self["title"] = str(title)
101
+ self["items"] = []
102
+
103
+ def append(self, icon, label, url, style=None):
104
+ self["items"].append(dict(icon=icon, label=str(label), url=url, style=style))
105
+
106
+
107
+ class Info(dict):
108
+ def __init__(self, title, message):
109
+ self["type"] = "info"
110
+ self["title"] = title
111
+ self["message"] = message
112
+ self["actions"] = []
113
+
114
+ def action(self, label, url, modal=False, icon=None):
115
+ self["actions"].append(dict(label=str(label), url=url, modal=modal, icon=icon))
116
+
117
+
118
+ class Warning(dict):
119
+ def __init__(self, title, message):
120
+ self["type"] = "warning"
121
+ self["title"] = title
122
+ self["message"] = message
123
+ self["actions"] = []
124
+
125
+ def action(self, label, url, modal=False, icon=None):
126
+ self["actions"].append(dict(label=str(label), url=url, modal=modal, icon=icon))
127
+
128
+
129
+ class Table(dict):
130
+ def __init__(self, title, subset=None, pagination=None):
131
+ self["type"] = "table"
132
+ self["title"] = title
133
+ self["actions"] = []
134
+ self["subsets"] = []
135
+ self["subset"] = subset
136
+ self["filters"] = []
137
+ self["flags"] = []
138
+ self["rows"] = []
139
+ self["pagination"] = {}
140
+
141
+ def add_subset(self, name, label, count):
142
+ self["subsets"].append(dict(name=name, label=label, count=count))
143
+
144
+ def add_action(self, name, label, icon=None, batch=True):
145
+ self["actions"].append(dict(name=name, label=label, icon=icon, batch=batch))
146
+
147
+ def add_flag(self, name, label, checked=False):
148
+ self["flags"].append(dict(name=name, label=label, checked=checked))
149
+
150
+ def add_filter(self, ftype, name, label, value, choices=None):
151
+ self["filters"].append(
152
+ dict(type=ftype, name=name, label=label, value=value, choices=choices)
153
+ )
154
+
155
+ def pagination(self, size, page, total, sizes):
156
+ self["pagination"].update(size=size, page=page, total=total, sizes=sizes)
157
+
158
+ def add_row(self, row):
159
+ self["rows"].append(row)
160
+
161
+ def row(self, value=None, checkable=False, deleted=False):
162
+ self["rows"].append(
163
+ [dict(name="#", value=value, checkable=checkable, deleted=deleted)]
164
+ )
165
+
166
+ def cell(self, name, value, style=None, url=None, actions=None):
167
+ self["rows"][-1].append(
168
+ dict(name=name, value=value, style=style, url=url, actions=actions)
169
+ )
170
+
171
+
172
+ class TemplateContent(dict):
173
+ def __init__(self, name, context):
174
+ self["type"] = "html"
175
+ self["content"] = render_to_string(name, context)
176
+
177
+
178
+ class Banner(dict):
179
+ def __init__(self, src):
180
+ self["type"] = "banner"
181
+ self["src"] = src
182
+
183
+
184
+ class Map(dict):
185
+ def __init__(self, latitude, longitude, width="100%", height=400):
186
+ self["type"] = "map"
187
+ self["latitude"] = str(latitude)
188
+ self["longitude"] = str(longitude)
189
+ self["width"] = width
190
+ self["height"] = height
191
+
192
+
193
+ class Steps(dict):
194
+ def __init__(self, icon=None):
195
+ self["type"] = "steps"
196
+ self["icon"] = icon
197
+ self["steps"] = []
198
+
199
+ def append(self, name, done):
200
+ number = len(self["steps"]) + 1
201
+ self["steps"].append(dict(number=number, name=name, done=bool(done)))
202
+
203
+
204
+ class WebConf(dict):
205
+ def __init__(self, caller, receiver):
206
+ self["type"] = "webconf"
207
+ self["caller"] = caller
208
+ self["receiver"] = receiver
209
+
210
+ class ZoomMeet(dict):
211
+ def __init__(self, number, password, name):
212
+ self["type"] = "zoommeet"
213
+ self["number"] = number
214
+ self["password"] = password
215
+ self["name"] = name
216
+
217
+ class Navbar(dict):
218
+ def __init__(self, title, subtitle=None, logo=None, user=None, search=False, roles=None):
219
+ self["type"] = "navbar"
220
+ self["title"] = title
221
+ self["subtitle"] = subtitle
222
+ self["logo"] = logo
223
+ self["user"] = user
224
+ self["usermenu"] = []
225
+ self["adder"] = []
226
+ self["tools"] = []
227
+ self["settings"] = []
228
+ self["actions"] = []
229
+ self["toolbar"] = []
230
+ self["search"] = search
231
+ self["roles"] = roles
232
+
233
+ def add_action(self, entrypoint, name, url, modal=True, icon=None):
234
+ self[entrypoint].append(dict(name=name, url=url, modal=modal, icon=icon))
235
+
236
+
237
+ class Menu(dict):
238
+ def __init__(self, items, user=None, image=None):
239
+ self["type"] = "menu"
240
+ self["items"] = items
241
+ self["user"] = user
242
+ self["image"] = image
243
+
244
+
245
+ class Footer(dict):
246
+ def __init__(self, version):
247
+ self["type"] = "navbar"
248
+ self["version"] = version
249
+
250
+
251
+ class Application(dict):
252
+ def __init__(self, icon=None, navbar=None, menu=None, footer=None, oauth=(), sponsors=()):
253
+ self["type"] = "application"
254
+ self["icon"] = icon
255
+ self["navbar"] = navbar
256
+ self["menu"] = menu
257
+ self["footer"] = footer
258
+ self["oauth"] = oauth
259
+ self["sponsors"] = sponsors
260
+
261
+
262
+ class Response(dict):
263
+
264
+ def __init__(self, message=None, redirect=None, store=None, **kwargs):
265
+ self["type"] = "response"
266
+ self["message"] = message
267
+ self["redirect"] = redirect or '..'
268
+ self["store"] = store or {}
269
+ self.update(**kwargs)
270
+
271
+
272
+ class IconSet(dict):
273
+ def __init__(self):
274
+ self["type"] = "iconset"
275
+
276
+
277
+ class Grid(dict):
278
+ def __init__(self):
279
+ self["type"] = "grid"
280
+ self["items"] = []
281
+
282
+ def append(self, component):
283
+ self["items"].append(component)
284
+
285
+
286
+ class Scheduler(dict):
287
+ INTERVALS = {1: ["00"], 2: ["00", "30"]}
288
+
289
+ def __init__(
290
+ self,
291
+ start_time=7,
292
+ end_time=20,
293
+ chucks=2,
294
+ start_day=None,
295
+ days=14,
296
+ single_selection=False,
297
+ input_name="schedule",
298
+ readonly=False,
299
+ ):
300
+ self["type"] = "scheduler"
301
+ self["single_selection"] = single_selection
302
+ self["input_name"] = input_name
303
+ self["readonly"] = readonly
304
+ self.end_day = start_day or datetime.now()
305
+ self.end_day = datetime(self.end_day.year, self.end_day.month, self.end_day.day)
306
+ self.times = []
307
+ for hour in range(start_time, end_time + 1):
308
+ for minute in Scheduler.INTERVALS[chucks]:
309
+ self.times.append("{}:{}".format(str(hour).rjust(2, "0"), minute))
310
+ self.days = []
311
+ for n in range(0, days):
312
+ self.days.append(self.end_day.strftime("%d/%m/%Y"))
313
+ self.end_day = self.end_day + timedelta(days=1)
314
+ self.end_day = datetime(self.end_day.year, self.end_day.month, self.end_day.day, 23, 59, 59)
315
+ self["slots"] = {}
316
+ for day in self.days:
317
+ self["slots"][day] = {k: None for k in self.times}
318
+
319
+ self["matrix"] = []
320
+ row = [dict(text='', icon=None, color=None)]
321
+ for day in self.days:
322
+ row.append(dict(text=day, icon=None, color=None))
323
+ self["matrix"].append(row)
324
+ for time in self.times:
325
+ row = [dict(text=time, icon=None, color=None)]
326
+ for day in self.days:
327
+ row.append(self["slots"][day][time])
328
+ self["matrix"].append(row)
329
+
330
+ def append(self, date_time, text, icon='check'):
331
+ day = date_time.strftime("%d/%m/%Y")
332
+ time = date_time.strftime("%H:%M")
333
+ value = dict(text=text, icon=icon)
334
+ self["slots"][day][time] = value
335
+ j = self.days.index(day) + 1 if day in self.days else -1
336
+ x = self.times.index(time) + 1 if time in self.times else -1
337
+ self["matrix"][x][j] = value
338
+
339
+
@@ -0,0 +1,3 @@
1
+ from ..roles import role
2
+ from .. import meta
3
+
@@ -0,0 +1,140 @@
1
+ from uuid import uuid1
2
+ from django.db.models import Model as DjangoModel
3
+ from django.db.models import *
4
+ from django.utils.translation import gettext_lazy as _
5
+ from .. import ModelMixin
6
+
7
+ class CharField(CharField):
8
+ def __init__(self, *args, **kwargs):
9
+ self.mask = kwargs.pop('mask', None)
10
+ kwargs.setdefault('max_length', 255)
11
+ super().__init__(*args, **kwargs)
12
+
13
+ def formfield(self, *args, **kwargs):
14
+ field = super().formfield(*args, **kwargs)
15
+ field.mask = self.mask
16
+ return field
17
+
18
+ class IntegerField(IntegerField):
19
+ def __init__(self, *args, **kwargs):
20
+ self.mask = kwargs.pop('mask', None)
21
+ super().__init__(*args, **kwargs)
22
+
23
+ def formfield(self, *args, **kwargs):
24
+ field = super().formfield(*args, **kwargs)
25
+ field.mask = self.mask
26
+ return field
27
+
28
+ class ForeignKey(ForeignKey):
29
+ def __init__(self, to, on_delete=None, **kwargs):
30
+ self.pick = kwargs.pop('pick', False)
31
+ self.addable = kwargs.pop('addable', False)
32
+ super().__init__(to, on_delete or CASCADE, **kwargs)
33
+
34
+ def formfield(self, *args, **kwargs):
35
+ from .. import forms
36
+ kwargs.update(form_class=forms.ModelChoiceField, pick=self.pick)
37
+ field = super().formfield(*args, **kwargs)
38
+ return field
39
+
40
+ class OneToManyField(ManyToManyField):
41
+ def __init__(self, *args, **kwargs):
42
+ self.fields = kwargs.pop('fields', '__all__')
43
+ super().__init__(*args, **kwargs)
44
+
45
+ def formfield(self, *args, **kwargs):
46
+ from .. import forms
47
+ kwargs.update(form_class=forms.OneToManyField, fields=self.fields)
48
+ field = super().formfield(*args, model=self.related_model, **kwargs)
49
+ field.label = self.verbose_name
50
+ return field
51
+
52
+
53
+ class OneToOneField(OneToOneField):
54
+ def __init__(self, *args, **kwargs):
55
+ self.fields = kwargs.pop('fields', '__all__')
56
+ super().__init__(*args, **kwargs)
57
+
58
+ def formfield(self, *args, **kwargs):
59
+ from .. import forms
60
+ kwargs.update(form_class=forms.OneToOneField, fields=self.fields)
61
+ field = super().formfield(*args, model=self.related_model, **kwargs)
62
+ field.label = self.verbose_name
63
+ field.required2 = not self.blank
64
+ return field
65
+
66
+
67
+ class ManyToManyField(ManyToManyField):
68
+ def __init__(self, *args, **kwargs):
69
+ self.pick = kwargs.pop('pick', False)
70
+ self.addable = kwargs.pop('addable', False)
71
+ super().__init__(*args, **kwargs)
72
+
73
+ def formfield(self, *args, **kwargs):
74
+ from .. import forms
75
+ kwargs.update(form_class=forms.ModelMultipleChoiceField, pick=self.pick)
76
+ field = super().formfield(*args, **kwargs)
77
+ return field
78
+
79
+
80
+ class DecimalField(DecimalField):
81
+ def __init__(self, *args, **kwargs):
82
+ kwargs['decimal_places'] = kwargs.pop('decimal_places', 2)
83
+ kwargs['max_digits'] = kwargs.pop('max_digits', 9)
84
+ super().__init__(*args, **kwargs)
85
+
86
+ def formfield(self, *args, **kwargs):
87
+ from .. import forms
88
+ kwargs.update(form_class=forms.DecimalField)
89
+ return super().formfield(*args, **kwargs)
90
+
91
+ class ColorField(CharField):
92
+
93
+ def formfield(self, *args, **kwargs):
94
+ from .. import forms
95
+ kwargs.update(form_class=forms.ColorField)
96
+ return super().formfield(*args, **kwargs)
97
+
98
+ class TextField(TextField):
99
+ def __init__(self, *args, **kwargs):
100
+ self.formatted= kwargs.pop('formatted', False)
101
+ super().__init__(*args, **kwargs)
102
+
103
+ class FileField(FileField):
104
+ def __init__(self, *args, extensions=('pdf',), max_size=5, **kwargs):
105
+ self.extensions= extensions
106
+ self.max_size = max_size
107
+ super().__init__(*args, **kwargs)
108
+
109
+ def formfield(self, *args, **kwargs):
110
+ from .. import forms
111
+ kwargs.update(extensions=self.extensions, max_size=self.max_size)
112
+ kwargs.update(form_class=forms.FileField)
113
+ return super().formfield(*args, **kwargs)
114
+
115
+ def generate_filename(self, instance, filename):
116
+ filename = '{}.{}'.format(uuid1().hex, filename.split('.')[-1].lower())
117
+ print(filename)
118
+ return super().generate_filename(instance, filename)
119
+
120
+ class ImageField(ImageField):
121
+ def __init__(self, *args, extensions=('png', 'jpg', 'jpeg'), width=None, height=None, **kwargs):
122
+ self.extensions= extensions
123
+ self.width = width
124
+ self.height = height
125
+ super().__init__(*args, **kwargs)
126
+
127
+ def formfield(self, *args, **kwargs):
128
+ from .. import forms
129
+ kwargs.update(extensions=self.extensions, width=self.width, height=self.height)
130
+ kwargs.update(form_class=forms.ImageField)
131
+ return super().formfield(*args, **kwargs)
132
+
133
+ def generate_filename(self, instance, filename):
134
+ filename = '{}.{}'.format(uuid1().hex, filename.split('.')[-1].lower())
135
+ print(filename)
136
+ return super().generate_filename(instance, filename)
137
+
138
+ class Model(DjangoModel, ModelMixin):
139
+ class Meta:
140
+ abstract = True