-
Notifications
You must be signed in to change notification settings - Fork 25
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Creme API #380
base: main
Are you sure you want to change the base?
Creme API #380
Conversation
def get_cremeentity_contenttypes(): | ||
models = list(creme_registry.iter_entity_models()) | ||
return ContentType.objects.get_for_models(*models).values() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
creme.creme_core.utils.content_type.entity_ctypes
fields = SimpleCremeEntitySerializer.Meta.fields + [ | ||
"user", | ||
"description", | ||
] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fields = [
*SimpleCremeEntitySerializer.Meta.fields,
"user",
"description",
]
(avoids a temporary list)
class ContactSerializer(PersonWithAddressesMixin, CremeEntitySerializer): | ||
class Meta(CremeEntitySerializer.Meta): | ||
model = get_contact_model() | ||
fields = CremeEntitySerializer.Meta.fields + [ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[*CremeEntitySerializer.Meta.fields, ...] (in others places too of course....)
created = CreationDateTimeField(verbose_name=_("Creation date"), editable=False) | ||
modified = ModificationDateTimeField( | ||
verbose_name=_("Last modification"), editable=False | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed editable==False by default (yes I should simplify CremeEntity declaration too).
<style> | ||
.api-content-page { | ||
display: flex; | ||
margin-top: 15px; | ||
} | ||
.api-left-panel-container { | ||
flex-shrink: 1 | ||
} | ||
.api-left-panel-content { | ||
min-width: 250px; | ||
background: white; | ||
border-left: 1px solid #d9d9d9; | ||
border-right: 1px solid #d9d9d9; | ||
border-top: 1px solid #d9d9d9; | ||
border-bottom: 1px solid #dedede; | ||
|
||
display: inline-block; | ||
|
||
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); | ||
-moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); | ||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); | ||
|
||
} | ||
.api-left-panel-content ul { | ||
list-style: none; | ||
} | ||
.api-left-panel-content ul li { | ||
padding-left: 15px; | ||
} | ||
.api-left-panel-content ul li.title { | ||
padding-left: 0; | ||
font-weight: 600; | ||
padding-bottom: 10px; | ||
} | ||
.api-content-container { | ||
flex: 1; | ||
padding-left: 15px; | ||
} | ||
|
||
</style> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- I presume you plan to extract this to a separated CSS file
- Add a CSS class to the brick with {% block brick_extra_class %}{{block.super}} creme_api-brick{% endblock %} and it to prefix the CSS rules.
@property | ||
def can_view(self): | ||
return bool(self.value & EntityCredentials.VIEW) | ||
|
||
@property | ||
def can_change(self): | ||
return bool(self.value & EntityCredentials.CHANGE) | ||
|
||
@property | ||
def can_delete(self): | ||
return bool(self.value & EntityCredentials.DELETE) | ||
|
||
@property | ||
def can_link(self): | ||
return bool(self.value & EntityCredentials.LINK) | ||
|
||
@property | ||
def can_unlink(self): | ||
return bool(self.value & EntityCredentials.UNLINK) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unit tests
def refresh_from_db(self, *args, **kwargs): | ||
self._teams = None | ||
self._teammates = None | ||
self._settings = None | ||
super().refresh_from_db(*args, **kwargs) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unit test (I presume it's better to test that queries are done with assertNumQueries() than testing protected attributes).
def refresh_from_db(self, *args, **kwargs): | ||
self._allowed_apps = None | ||
self._extended_allowed_apps = None | ||
|
||
self._admin_4_apps = None | ||
self._extended_admin_4_apps = None | ||
|
||
self._creatable_ctypes_set = None | ||
self._exportable_ctypes_set = None | ||
|
||
self._setcredentials = None | ||
|
||
super().refresh_from_db(*args, **kwargs) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unit test (I presume it's better to test that queries are done with assertNumQueries() than testing protected attributes).
class ContentTypeViewSet(viewsets.ReadOnlyModelViewSet): | ||
""" | ||
retrieve: | ||
Retrieve a content type. | ||
|
||
list: | ||
List content types. | ||
""" | ||
|
||
queryset = None | ||
serializer_class = ContentTypeSerializer | ||
schema = AutoSchema(tags=["Content Types"]) | ||
|
||
def get_queryset(self): | ||
return get_cremeentity_contenttype_queryset() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Is it possible to return a list not based on a Queryset ? (if yes, remove 'get_cremeentity_contenttype_queryset()' )
- Rename EntityContentTypesViewSet VS return all ContentTypes (or entity types + types registered on crme_config + some types in an attributes with Relation/EntityFilters/...). I don't know where this view is used so I ignore what's the smartest.
class DeleteUserSerializer(serializers.ModelSerializer): | ||
""" | ||
Serializer which assigns the fields with type CremeUserForeignKey | ||
referencing a given user A to another user B, then deletes A. | ||
""" | ||
|
||
transfer_to = serializers.PrimaryKeyRelatedField( | ||
queryset=CremeUser.objects.none(), required=True | ||
) | ||
|
||
class Meta: | ||
model = CremeUser | ||
fields = ["transfer_to"] | ||
|
||
def __init__(self, instance=None, **kwargs): | ||
super().__init__(instance=instance, **kwargs) | ||
users = CremeUser.objects.exclude(is_staff=True) | ||
if instance is not None: | ||
users = users.exclude(pk=instance.pk) | ||
self.fields["transfer_to"].queryset = users | ||
|
||
def save(self, **kwargs): | ||
CremeUserForeignKey._TRANSFER_TO_USER = self.validated_data["transfer_to"] | ||
|
||
try: | ||
self.instance.delete() | ||
finally: | ||
CremeUserForeignKey._TRANSFER_TO_USER = None |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Beware the view 'creme.creme_config.views.user.UserDeletion' uses a lock to avoid race conditions (eg: a user transfers A to B, & other one transfers B to A).
- use the same lock (the name is in a class attribute)
- I presume we should perform the deletion in a deletion job (I mean in the creme_config too) ; but I do not know how the REST API would manage that (return immediately "the job has been created" VS wait the job is complete).
This is a work in progress