Code Monkey home page Code Monkey logo

django-groups-manager's People

Contributors

areski avatar dalito avatar gornoka avatar io-ma avatar oskarpersson avatar vittoriozamboni avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

django-groups-manager's Issues

ImportError: No module named django_helper_forms.forms

Installing the groups manager 0.5.0 wth pip install does not also pull the django_helper_forms dependency resulting in following crash while adding in urls. No explicit mention in the docs to install as such as well.

url(r'^groups-manager/', include('groups_manager.urls', namespace='groups_manager')),

File "/Users/rs/projects/lipton/lib/python2.7/site-packages/groups_manager/urls.py", line 3, in
from groups_manager import views
File "/Users/rs/projects/lipton/lib/python2.7/site-packages/groups_manager/views.py", line 9, in
from groups_manager import models, forms, settings
File "/Users/rs/projects/lipton/lib/python2.7/site-packages/groups_manager/forms.py", line 3, in
from django_helper_forms.forms import DictionaryFieldsForm
ImportError: No module named django_helper_forms.forms

Group membership in descendants

Hello, I'm trying to build a test that checks permissions and memberships as I'm still trying to understand how I will use this permissions. I have custom Member and Group (app core):

class Usuario(Member):
    ...

    class Meta:
        verbose_name = "Usuario"
        verbose_name_plural = "Usuarios"
class Organizacion(Group):

      ....

      class Meta:
          verbose_name = "Organizacion"
          verbose_name_plural = "Organizaciones"

     class GroupsModelMeta:
            model_name = 'core.Usuario'

And the (simplified) test is:

# Prep
org = Organizacion.objects.create(name="org")
org_child = Organizacion.objects.create(name="org_child", parent=org)
org_grand_child = Organizacion.objects.create(name="org_grand_child", parent=org_child)

user1 = Usuarios.objects.create(username="user1")
org.add_member(user1)
user2 = Usuarios.objects.create(username="user2")
org_child.add_member(user2)
user3 = Usuarios.objects.create(username="user3")
org_grand_child.add_member(user3)


# Test Membership
self.assertTrue(user_1 in org.members) 

self.assertTrue(user_2 in org_child.members)
self.assertTrue(user_2 in org.members)

self.assertTrue(user_3 in org_grand_child.members)
self.assertTrue(user_3 in org_child.members)
self.assertTrue(user_3 in org.members)

All asserts fails here as members are instances of Member and not Usuario. If I use this instead:

class Organizacion(Group):

      ....

      class Meta:
          verbose_name = "Organizacion"
          verbose_name_plural = "Organizaciones"

       class GroupsManagerMeta:
            member_model = "core.Usuario"

users are of instance Usuario in the main Organizacion but not in it's children.

Any ideas?
Thank you!

standard templates, from groups_manager’s urls

can u preview or tell step by step when to use standard templates, from groups_manager’s urls?
i already run it, but i still confuse to use it...

I already change it to be working for django 1.9.
.... working (change to bootstrap 3.3.7)

Question about permissions

Hi, I'm still integrating this lib and have some questions.

I'm trying to model a hierarchical organization. I have Organization extending from Group and User extending from Member. I want to create Users that have permissions over the sub organization of which they are members.

After creating the user I'm using add_member to add the User to the Org and assign_object to assign the Org object to the Org group.

Running some tests I see that permissions are correct over the Organization objects, but the Users have no permissions over the models. This is causing for example that a user has no permissions for Django admin.

Do I have to add these permissions manually, or I'm using this the wrong way?

Thank you for your patience!

Remove/Modify permissions with Groups Manager

Hello, I believe I have issues understanding how the permissions manager is suposed to work.

I can see how the downstream and upstream priviledges are granted. But I cannot figure out how to revoke them properly.

Here a test I tried:

# Create company structure
companyA = Group.objects.create(name="CompanyA")
division1 = Group.objects.create(name="Division1", parent=companyA)
division2 = Group.objects.create(name="Division2", parent=companyA)

# Create user and and assign to division
member_div_1 = Member.objects.create(username="memberDiv1", first_name="MemberDiv1")
division1.add_member(member_div_1)

# Creating Mock Document
document = MyDocumentModel.objects.create(title="TestDocument")

# Assign permissions

custom_permissions = {
        'groups_downstream': ['view', 'change'],
 }


companyA.assign_object(document, custom_permissions=custom_permissions)

member_div_1.has_perm("view_document", document)
# This returns True

member_div_1.has_perm("change_document", document)
# This returns True

Until here everything works as expected but if I want to modify the permissions on the document for companyA and remove the change option:

# Modify permissions

custom_permissions = {
       'group' : [],
        'groups_downstream': ['view',],
 }


companyA.assign_object(document, custom_permissions=custom_permissions)

member_div_1.has_perm("view_document", document)
# This returns True

member_div_1.has_perm("change_document", document)
# This returns True -> In this test this was expected to return False

I think I don't fully understand how to revoke privileges using this manager.

I haven't found any documentation on revoking/modifying permissions and I haven't seen other users requesting this feature, which means I am probably doing/understading something wrong.

Could you point me in the direction to achieve this?

Thank you in advance!
Fran

ModuleNotFoundError: No module named 'jsonfield'

The moment I add groups_manger to INSTALLED_APPS, I get this exception. I think we can simply use JSONField which is now natively supported in Django which is now supported by both postgres as well as MySQL.

General groups like Referent, Leader to moderate the group

Hi @OskarPersson , @vittoriozamboni ,

is possible create a general groups for moderate/handle the group like Tohir is "leader", like this example:

from groups_manager.models import Group, Member
fc_internazionale = Group.objects.create(name='F.C. Internazionale Milan')
staff = Group.objects.create(name='Staff', parent=fc_internazionale)
players = Group.objects.create(name='Players', parent=fc_internazionale)
thohir = Member.objects.create(first_name='Eric', last_name='Thohir')
staff.add_member(thohir)
palacio = Member.objects.create(first_name='Rodrigo', last_name='Palacio')
players.add_member(palacio)

I need a general group staff for each "football club" who can handle only for specific "football club"

Thanks for support!
Sorry for my bad english

Runtime Error when installing with Docker Compose

I am trying to use this app with a Django deployment under Docker compose (DB + web app).
After installing the app I get this error message

RuntimeError: Model class guardian.models.UserObjectPermission doesn't declare an explicit app_label and isn't in an application in INSTALLED_APPS.

The app is installed and listed in INSTALLED_APPS, what am I missing?

thank you!
Claudio

TemplateDoesNotExist at /api/v1/groups-manager/

Hey guys, I tried to use the groups-manager url and got the following exception.


Template loader postmortem
Django tried loading these templates, in this order:

Using engine django:
    * django.template.loaders.filesystem.Loader: /code/vitapio/static/base.html (Source does not exist)
    * django.template.loaders.app_directories.Loader: /usr/local/lib/python3.6/site-packages/django/contrib/admin/templates/base.html (Source does not exist)
    * django.template.loaders.app_directories.Loader: /usr/local/lib/python3.6/site-packages/django/contrib/auth/templates/base.html (Source does not exist)
    * django.template.loaders.app_directories.Loader: /usr/local/lib/python3.6/site-packages/rest_framework/templates/base.html (Source does not exist)
    * django.template.loaders.app_directories.Loader: /usr/local/lib/python3.6/site-packages/django_filters/templates/base.html (Source does not exist)
    * django.template.loaders.app_directories.Loader: /usr/local/lib/python3.6/site-packages/drf_yasg/templates/base.html (Source does not exist)
    * django.template.loaders.app_directories.Loader: /usr/local/lib/python3.6/site-packages/guardian/templates/base.html (Source does not exist)
    * django.template.loaders.app_directories.Loader: /usr/local/lib/python3.6/site-packages/groups_manager/templates/base.html (Source does not exist)
    * django.template.loaders.app_directories.Loader: /usr/local/lib/python3.6/site-packages/bootstrap3/templates/base.html (Source does not exist)


Template error:
In template /usr/local/lib/python3.6/site-packages/groups_manager/templates/groups_manager/bootstrap3/groups_manager.html, error at line 1
   base.html
   1 :  {% extends "base.html" %} 
   2 : 
   3 : 
   4 : {% block breadcrumbs %}
   5 :   {{ block.super }}
   6 :   <li>
   7 :     <a href="{% url 'groups_manager:groups_manager' %}">Groups Manager</a>
   8 :   </li>
   9 : {% endblock breadcrumbs %}
   10 : 
   11 : 


Traceback:

File "/usr/local/lib/python3.6/site-packages/django/template/backends/django.py" in render
  61.             return self.template.render(context)

File "/usr/local/lib/python3.6/site-packages/django/template/base.py" in render
  171.                     return self._render(context)

File "/usr/local/lib/python3.6/site-packages/django/template/base.py" in _render
  163.         return self.nodelist.render(context)

File "/usr/local/lib/python3.6/site-packages/django/template/base.py" in render
  937.                 bit = node.render_annotated(context)

File "/usr/local/lib/python3.6/site-packages/django/template/base.py" in render_annotated
  904.             return self.render(context)

File "/usr/local/lib/python3.6/site-packages/django/template/loader_tags.py" in render
  150.             return compiled_parent._render(context)

File "/usr/local/lib/python3.6/site-packages/django/template/base.py" in _render
  163.         return self.nodelist.render(context)

File "/usr/local/lib/python3.6/site-packages/django/template/base.py" in render
  937.                 bit = node.render_annotated(context)

File "/usr/local/lib/python3.6/site-packages/django/template/base.py" in render_annotated
  904.             return self.render(context)

File "/usr/local/lib/python3.6/site-packages/django/template/loader_tags.py" in render
  127.         compiled_parent = self.get_parent(context)

File "/usr/local/lib/python3.6/site-packages/django/template/loader_tags.py" in get_parent
  124.         return self.find_template(parent, context)

File "/usr/local/lib/python3.6/site-packages/django/template/loader_tags.py" in find_template
  104.             template_name, skip=history,

File "/usr/local/lib/python3.6/site-packages/django/template/engine.py" in find_template
  130.         raise TemplateDoesNotExist(name, tried=tried)

The above exception (base.html) was the direct cause of the following exception:

File "/usr/local/lib/python3.6/site-packages/django/core/handlers/exception.py" in inner
  34.             response = get_response(request)

File "/usr/local/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response
  156.                 response = self.process_exception_by_middleware(e, request)

File "/usr/local/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response
  154.                 response = response.render()

File "/usr/local/lib/python3.6/site-packages/django/template/response.py" in render
  106.             self.content = self.rendered_content

File "/usr/local/lib/python3.6/site-packages/django/template/response.py" in rendered_content
  83.         content = template.render(context, self._request)

File "/usr/local/lib/python3.6/site-packages/django/template/backends/django.py" in render
  63.             reraise(exc, self.backend)

File "/usr/local/lib/python3.6/site-packages/django/template/backends/django.py" in reraise
  84.     raise new from exc

Exception Type: TemplateDoesNotExist at /api/v1/groups-manager/
Exception Value: base.html

Django custom user model and Member

Note: I am using a custom user model in Django and not a default user model (replaced username with email)

def create_member(sender, instance,created, **kwargs):
    if created:
        if not instance.is_staff:
            try:
                Member.objects.create(first_name=instance.first_name, last_name=instance.last_name, django_user_id=instance.id)
            except:
                pass

post_save.connect(create_member,sender=User)

This creates an instance of Member when an instance of CustomUser is created, but Under customuser the users email disappears.
If I remove "django_user_id=instance.id" everything is normal but, django_user is unassigned as expected.

How can I create an instance of member class ?

Is class User(AbstractUser, MemberMixin) possible?

My application has a customized User class derived from AbstractUser. Instead of defining separate Member class and sync or one to one to User, I am wondering if it is more straightforward to do

class User(AbstractUser, MemberMixin)

so that every user would automatically be a Member.

I understand MemberMixin has some conflicting fields with AbstractUser, so I was basically asking if it is ok to copy the code for MemberMixin into class User, and do something like


class User(AbstractUser, MemberRelationsMixin):
    class GroupsManagerMeta:
        group_model = 'organization.OrganizationGroups'
        group_member_model = 'users.User'

ImageFields

Hi,
I added the ImageField for class GroupMixin(GroupRelationsMixin, MPTTModel):
But doesn't work the makemigrations and migrate commands.

This is my fields:

no_picture = django_settings.MEDIA_URL +'/group_pictures/avatar-team.jpg'
    no_cover = django_settings.MEDIA_URL +'/group_covers/covers.jpg'
    url_back = 'group_covers/'
    url_photo = 'group_pictures/'
    background_photo = models.ImageField(upload_to =url_back, default=no_cover, null=True, blank=True)
    profile_photo = models.ImageField(upload_to=url_photo, default=no_picture, null=True, blank=True)

screen shot 2017-11-27 at 18 33 47

Need some explanations...

Hi.

I'm studying the module. I have some questions to understand it well.

In groups:

  • There are a field 'entities', what is the meaning of that? I know I can choose 1 or more, but what is the functionaility?
  • On the field 'properties', must go a json, but whit what content? Do you have an example that can clarify why exists?

On the members.

When sync with the django users, when create a member create an user. But not create a password. Son i have to go to the user form and create the other information. Or only sync with existing users?

That's all for the moment

Broken with Django 4.0

Currently this does not work with Django 4.0 as far as I could see the only problem is the usage of the deprecated alias

django.conf.urls.url

I would propose a quick fix later, however it should be discussed whether the old behaviour of using the alias is still kept for backwards compatibility or not.

Migrations warning

I have this warning at makemigrations:

System check identified some issues:

WARNINGS:
groups_manager.Group.group_entities: (fields.W340) null has no effect on ManyToManyField.
groups_manager.GroupMember.roles: (fields.W340) null has no effect on ManyToManyField.
No changes detected

Python 3.5.2
Django 1.9.7
django-groups-manager 0.4.1

How do I add a password to the member I added?

We can create fields such as username, e-mail. However, the password field is not available. When I add a member to the member add page, I want to set the password on the page. How can I do it?

forms.py

class CalisanForm(forms.ModelForm):
    member = forms.CharField(max_length=100, label='Çalışan Adı')

    class Meta:
        model = User
        fields = [
            'member',
        ]

views.py

def calisan(request):
    form = CalisanForm(request.POST or None)
    if form.is_valid():
        member = form.cleaned_data['member']
        member = Member.objects.create(first_name=member)
        return redirect('home')
    return render(request, 'accounts/calisan/calisan.html', {'form': form})

Extend the downstream permissions with roles

I bugfixed the assign_object()

team   = Group.objects.create(name=society.name, group_type=g_type, parent=society) 
member = Member.objects.get(django_user=user)
team.add_member(member, roles = [GroupMemberRole.OWNER])

But when I try to modify the groups_downstream I have error:

this is example:
'PERMISSIONS': {
        'owner': ['view', 'change', 'delete'],
        'group': ['view', 'change'],
        'groups_upstream': ['view'],
        'groups_downstream': [],
        'groups_siblings': ['view'],
    },
    
this is my:
PERMISSIONS = {
    #'owner': ['view', 'change', 'delete',],
    'owner': {
        'leader': ['change', 'delete', 'can_add_member_custom', 'can_remove_member_custom'], 
        'referent': ['change', 'delete', 'can_add_member_custom', 'can_remove_member_custom'],
        'default': ['view', 'change', 'delete'],
    },
    'group': ['view', 'change',],
    'groups_upstream': ['view'],
    'groups_downstream': {
        'leader': ['change', 'delete', 'can_add_member_custom', 'can_remove_member_custom'], 
        'referent': ['change', 'delete', 'can_add_member_custom', 'can_remove_member_custom' ], 
        #'default': ['view']
    },
    'groups_siblings': ['view'],
}

Is possibile have the role permission for downstream permss?

Thanks

this is error:
Permission matching query does not exist.

Use the PERMISSION in settings.py of groups_manager to standard

Hi @OskarPersson ,

I would need that when a user is associated with the staff or referent role can have the privileges of being able to modify the group, add users or remove them both for the belonging group and the children of the group.

It's possible?

from django.conf import settings

GROUPS_MANAGER_SETTINGS = getattr(settings, 'GROUPS_MANAGER', {})

SETTINGS_PERMISSIONS = GROUPS_MANAGER_SETTINGS.get('PERMISSIONS', {})

PERMISSIONS = {
    #'owner': ['view', 'change', 'delete',],
    'owner': {
        'leader': ['change', 'delete'], 
        'referent': ['change', 'delete'],
        'default': ['view', 'change', 'delete',],
    },
    'group': ['view', 'change',],
    #'groups_upstream': ['view'],
    #'groups_downstream': ,
    'groups_upstream': {
        'leader': ['change', 'delete'], 
        'referent': ['change', 'delete'], 
        'default': ['view']
    },
    'groups_downstream': {
        'leader': ['change', 'delete'], 
        'referent': ['change', 'delete'], 
        'default': ['view']
    },
    'groups_siblings': ['view'],
}
PERMISSIONS.update(SETTINGS_PERMISSIONS)

GROUPS_MANAGER = {
    # User and Groups sync settings
    'AUTH_MODELS_SYNC': GROUPS_MANAGER_SETTINGS.get('AUTH_MODELS_SYNC', False),
    'AUTH_MODELS_GET_OR_CREATE': GROUPS_MANAGER_SETTINGS.get('AUTH_MODELS_GET_OR_CREATE', True),
    'GROUP_NAME_PREFIX': GROUPS_MANAGER_SETTINGS.get('GROUP_NAME_PREFIX', 'DGM_'),
    'GROUP_NAME_SUFFIX': GROUPS_MANAGER_SETTINGS.get('GROUP_NAME_SUFFIX', '_$$random'),
    'USER_USERNAME_PREFIX': GROUPS_MANAGER_SETTINGS.get('USER_USERNAME_PREFIX', 'DGM_'),
    'USER_USERNAME_SUFFIX': GROUPS_MANAGER_SETTINGS.get('USER_USERNAME_SUFFIX', '_$$random'),
    # Permissions
    'PERMISSIONS': PERMISSIONS,
    # Templates
    'TEMPLATE_STYLE': GROUPS_MANAGER_SETTINGS.get('TEMPLATE_STYLE', 'bootstrap3')
}

My problem is how does the GROUPS_MANAGER ['PERMISSIONS'] work?

Issue "on delete" - first installation

:\Users\Emauele Di Molfetta\Desktop\ALLAN\django>python manage.py migrate
Traceback (most recent call last):
File "manage.py", line 22, in
execute_from_command_line(sys.argv)
File "C:\Users\Emauele Di Molfetta\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\core\management_init_.py", line 371, in execute_from_command_line
utility.execute()
File "C:\Users\Emauele Di Molfetta\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\core\management_init_.py", line 347, in execute
django.setup()
File "C:\Users\Emauele Di Molfetta\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django_init_.py", line 24, in setup
apps.populate(settings.INSTALLED_APPS)
File "C:\Users\Emauele Di Molfetta\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\apps\registry.py", line 112, in populate
app_config.import_models()
File "C:\Users\Emauele Di Molfetta\AppData\Local\Programs\Python\Python36-32\lib\site-packages\django\apps\config.py", line 198, in import_models
self.models_module = import_module(models_module_name)
File "C:\Users\Emauele Di Molfetta\AppData\Local\Programs\Python\Python36-32\lib\importlib_init_.py", line 126, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File "", line 994, in _gcd_import
File "", line 971, in _find_and_load
File "", line 955, in _find_and_load_unlocked
File "", line 665, in load_unlocked
File "", line 678, in exec_module
File "", line 219, in call_with_frames_removed
File "C:\Users\Emauele Di Molfetta\AppData\Local\Programs\Python\Python36-32\lib\site-packages\groups_manager\models.py", line 295, in
class GroupMixin(GroupRelationsMixin, MPTTModel):
File "C:\Users\Emauele Di Molfetta\AppData\Local\Programs\Python\Python36-32\lib\site-packages\groups_manager\models.py", line 326, in GroupMixin
related_name='sub
%(app_label)s
%(class)s_set')
TypeError: init() missing 1 required positional argument: 'on_delete'

TypeError: __init__() got an unexpected keyword argument 'load_kwargs'

I noticed in #41, that you addressed an issue with line 33 in migration 0006 regarding the JSON field. I have an existing project that uses groups_manager version 1.0.2 that is working fine. However, I was doing a clean install from source to test deployment and during makemigrations, I am getting the following error:
File "<frozen importlib._bootstrap>", line 1014, in _gcd_import File "<frozen importlib._bootstrap>", line 991, in _find_and_load File "<frozen importlib._bootstrap>", line 975, in _find_and_load_unlocked File "<frozen importlib._bootstrap>", line 671, in _load_unlocked File "<frozen importlib._bootstrap_external>", line 783, in exec_module File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed File "/home/smontalbano/work/tmpMartie/martie_stripped/venv/lib/python3.8/site-packages/groups_manager/migrations/0006_1_0_0_default.py", line 8, in <module> class Migration(migrations.Migration): File "/home/smontalbano/work/tmpMartie/martie_stripped/venv/lib/python3.8/site-packages/groups_manager/migrations/0006_1_0_0_default.py", line 33, in Migration field=jsonfield.fields.JSONField(blank=True, default={}, load_kwargs={'object_pairs_hook': collections.OrderedDict}, verbose_name='properties'), File "/home/smontalbano/work/tmpMartie/martie_stripped/venv/lib/python3.8/site-packages/jsonfield/fields.py", line 39, in __init__ super(JSONField, self).__init__(*args, **kwargs) TypeError: __init__() got an unexpected keyword argument 'load_kwargs'
I'm unsure why this error exists only when doing a clean install and not on an existing instance of the project. I even tried moving my db file into source control and skipping the migration process and going right into runserver but this error is still raised.

Permission for specific object in AdminPanel

I have this admin.py and models.py

from django.contrib import admin

from bootcamp.groups_manager.models import Group, Member, GroupType, GroupEntity, GroupMember, GroupMemberRole
from guardian.admin import GuardedModelAdmin
class GroupAdmin(GuardedModelAdmin):
    pass

#admin.site.register(models.Group)
admin.site.register(Group, GroupAdmin)
admin.site.register(Member)
admin.site.register(GroupType)
admin.site.register(GroupEntity)
admin.site.register(GroupMember)
admin.site.register(GroupMemberRole)


class GroupMixin(GroupRelationsMixin, MPTTModel):
    name = models.CharField(max_length=255)
    codename = models.SlugField(blank=True, max_length=255)
    description = models.TextField(default='', blank=True)
    comment = models.TextField(default='', blank=True)
    parent = TreeForeignKey('self', null=True, blank=True,
                            related_name='sub_%(app_label)s_%(class)s_set')
    full_name = models.CharField(max_length=255, default='', blank=True)
    properties = JSONField(default={}, blank=True,
                            load_kwargs={'object_pairs_hook': OrderedDict})

    django_auth_sync = models.BooleanField(default=True, blank=True)
    
    #Custom permission
    background_photo = models.CharField(max_length=255, null=True, blank=True)
    profile_photo = models.CharField(max_length=255, null=True, blank=True)
    #type = models.TextField(default='', blank=True)

    class Meta:
        abstract = True
        ordering = ('name', )

    class MPTTMeta:
        level_attr = 'level'
        order_insertion_by = ['name', ]

    class GroupsManagerMeta(GroupRelationsMixin.GroupsManagerMeta):
        pass

    def __unicode__(self):
        return '%s' % self.name

    def __str__(self):
        return '%s' % self.name

    def save(self, *args, **kwargs):
        self.full_name = self._get_full_name()[:255]
        if not self.codename:
            self.codename = slugify(self.name, to_lower=True)
        super(GroupMixin, self).save(*args, **kwargs)

    def _get_full_name(self):
        if self.parent:
            return '%s - %s' % (self.parent._get_full_name(), self.name)
        return self.name

    @property
    def subgroups(self):
        message = 'The "subgroups" attribute will be removed in next version. ' + \
                  'Use "sub_groups_manager_group_set" instead.'
        warnings.warn(message, DeprecationWarning)
        return self.sub_groups_manager_group_set

    def get_members(self, subgroups=False):
        """Return group members.
        The result is a list of GroupsManagerMeta's attribute ``member_model`` instances.

        :Parameters:
          - `subgroups`: return also descendants members (default: `False`)
        """
        member_model = self.member_model
        group_member_model = self.group_member_model
        if group_member_model == GroupMember:
            members_relation = getattr(self, self.group_members_attribute)
            if member_model == Member:
                members = list(members_relation.all())
            else:
                # proxy model
                if member_model._meta.proxy:
                    members = list(member_model.objects.filter(
                        id__in=members_relation.values_list('id', flat=True)))
                # subclassed
                else:
                    members = list(member_model.objects.filter(
                        member_ptr__in=members_relation.all()))
        else:
            members = [gm.member for gm in group_member_model.objects.filter(group=self)]
        if subgroups:
            for subgroup in self.subgroups.all():
                members += subgroup.members
        members = list(set(members))
        return members

    @property
    def members(self):
        """Return group members. """
        return self.get_members(True)

    @property
    def users(self):
        """Return group django users. """
        users = []
        for member in self.members:
            if member.django_user:
                users.append(member.django_user)
        return users

    def get_entities(self, subgroups=False):
        """Return group entities.

        :Parameters:
          - `subgroups`: return also descendants entities (default: `False`)
        """
        entities = list(self.group_entities.all())
        if subgroups:
            for subgroup in self.subgroups.all():
                entities += subgroup.entities
            entities = list(set(entities))
        return entities

    @property
    def entities(self):
        """Return group entities."""
        return self.get_entities(True)

    def add_member(self, member, roles=None):
        """Add a member to the group.
        :Parameters:
          - `member`: member (required)
          - `roles`: list of roles. Each role could be a role id, a role label or codename,
            a role instance (optional, default: ``[]``)
        """
        print("add_member() method")
        if roles is None:
            roles = []
        if not self.id:
            raise exceptions_gm.GroupNotSavedError(
                "You must save the group before to create a relation with members")
        if not member.id:
            raise exceptions_gm.MemberNotSavedError(
                "You must save the member before to create a relation with groups")
        group_member_model = self.group_member_model
        group_member = group_member_model(member=member, group=self)
        group_member.save()
        if roles:
            for role in roles:
                if isinstance(role, GroupMemberRole):
                    group_member.roles.add(role)
                elif isinstance(role, int):
                    role_obj = GroupMemberRole.objects.get(id=role)
                    group_member.roles.add(role_obj)
                else:
                    try:
                        role_obj = GroupMemberRole.objects.get(models.Q(label=role) |
                                                               models.Q(codename=role))
                        group_member.roles.add(role_obj)
                    except Exception as e:
                        raise exceptions_gm.GetRoleError(e)
        return group_member

    def remove_member(self, member):
        """Remove a member from the group.

        :Parameters:
          - `member`: member (required)
        """
        group_member_model = self.group_member_model
        try:
            group_member = group_member_model.objects.get(member=member, group=self)
        except Exception as e:
            raise exceptions_gm.GetGroupMemberError(e)
        group_member.delete()

    def assign_object(self, obj, **kwargs):
        """Assign an object to the group.

        :Parameters:
          - `obj`: the object to assign (required)

        :Kwargs:
          - `custom_permissions`: a full or partial redefinition of PERMISSIONS setting.

        .. note::
         This method needs django-guardian.
        """
        return assign_object_to_group(self, obj, **kwargs)

    #Custom Method
    def get_picture(self):
        no_picture = django_settings.MEDIA_URL +'/group_pictures/avatar-team.jpg'
        try:
            filename = django_settings.MEDIA_ROOT + '/group_pictures/' +\
                self.user.username + '.jpg'
            picture_url = django_settings.MEDIA_URL + 'group_pictures/' +\
                self.user.username + '.jpg'
            if os.path.isfile(filename):  # pragma: no cover
                return picture_url
            else:  # pragma: no cover
                gravatar_url = 'http://www.gravatar.com/avatar/{0}?{1}'.format(
                    hashlib.md5(self.user.email.lower()).hexdigest(),
                    urllib.urlencode({'d': no_picture, 's': '256'})
                    )
                return gravatar_url

        except Exception:
            return no_picture
    
    #Retrieve users' cover
    def get_cover(self):
        no_cover = django_settings.MEDIA_URL +'group_covers/cover.jpg'
        try:
            filename = django_settings.MEDIA_ROOT + '/group_covers/' +\
                self.user.username + '.jpg'
            cover_url = django_settings.MEDIA_URL + 'group_covers/' +\
                self.user.username + '.jpg'
            if os.path.isfile(filename) and os.path.exists(filename):  # pragma: no cover
                if cover_url != None:
                    return cover_url
                else:
                    return no_cover
            else:
                no_cover
        except Exception:
            return no_cover

class Group(GroupMixin):

    group_type = models.ForeignKey(GroupType, null=True, blank=True, on_delete=models.SET_NULL,
                                   related_name='%(app_label)s_%(class)s_set')
    group_entities = models.ManyToManyField(GroupEntity, blank=True,
                                            related_name='%(app_label)s_%(class)s_set')

    django_group = models.ForeignKey(DjangoGroup, null=True, blank=True, on_delete=models.SET_NULL)
    group_members = models.ManyToManyField(Member, through='GroupMember',
                                           related_name='%(app_label)s_%(class)s_set')

    # this is just required for easy explanation
    class Meta(GroupMixin.Meta):
        abstract = False
        permissions = (
            ('can_add_member_custom', 'Can Add Member Custom'),
            ('can_remove_member_custom', 'Can Remove Member Custom'),
            ('can_edit_group_custom', 'Can Edit Group Custom'),
        )

It works, but there isn't the autosearch for users, how can I implement it?

screen shot 2017-11-28 at 09 40 20

I created programmatically when the user is registered.
screen shot 2017-11-28 at 09 57 16

Reason of adding prefix and suffix of original django auth.models

Hi.
I am trying to introduce django groups manager to my django site but I found there are some behavior when syncing with main django auth models. It will add some suffix and prefix to original model. I am planing to re-design this behavior. Could you tell why you need to add prefix and suffix ?

Chang

Is possible extend the permission of groups for all member?

Like the example,

Thoir is in staff group and can handle the budget or does other for Inter group.

I extend the permission in settings.py with:

from django.conf import settings


GROUPS_MANAGER_SETTINGS = getattr(settings, 'GROUPS_MANAGER', {})

SETTINGS_PERMISSIONS = GROUPS_MANAGER_SETTINGS.get('PERMISSIONS', {})
#print(SETTINGS_PERMISSIONS)
PERMISSIONS = {
    #'owner': ['view', 'change', 'delete',],
    'owner': {
        'leader': ['change', 'delete'], 
        'referent': ['change', 'delete'],
        'default': ['view', 'change', 'delete',],
    },
    'group': ['view', 'change',],
    #'groups_upstream': ['view'],
    #'groups_downstream': ,
    'groups_upstream': {
        'leader': ['change', 'delete'], 
        'referent': ['change', 'delete'], 
        'default': ['view']
    },
    'groups_downstream': {
        'leader': ['change', 'delete'], 
        'referent': ['change', 'delete'], 
        'default': ['view']
    },
    'groups_siblings': ['view'],
}
PERMISSIONS.update(SETTINGS_PERMISSIONS)

GROUPS_MANAGER = {
    # User and Groups sync settings
    'AUTH_MODELS_SYNC': GROUPS_MANAGER_SETTINGS.get('AUTH_MODELS_SYNC', False),
    'AUTH_MODELS_GET_OR_CREATE': GROUPS_MANAGER_SETTINGS.get('AUTH_MODELS_GET_OR_CREATE', True),
    'GROUP_NAME_PREFIX': GROUPS_MANAGER_SETTINGS.get('GROUP_NAME_PREFIX', 'DGM_'),
    'GROUP_NAME_SUFFIX': GROUPS_MANAGER_SETTINGS.get('GROUP_NAME_SUFFIX', '_$$random'),
    'USER_USERNAME_PREFIX': GROUPS_MANAGER_SETTINGS.get('USER_USERNAME_PREFIX', 'DGM_'),
    'USER_USERNAME_SUFFIX': GROUPS_MANAGER_SETTINGS.get('USER_USERNAME_SUFFIX', '_$$random'),
    # Permissions
    'PERMISSIONS': PERMISSIONS,
    # Templates
    'TEMPLATE_STYLE': GROUPS_MANAGER_SETTINGS.get('TEMPLATE_STYLE', 'bootstrap3')
}

But the member that have role referent doesn't have the permission, why?

Please answer me, thanks @OskarPersson

ValueError: "<Group: Compravo>" needs to have a value for field "id" before this many-to-many relationship can be used.

How can I fix?

Traceback (most recent call last):
  File "/usr/local/lib/python3.5/dist-packages/django/core/handlers/exception.py", line 41, in inner
    response = get_response(request)
  File "/usr/local/lib/python3.5/dist-packages/django/core/handlers/base.py", line 249, in _legacy_get_response
    response = self._get_response(request)
  File "/usr/local/lib/python3.5/dist-packages/django/core/handlers/base.py", line 187, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "/usr/local/lib/python3.5/dist-packages/django/core/handlers/base.py", line 185, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/home/ies/bootcamp/bootcamp/authentication/views.py", line 422, in create_society
    fsociety = Group(**form.cleaned_data)
  File "/usr/local/lib/python3.5/dist-packages/mptt/models.py", line 388, in __init__
    super(MPTTModel, self).__init__(*args, **kwargs)
  File "/usr/local/lib/python3.5/dist-packages/django/db/models/base.py", line 567, in __init__
    _setattr(self, prop, kwargs[prop])
  File "/usr/local/lib/python3.5/dist-packages/django/db/models/fields/related_descriptors.py", line 536, in __set__
    manager = self.__get__(instance)
  File "/usr/local/lib/python3.5/dist-packages/django/db/models/fields/related_descriptors.py", line 513, in __get__
    return self.related_manager_cls(instance)
  File "/usr/local/lib/python3.5/dist-packages/django/db/models/fields/related_descriptors.py", line 830, in __init__
    (instance, self.pk_field_names[self.source_field_name]))
ValueError: "<Group: Compravo>" needs to have a value for field "id" before this many-to-many relationship can be used.

Permission matching query does not exist.

Hello, I run into following issue while using Django-groups-manager. When I create a first company making the use of the serialiser below, it works fine. But when I try to register another company, I get error as shown in the track back. What did I do wrong?

class OrganisationCreateSerializer(serializers.ModelSerializer):
    vat = serializers.CharField(allow_blank=False, write_only=True)
    default_admin = CorporateAdminSerializer(many=False)

    def create(self, validated_data):

        validated_data_admin = validated_data.pop('default_admin')

        default_admin = CorporateUser.objects.create(**validated_data_admin)

        company_name = ('%s' % (validated_data['name'])).capitalize()

        default_team_permissions = {
            'owner': {'administrator': ['change','delete'], 'default': ['view']},
            'group': ['view'],
            'groups_upstream': [''],
            'groups_downstream': ['view'],
            'groups_siblings': [''],
        }

        team_type_company = GroupType.objects.get_or_create(codename='%s-company' % company_name.lower(),
                                                            label='%s company' % company_name)[0]
        default_team = Team.objects.get_or_create(
            group_type=team_type_company,
            short_name="%s Team" % company_name,
            name="%s Company Team" % company_name,
            codename="%s" % company_name.lower()
        )[0]

        company = Organisation.objects.create(
            default_team=default_team, default_admin=default_admin, **validated_data)

        corp_user = default_admin


        admin_role = GroupMemberRole.objects.get_or_create(
            codename='administrator', label="Company Administrator")[0]
        member_role = GroupMemberRole.objects.get_or_create(
            codename='member', label="Company Member")[0]

        company.default_team.add_member(corp_user, [admin_role])

        corp_user.assign_object(company.default_team, company,
                                custom_permissions=default_team_permissions)

        company.default_team.assign_object(company, custom_permissions=default_team_permissions)

        return company

    class Meta:
        model = Organisation
        fields = ('id', 'name', 'vat', 'default_admin')
        ref_name = "Organisation"
Trackback:


Request Method: POST
Request URL: http://0.0.0.0:8000/api/v1/register/organisation/

Django Version: 2.1.2
Python Version: 3.6.7
Installed Applications:
('django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'rest_framework',
 'rest_framework.authtoken',
 'django_filters',
 'drf_yasg',
 'guardian',
 'groups_manager',
 'bootstrap3',
 'users',
 'candidates',
 'organisations',
 'django_nose')
Installed Middleware:
('django.middleware.security.SecurityMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware')



Traceback:

File "/usr/local/lib/python3.6/site-packages/django/core/handlers/exception.py" in inner
  34.             response = get_response(request)

File "/usr/local/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response
  126.                 response = self.process_exception_by_middleware(e, request)

File "/usr/local/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response
  124.                 response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "/usr/local/lib/python3.6/site-packages/django/views/decorators/csrf.py" in wrapped_view
  54.         return view_func(*args, **kwargs)

File "/usr/local/lib/python3.6/site-packages/rest_framework/viewsets.py" in view
  116.             return self.dispatch(request, *args, **kwargs)

File "/usr/local/lib/python3.6/site-packages/rest_framework/views.py" in dispatch
  495.             response = self.handle_exception(exc)

File "/usr/local/lib/python3.6/site-packages/rest_framework/views.py" in handle_exception
  455.             self.raise_uncaught_exception(exc)

File "/usr/local/lib/python3.6/site-packages/rest_framework/views.py" in dispatch
  492.             response = handler(request, *args, **kwargs)

File "/usr/local/lib/python3.6/site-packages/rest_framework/mixins.py" in create
  21.         self.perform_create(serializer)

File "/usr/local/lib/python3.6/site-packages/rest_framework/mixins.py" in perform_create
  26.         serializer.save()

File "/usr/local/lib/python3.6/site-packages/rest_framework/serializers.py" in save
  214.             self.instance = self.create(validated_data)

File "/code/vitapio/organisations/serializers.py" in create
  97.                                 custom_permissions=default_team_permissions)

File "/usr/local/lib/python3.6/site-packages/groups_manager/models.py" in assign_object
  122.         return assign_object_to_member(group_member, obj, **kwargs)

File "/usr/local/lib/python3.6/site-packages/groups_manager/perms.py" in assign_object_to_member
  82.         assign_related(siblings_groups, siblings_perms, obj)

File "/usr/local/lib/python3.6/site-packages/groups_manager/perms.py" in assign_related
  33.                 assign_perm(perm_name, django_group, obj)

File "/usr/local/lib/python3.6/site-packages/guardian/shortcuts.py" in assign_perm
  109.         return model.objects.assign_perm(perm, group, obj)

File "/usr/local/lib/python3.6/site-packages/guardian/managers.py" in assign_perm
  39.             permission = Permission.objects.get(content_type=ctype, codename=perm)

File "/usr/local/lib/python3.6/site-packages/django/db/models/manager.py" in manager_method
  82.                 return getattr(self.get_queryset(), name)(*args, **kwargs)

File "/usr/local/lib/python3.6/site-packages/django/db/models/query.py" in get
  399.                 self.model._meta.object_name

Exception Type: DoesNotExist at /api/v1/register/organisation/
Exception Value: Permission matching query does not exist.

How can I adjust the page permission according to the member role?

I can set the page permission according to the user in the group in the decorator below. So how can I set this up for the member's role? Thus, only the member with this role can see the page. I'm waiting for your help.

Screenshot

decorators.py

def sahip_only(view_func):
    def wrapper_function(request, *args, **kwargs):
        group = None
        if request.user.groups.exists():
            group = request.member.groups.all()[0].name
        if group == 'PC':
            return redirect('home')
        if group == 'Console':
            return view_func(request, *args, **kwargs)
        else:
            return HttpResponse('You are not authorized to access this page.')
    return wrapper_function

views.py

@login_required(login_url='/accounts/login/')
@sahip_only
def calisan(request):
    queryset = request.user.groups
    form = CalisanForm(request.POST or None, group_qs=queryset)
    if form.is_valid():
        user = form.save()
        group = form.cleaned_data['group']
        user.groups.add(AGroup.objects.get(name=group))
        username = form.cleaned_data['username']
        member = Member.objects.create(first_name=username)
        group = Group.objects.get(name=form.cleaned_data['group'])
        group.add_member(member, [form.cleaned_data.get('roles')])
        user.save()
        password = form.cleaned_data.get('password1')
        new_user = authenticate(username=user.username, password=password)
        return redirect('home')
    return render(request, 'accounts/calisan/calisan.html', {'form': form, 'title': 'Üye Ol'})

forms.py

class CalisanForm(UserCreationForm):
    username = forms.CharField(max_length=100, label='Kullanıcı Adı')
    email = forms.EmailField(max_length=200, help_text='Required')
    password1 = forms.CharField(max_length=100, label='Parola', widget=forms.PasswordInput)
    password2 = forms.CharField(max_length=100, label='Parola Doğrulama', widget=forms.PasswordInput)
    group = forms.ModelChoiceField(queryset=Group.objects.all(), widget=forms.widgets.RadioSelect(), empty_label=None)
    roles = forms.ModelChoiceField(queryset=GroupMemberRole.objects.all(), widget=forms.widgets.RadioSelect(), empty_label=None)

    def __init__(self, *args, **kwargs):
        qs = kwargs.pop("group_qs")
        super().__init__(*args, **kwargs)
        self.fields["group"].queryset = qs

    class Meta:
        model = User
        fields = [
            'username',
            'email',
            'password1',
            'password2',
            'group',
            'roles',
        ]

    def clean_password2(self):
        password1 = self.cleaned_data.get('password1')
        password2 = self.cleaned_data.get('password2')
        if password1 and password2 and password1 != password2:
            raise forms.ValidationError("Parolalar eşleşmiyor!")
        return password2

    def clean_email(self):
        email = self.cleaned_data.get('email')
        lenghtw = len(User.objects.filter(email=email))
        if lenghtw > 0 :
            raise forms.ValidationError('Bu email adresine sahip bir kullanıcı zaten var.')
        return email

Migration being created inside groups_manager/migrations

Hi, first of all, thank you, this library is amazing.

I've noticed in my migrations that I have dependencies on a 0007_alter_group_group_entities_alter_group_group_members_and_more.py

This is being created, but it's difficult to version in git. Is this missing from your repo? Or am I doing something wrong?

Migrations for 'groups_manager':
  venv/lib/python3.8/site-packages/groups_manager/migrations/0007_alter_group_group_entities_alter_group_group_members_and_more.py
    - Alter field group_entities on group
    - Alter field group_members on group
    - Alter field group_type on group
    - Alter field id on group
    - Alter field parent on group
    - Alter field id on groupentity
    - Alter field id on groupmember
    - Alter field id on groupmemberrole
    - Alter field id on grouptype
    - Alter field django_user on member
    - Alter field id on member

thank you!

Directly assigning an object to a Group is not implemented

Is this intentionally left unimplemented in order to implement in a subclass?

I'd like to be able to do (as the API shows) e.g.

my_group.assign_object(some_object)

instead of having to associate that with a user (which the docs show) e.g.

my_user.assign_object(my_group, some_object)

Why is django-guardian required?

From the documentation I had the feeling that guardian is optional, however, guardian is listed as a required package and will be installed with django-groups-manager,

'django-guardian',

Then because guardian can be imported,

from guardian.shortcuts import assign_perm

django complains about

  File "manage.py", line 30, in <module>
    execute_from_command_line(sys.argv)
  File "/usr/local/lib/python3.7/site-packages/django/core/management/__init__.py", line 381, in execute_from_command_line
    utility.execute()
  File "/usr/local/lib/python3.7/site-packages/django/core/management/__init__.py", line 357, in execute
    django.setup()
  File "/usr/local/lib/python3.7/site-packages/django/__init__.py", line 24, in setup
    apps.populate(settings.INSTALLED_APPS)
  File "/usr/local/lib/python3.7/site-packages/django/apps/registry.py", line 114, in populate
    app_config.import_models()
  File "/usr/local/lib/python3.7/site-packages/django/apps/config.py", line 211, in import_models
    self.models_module = import_module(models_module_name)
  File "/usr/local/lib/python3.7/importlib/__init__.py", line 127, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1006, in _gcd_import
  File "<frozen importlib._bootstrap>", line 983, in _find_and_load
  File "<frozen importlib._bootstrap>", line 967, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 677, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 728, in exec_module
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "/usr/local/lib/python3.7/site-packages/groups_manager/models.py", line 22, in <module>
    from groups_manager.perms import assign_object_to_member, assign_object_to_group
  File "/usr/local/lib/python3.7/site-packages/groups_manager/perms.py", line 4, in <module>
    from guardian.shortcuts import assign_perm
  File "/usr/local/lib/python3.7/site-packages/guardian/shortcuts.py", line 27, in <module>
    GroupObjectPermission = get_group_obj_perms_model()
  File "/usr/local/lib/python3.7/site-packages/guardian/utils.py", line 228, in get_group_obj_perms_model
    from guardian.models import GroupObjectPermissionBase
  File "/usr/local/lib/python3.7/site-packages/guardian/models/__init__.py", line 1, in <module>
    from .models import (
  File "/usr/local/lib/python3.7/site-packages/guardian/models/models.py", line 69, in <module>
    class UserObjectPermission(UserObjectPermissionAbstract):
  File "/usr/local/lib/python3.7/site-packages/django/db/models/base.py", line 111, in __new__
    "INSTALLED_APPS." % (module, name)
RuntimeError: Model class guardian.models.models.UserObjectPermission doesn't declare an explicit app_label and isn't in an application in INSTALLED_APPS.

So guardian has to be installed to INSTALLED_APPS. Should not django-guardian be removed from setup.py if it is indeed optional?

Member and Django User

Hi again!

I think the Member class could has a relationship with django user OneToOne, in that way the reverse call is direct.

Like 'user.member' despite 'user.members.first()' (because uses foreignkey'.

Is a bit more consistent because identifies one member with one user....

could help

Add kwargs for django auth models sync

When subclassing Group and Member classes, the check on signal functions are made against GROUPS_MANAGER's AUTH_MODELS_SYNC key.
With a kwarg it will be easily controlled separately for each subclassed model.

Permission for user with specific object

Hi,

in template view doesn't work the get_obj_perms.

{% load guardian_tags %}
{% get_obj_perms request.user for groups_manager as "context_var" %}
{{context_var}}

{{perms.groups_manager}}
          {{perms.groups}}
          
          <!--PERMISSIONS_HERE-->
          {% if perms.groups_manager.can_add_member_custom %}
            <p>
              <a href="{% url 'groups_manager:group_member_add_member' group.id %}">
                <i class="fa fa-plus"></i>
                Add member to group
              </a>
            </p>
          {% endif %}

screen shot 2017-11-22 at 09 35 06

But with django shell it works:
screen shot 2017-11-21 at 16 42 17

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.