Skip to content

Commit 0d0fd1c

Browse files
committed
Initial draft
1 parent 6b23339 commit 0d0fd1c

File tree

1 file changed

+90
-0
lines changed

1 file changed

+90
-0
lines changed

djangocms_picture/fields.py

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
from django.contrib.contenttypes.fields import GenericForeignKey
2+
from django.contrib.contenttypes.models import ContentType
3+
from django import forms
4+
from django.db import models
5+
6+
7+
class PictureWidget(forms.MultiWidget):
8+
def __init__(self):
9+
widgets = [
10+
forms.Select(attrs={},choices=[
11+
# TODO: provide a configuration settings instead of
12+
# accessing the db?
13+
# Also, check that the provided value exists
14+
(ct.id, ct.name) for ct in ContentType.objects.all()
15+
]),
16+
forms.NumberInput(attrs={}),
17+
]
18+
super().__init__(widgets)
19+
20+
21+
class PictureFormField(forms.Field):
22+
widget = PictureWidget
23+
24+
def __init__(self, *args, **kwargs):
25+
kwargs.pop('encoder', None) # passed from models.JSONField
26+
kwargs.pop('decoder', None)
27+
super().__init__(*args, **kwargs)
28+
29+
def prepare_value(self, value):
30+
data = []
31+
if value is None:
32+
return data
33+
34+
ct = ContentType.objects.get_for_model(value)
35+
data.extend([ct.id, value.pk])
36+
return data
37+
38+
def to_python(self, value):
39+
if not value:
40+
return value
41+
42+
# NOTE: what if we save this in a hidden widget
43+
ct_id, fk = value
44+
45+
ct = ContentType.objects.get_for_id(id=ct_id)
46+
obj = ct.get_object_for_this_type(id=fk)
47+
48+
# This should help us deceive GFK.get_content_type
49+
# to get the necessary ct and fk
50+
class HelperObj:
51+
_state = ct._state
52+
pk = int(fk)
53+
_meta = ct.model_class()._meta
54+
55+
def __repr__(this):
56+
return f"{this._meta.model_name}({fk})"
57+
58+
return obj
59+
60+
61+
class PictureField(GenericForeignKey, models.Field):
62+
def __init__(self, **kwargs):
63+
# call to models.JSONField
64+
super(GenericForeignKey, self).__init__(**kwargs)
65+
66+
# call to GenericForeignKey
67+
super().__init__(**kwargs)
68+
self.editable = True
69+
70+
def contribute_to_class(self, cls, name):
71+
ct = models.ForeignKey(ContentType,
72+
editable=False,
73+
on_delete=models.CASCADE)
74+
fk = models.PositiveIntegerField(editable=False)
75+
76+
self.ct_field = f"{name}_ct"
77+
self.fk_field = f"{name}_fk"
78+
79+
cls.add_to_class(self.ct_field, ct)
80+
cls.add_to_class(self.fk_field, fk)
81+
super().contribute_to_class(cls, name)
82+
83+
# this is required by _post_clean hook used during
84+
# model validation in forms
85+
self.attname = self.name
86+
87+
def formfield(self, **kwargs):
88+
kwargs.setdefault("form_class", PictureFormField)
89+
return super().formfield(**kwargs)
90+

0 commit comments

Comments
 (0)