Git Product home page Git Product logo

django-custom-user's Introduction

Django Custom User

PyPI version GitHub Actions Workflow Status (main branch)

Custom user model for Django with the same behaviour as the default User class but without a username field. Uses email as the USERNAME_FIELD for authentication.

Quick start

  1. Install django-custom-user with your favorite Python package manager:
pip install django-custom-user
  1. Add 'custom_user' to your INSTALLED_APPS setting:
INSTALLED_APPS = (
    # other apps
    'custom_user',
)
  1. Set your AUTH_USER_MODEL setting to use EmailUser:
AUTH_USER_MODEL = 'custom_user.EmailUser'
  1. Create the database tables:
python manage.py migrate

Usage

Instead of referring to EmailUser directly, you should reference the user model using get_user_model() as explained in the Django documentation. For example:

from django.contrib.auth import get_user_model

user = get_user_model().objects.get(email="[email protected]")

When you define a foreign key or many-to-many relations to the EmailUser model, you should specify the custom model using the AUTH_USER_MODEL setting. For example:

from django.conf import settings
from django.db import models

class Article(models.Model):
    author = models.ForeignKey(settings.AUTH_USER_MODEL)

Extending EmailUser model

You can easily extend EmailUser by inheriting from AbstractEmailUser. For example:

from custom_user.models import AbstractEmailUser

class MyCustomEmailUser(AbstractEmailUser):
    """
    Example of an EmailUser with a new field date_of_birth
    """
    date_of_birth = models.DateField()

Remember to change the AUTH_USER_MODEL setting to your new class:

AUTH_USER_MODEL = 'my_app.MyCustomEmailUser'

If you use the AdminSite, add the following code to your my_app/admin.py file:

from django.contrib import admin
from custom_user.admin import EmailUserAdmin
from .models import MyCustomEmailUser


class MyCustomEmailUserAdmin(EmailUserAdmin):
    """
    You can customize the interface of your model here.
    """
    pass

# Register your models here.
admin.site.register(MyCustomEmailUser, MyCustomEmailUserAdmin)

Supported versions

Django:

  • 4.1
  • 4.0
  • 3.2 LTS

Python:

  • 3.11
  • 3.10
  • 3.9
  • 3.8
  • 3.7

Changelog

Version 1.1 (2022-12-10)

Added support for Django 4.1 and Python 3.11.

Version 1.0 (2022-03-29)

After a long hiatus, this new version brings compatibility with the latest Django and Python versions, among lots of small improvements and cleanups.

  • Supported versions:
    • Django: 3.2 LTS, 4.0
    • Python: 3.7, 3.8, 3.9, 3.10
  • Import latest code changes from Django 4.0 (#65):
    • EmailUserCreationForm does not strip whitespaces in the password fields, to match Django's behavior.
    • EmailUserCreationForm supports custom password validators configured by AUTH_PASSWORD_VALIDATORS.
    • EmailUser.objects.create_superuser() allows empty passwords. It will also check that both is_staff and is_superuser parameters are True (if passed). Otherwise, it would create an invalid superuser.
  • Internal changes:
    • Moved away from Travis CI to Github Actions.
    • Build system and dependencies managed with Poetry.
    • Code formatted with black and isort.

Note that older versions of Django are not supported, but you can use the previous version 0.7 if you need it.

Version 0.7 (2017-01-12)

  • Fixed change password link in EmailUserChangeForm (thanks to Igor Gai and rubengrill)

Version 0.6 (2016-04-03)

  • Added migrations (thanks to everybody for the help).

How to apply the migrations after upgrading:

Django 1.7

For this version just run the following commands.

python manage.py migrate custom_user 0001_initial_django17 --fake
python manage.py migrate custom_user

Django 1.8

This version didn't work without migrations, which means that your migrations will conflict with the new ones included in this version.

If you added the migrations with Django's MIGRATION_MODULES setting, delete the folder containing the migration modules and remove the setting from your config.

If you just ran python manage.py makemigrations, the migrations are located inside your system's or virtualenv's site-packages folder. You can check the location running this command, and then delete the folder migrations that is inside:

python -c "import os; import custom_user; print(os.path.dirname(custom_user.__file__))"

You can check if you have removed the migrations successfully running this command, you shouldn't see the section custom_user anymore:

python manage.py migrate --list

Once the old migrations are gone, run the following command to finish:

python manage.py migrate custom_user 0002_initial_django18 --fake

Version 0.5 (2014-09-20)

  • Django 1.7 compatible (thanks to j0hnsmith).
  • Custom application verbose_name in AdminSite with AppConfig.

Version 0.4 (2014-03-06)

  • The create_user() and create_superuser() manager methods now accept is_active and is_staff as parameters (thanks to Edil Kratskih).

Version 0.3 (2014-01-17)

  • AdminSite now works when subclassing AbstractEmailUser (thanks to Ivan Virabyan).
  • Updated model changes from Django 1.6.1.

Version 0.2 (2013-11-24)

  • Django 1.6 compatible (thanks to Simon Luijk).

Version 0.1 (2013-04-09)

  • Initial release.

django-custom-user's People

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  avatar  avatar  avatar  avatar  avatar

Watchers

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

django-custom-user's Issues

Accessor for m2m field 'groups' clashes with related m2m field 'Group.user_set'.

Hi there,
I'm trying to extend the UserEmail model, and when I run the schemamigration with South, I get this:

CommandError: One or more models did not validate:
ducales_site.usuariocustomemailuser: Accessor for m2m field 'groups' clashes with related m2m field 'Group.user_set'. Add a related_name argument to the definition for 'groups'.
ducales_site.usuariocustomemailuser: Accessor for m2m field 'user_permissions' clashes with related m2m field 'Permission.user_set'. Add a related_name argument to the definition for 'user_permissions'.
custom_user.emailuser: Accessor for m2m field 'groups' clashes with related m2m field 'Group.user_set'. Add a related_name argument to the definition for 'groups'.
custom_user.emailuser: Accessor for m2m field 'user_permissions' clashes with related m2m field 'Permission.user_set'. Add a related_name argument to the definition for 'user_permissions'.

Here is my model:

from custom_user.models import AbstractEmailUser
class UsuarioCustomEmailUser(AbstractEmailUser):
    generos = (('M', 'Masculino'), ('F', 'Femenino'),)
    tipo_documento = (('CC', 'Cédula de Ciudadanía'), ('CE', 'Cédula de Extranjería'),)
    genero = models.CharField(blank = True, max_length = 1, choices = generos, verbose_name = u'Género')
    t_documento = models.CharField(blank = True, max_length = 2, choices = tipo_documento, verbose_name = u'Tipo de documento')
    n_documento = models.IntegerField(blank = True, max_length = 15, verbose_name = u'No. de documento')
    direccion = models.CharField(blank = True, max_length = 140, verbose_name = u'Dirección')
    ciudad = models.ForeignKey(Ciudad, blank = True, verbose_name = u'Ciudad')
    twitter = models.CharField(blank = True, max_length = 15, verbose_name = u'Twitter')
    tyc = models.BooleanField(verbose_name = u'Acepta términos y condiciones')
    recibir_sms = models.BooleanField(blank = True, verbose_name = u'Acepta recibir información en el celular')
    recibir_correo = models.BooleanField(blank = True, verbose_name = u'Acepta recibir información en el correo electrónico')

How can I add the related_name argument to solve this? Thanks in advance.

Subclass and password in Django Admin.

Hello. I created subclass like an example

from django.conf import settings
from django.db import models

class Article(models.Model):
author = models.ForeignKey(settings.AUTH_USER_MODEL)

and when i try add new User in Django Admin, i have no standart form for this.. have just one field for passwd, and this is no works (no hash pass..) how fix it? Tnx for answer.

Not the same behavior as Django's default User

This project's description is:

Custom user model for Django >= 1.5 with the same behaviour as Django's default User but with email instead of username.

The thing is, this custom user model doesn't have the same behavior as Django's default User. I expected this to be exactly the same as what I get with from django.contrib.auth.models import User, only without a username. It turns out that it's missing the first_name and last_name fields. Also, the get_full_name and get_short_name methods behave differently than Django's default User.

I propose that these differences be brought into alignment with Django's default behavior. Either that or change this project's description so that it's not misleading. Other than that, this project is great!

AbstractEmailUser without get_profile?

Any special reason for not having a get_profile method in AbstractEmailUser? This is the get_profile for Django 1.5.1:

    def get_profile(self):
        """
        Returns site-specific profile for this user. Raises
        SiteProfileNotAvailable if this site does not allow profiles.
        """
        warnings.warn("The use of AUTH_PROFILE_MODULE to define user profiles has been deprecated.",
            PendingDeprecationWarning)
        if not hasattr(self, '_profile_cache'):
            from django.conf import settings
            if not getattr(settings, 'AUTH_PROFILE_MODULE', False):
                raise SiteProfileNotAvailable(
                    'You need to set AUTH_PROFILE_MODULE in your project '
                    'settings')
            try:
                app_label, model_name = settings.AUTH_PROFILE_MODULE.split('.')
            except ValueError:
                raise SiteProfileNotAvailable(
                    'app_label and model_name should be separated by a dot in '
                    'the AUTH_PROFILE_MODULE setting')
            try:
                model = models.get_model(app_label, model_name)
                if model is None:
                    raise SiteProfileNotAvailable(
                        'Unable to load the profile model, check '
                        'AUTH_PROFILE_MODULE in your project settings')
                self._profile_cache = model._default_manager.using(
                                   self._state.db).get(user__id__exact=self.id)
                self._profile_cache.user = self
            except (ImportError, ImproperlyConfigured):
                raise SiteProfileNotAvailable
        return self._profile_cache

migration not included in python package, causing migrations not to run

Fixed in #27

Shown by first installing package normally, and then from my master.

# virtualenv ve1
New python executable in ve1/bin/python2.7
Also creating executable in ve1/bin/python
Installing setuptools, pip, wheel...done.
# ve1/bin/pip install django-custom-user
Collecting django-custom-user
  Using cached django_custom_user-0.5-py2.py3-none-any.whl
Collecting Django>=1.5 (from django-custom-user)
  Using cached Django-1.9-py2.py3-none-any.whl
Installing collected packages: Django, django-custom-user
Successfully installed Django-1.9 django-custom-user-0.5
# ve1/bin/python
Python 2.7.10 (default, Jul 13 2015, 12:05:58)
[GCC 4.2.1 Compatible Apple LLVM 6.1.0 (clang-602.0.53)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from custom_user.migrations import *
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named migrations
>>>
# virtualenv ve2
New python executable in ve2/bin/python2.7
Also creating executable in ve2/bin/python
Installing setuptools, pip, wheel...done.
# ve2/bin/pip install https://github.com/peterlauri/django-custom-user/archive/master.zip
Collecting https://github.com/peterlauri/django-custom-user/archive/master.zip
  Downloading https://github.com/peterlauri/django-custom-user/archive/master.zip
     | 28kB 204kB/s
Collecting Django>=1.5 (from django-custom-user==0.5)
  Using cached Django-1.9-py2.py3-none-any.whl
Installing collected packages: Django, django-custom-user
  Running setup.py install for django-custom-user
Successfully installed Django-1.9 django-custom-user-0.5
# ve2/bin/python
Python 2.7.10 (default, Jul 13 2015, 12:05:58)
[GCC 4.2.1 Compatible Apple LLVM 6.1.0 (clang-602.0.53)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from custom_user.migrations import *
>>>

Instructions aren't quite complete

The instructions in README.rst don't quite cover using django-custom-user. I think the missing bits are just urls.py and the necessary templates. The first reaction on not seeing those specified is to use the urls.py and templates from the django default registration backend, but that leads to some odd behavior on user registration, as discussed in this SO question.

RemovedInDjango18Warning

$ ./manage.py check
... /custom_user/forms.py:60: RemovedInDjango18Warning: Creating a ModelForm without either the 'fields' attribute or the 'exclude' attribute is deprecated - form EmailUserChangeForm needs updating
class EmailUserChangeForm(forms.ModelForm):

Emails are not being validated

Emails are not being validated:

user = get_user_model().objects.create_user(email="notvalidemail", password="password")
print(user) # notvalidemail
validate_email(user.email) # raises ValidationError: ['Enter a valid email address.']

EmailUser is using EmailField for email field and Django documentation says

EmailField

class EmailField(max_length=254, **options)[source]
A CharField that checks that the value is a valid email address. It uses EmailValidator to validate the input.

How is this possible?

Base on Django documentation, full_clean() should be called before saving objects:
https://docs.djangoproject.com/en/1.11/ref/models/instances/#django.db.models.Model.full_clean

Using Django 1.11.5 and Django Custom User 0.7

ImportError: No module named 'custom_usermail' after install

After properly installing (with pip, adding the app in INSTALLED_APPS, and the line AUTH_USER_MODEL = 'custom_user.EmailUser'), I get

ImportError: No module named 'custom_usermail'

when I want to run python manage.py syncdb or python manage.py runserver

I am running it with Django 1.6 and python 3.3.

Full traceback in case that helps:

Traceback (most recent call last):
  File "manage.py", line 10, in <module>
    execute_from_command_line(sys.argv)
  File "/Users/maxbellec/anaconda/envs/py3/lib/python3.3/site-packages/django/core/management/__init__.py", line 399, in execute_from_command_line
    utility.execute()
  File "/Users/maxbellec/anaconda/envs/py3/lib/python3.3/site-packages/django/core/management/__init__.py", line 392, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/Users/maxbellec/anaconda/envs/py3/lib/python3.3/site-packages/django/core/management/base.py", line 242, in run_from_argv
    self.execute(*args, **options.__dict__)
  File "/Users/maxbellec/anaconda/envs/py3/lib/python3.3/site-packages/django/core/management/base.py", line 280, in execute
    translation.activate('en-us')
  File "/Users/maxbellec/anaconda/envs/py3/lib/python3.3/site-packages/django/utils/translation/__init__.py", line 130, in activate
    return _trans.activate(language)
  File "/Users/maxbellec/anaconda/envs/py3/lib/python3.3/site-packages/django/utils/translation/trans_real.py", line 188, in activate
    _active.value = translation(language)
  File "/Users/maxbellec/anaconda/envs/py3/lib/python3.3/site-packages/django/utils/translation/trans_real.py", line 177, in translation
    default_translation = _fetch(settings.LANGUAGE_CODE)
  File "/Users/maxbellec/anaconda/envs/py3/lib/python3.3/site-packages/django/utils/translation/trans_real.py", line 159, in _fetch
    app = import_module(appname)
  File "/Users/maxbellec/anaconda/envs/py3/lib/python3.3/importlib/__init__.py", line 90, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1582, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1563, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1527, in _find_and_load_unlocked

EmailUser considers [email protected] and [email protected] different users

The domain part of an email address is case-insensitive. These days the local-part is considered case-sensitive too by nearly every email provider.

With EmailUser I was able to create two users in the admin with addresses [email protected] and [email protected] - this should be impossible, these should not be judged as unique.

I'm grappling with this in a project I'm working on, where users can type an email address to invite other users to a project - if they use a different case, then the user that already has an account gets another signup email! Not good. So I have to use get(email__iexact='...'), but now I have the problem that get() could crash since there could be multiple accounts returned!

Currently I'm 'fixing' with the following manager:

class UserManager(EmailUserManager):
    def filter(self, **kwargs):
        if 'email' in kwargs:
            kwargs['email__iexact'] = kwargs['email']
            del kwargs['email']
        return super(UserManager, self).filter(**kwargs)

    def get(self, **kwargs):
        if 'email' in kwargs:
            kwargs['email__iexact'] = kwargs['email']
            del kwargs['email']
        return super(UserManager, self).get(**kwargs)

But this feels pretty hacky and I'm concerned that these won't pass to the queryset, so User.objects.get(email='...') works fine but User.objects.filter(is_admin=True).filter(email='...') won't.

Any ideas on how this could be resolved and perhaps incorporated into django-custom-user?

EmailUserChangeForm assumes clean_password can't fail.

Should the EmailUserChangeForm be used in such a way as only a subset of fields are set, return self.initial["password"] may fail because password isn't in self.initial, resulting in a KeyError ...

I have no idea what the rationale is for returning the initial password (nor where it's even set), but it should probably be done in the safer form of return self.initial.get('password', '') ... substituting '' for None if applicable.

"Change password" admin page is missing

When you visit a User admin page, Django provides a link to set someone's password

change password form link

When clicking that link with Django Custom User installed, it 404's

change password form 404

From the error, user object with primary key u'1/change' does not exist, looks like either a URL regex might be outdated, or this functionality was never implemented in the first place.

Not working in Django 1.9

I am trying to get this working fully in Django 1.9, but I'm having an issue...
The default setup works fine, but I need to extend your model. However, I follow your directions to the letter (literally copy and paste, including creating an app called "my_app"), but it gets an error on migrations that ultimately won't let is setup any of the auth tables... any ideas?

I wonder if related to changed referenced at: https://docs.djangoproject.com/en/1.9/releases/1.9/#django-contrib-auth

Here's the error:

File "/usr/local/lib/python3.4/site-packages/django/db/backends/utils.py", line 64, in execute
return self.cursor.execute(sql, params)
File "/usr/local/lib/python3.4/site-packages/django/db/backends/mysql/base.py", line 112, in execute
return self.cursor.execute(query, args)
File "/usr/local/lib/python3.4/site-packages/MySQLdb/cursors.py", line 226, in execute
self.errorhandler(self, exc, value)
File "/usr/local/lib/python3.4/site-packages/MySQLdb/connections.py", line 36, in defaulterrorhandler
raise errorvalue
File "/usr/local/lib/python3.4/site-packages/MySQLdb/cursors.py", line 217, in execute
res = self._query(query)
File "/usr/local/lib/python3.4/site-packages/MySQLdb/cursors.py", line 378, in _query
rowcount = self._do_query(q)
File "/usr/local/lib/python3.4/site-packages/MySQLdb/cursors.py", line 341, in _do_query
db.query(q)
File "/usr/local/lib/python3.4/site-packages/MySQLdb/connections.py", line 280, in query
_mysql.connection.query(self, query)
_mysql_exceptions.IntegrityError: (1215, 'Cannot add foreign key constraint')

Deprecation warning for ugettext_lazy

Have been using this library since Django 1.6, works really well, no complaints - thanks for building!

In at least Django 2, ugettext_lazy issues a deprecation warning in favor if gettext_lazy - related to deprecating Python 2 support, I assume

Is there interest in releasing a new version of this, changing imports of ugettext_lazy to gettext_lazy? Otherwise should be no changes needed, ugettext_lazy is just an alias for gettext_lazy as it is.

I'm happy to make a PR (basically trivial) - but if there isn't interest in a version bump after so long I understand, and we'll probably move to vendoring our own version

Prevent user registration - when any UserProfile filed is invalid

Hello,

I'm trying to use django-registration-redux along with custom_user. I have added both apps to settings.py

My main urls.py is as given below

from userprofile.forms import UserProfileForm
from registration.backends.default.views import RegistrationView
urlpatterns = [
url(r'user/register/$', 
        RegistrationView.as_view(form_class = UserProfileForm), 
        name = 'registration_register'),

    url(r'^user/', include('registration.backends.default.urls')),
]

I have a UserProfile model as given below. (userprofile/models.py)

def validate_dob(value):
    now=timezone.now()
    start_date=date(now.year-settings.AGE_UPPER, 1, 1)
    end_date=date(now.year-settings.AGE_LOWER, 12, 31)
    print("start: %s end: %s supplied :%s" % (start_date, end_date, value))
    if start_date >value or value > end_date:
            raise ValidationError("Please choose a valid date from the given set") 
#----------------------------------------
class UserProfile(models.Model):
    user=models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE,
        primary_key=True,)
    fullname=models.CharField(max_length=70, blank=False)
    dob=models.DateField(blank=False,validators=[validate_dob] )
    photo=models.ImageField(upload_to='profile_images', blank=False)
    def __str__(self):
        return self.user.email
    def get_profile(self):
        return self.user.id
#-------------------------------------
def user_registered_callback(sender, user, request, **kwargs):
    #print(user.email)
    profile = UserProfile(user = user)
    print(request.POST)
    profile.fullname =request.POST["fullname"]
    profile.dob ="%s-%s-%s" % (request.POST["dob_year"],request.POST["dob_month"],request.POST["dob_day"])
    #profile.dob=request.POST["dob"]
    if 'photo' in request.FILES:
        profile.photo = request.FILES['photo']

    profile.save()

user_registered.connect(user_registered_callback)

and here's my userprofile/forms.py

class UserProfileForm(RegistrationForm):
    fullname=forms.CharField(required=True,label="Full name",  min_length=3, max_length=75)
    dob=forms.DateField(required=True,label="Date of birth", 
        widget=forms.SelectDateWidget(years=range(now.year-settings.AGE_UPPER,now.year-settings.AGE_LOWER)))

    photo=forms.ImageField(required=True)`

How do I prevent inserting User values into the table if the filed, say dob is not in the specified range (AGE_UPPER=70 ,AGE_LOWER=18)

Please tell me if I'm making this over complicated.

Thanks

Edit New issue Subclassing AbstractEmailUser does not prompt for superuser on syncdb to blank database

I am virtually copying EmailUser, but just adding a field:

class CustomUser(AbstractEmailUser):
    """
    Subclass EmailUser to add the last_seen date.
    """
    last_seen = models.DateField(auto_now_add=True)

    class Meta(AbstractEmailUser.Meta):
        swappable = 'AUTH_USER_MODEL'

If I syncdb to a blank DB with AUTH_USER_MODEL = 'custom_user.EmailUser' then I am prompted for superuser no problem. But with my custom model above, no such luck.

I know I can call createsuperuser but I'd like to understand what I'm missing :)

Thanks for any advice :D

Problem extending EmailUser

I'm trying to extend the EmailUser model using the instructions in https://github.com/jcugat/django-custom-user#extending-emailuser-model. I'm also extending the EmailUserAdmin. When I run "python manage.py migrate", i get the following error:

django.core.exceptions.ImproperlyConfigured: AUTH_USER_MODEL refers to model 'ccuser.CCUser' that has not been installed

I believe the problem is in 'custom_user/forms.py'.

clase EmailUserCreationForm(forms.ModelForm):

...
class Meta:
model: get_user_model()

Shouldn't we use settings.AUTH_USER_MODEL here instead of get_user_model()?

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.