3

I want allow from my backend API, that any user can be created with characters like .,-,_, ñ between others characters in their username field which is primary_key=True,.

I define my custom user (AbstractBaseUser) of this way, in relation to username field which is of my interest:

class User(AbstractBaseUser, PermissionsMixin):

    username = models.CharField(
        _('username'),
        max_length=30,
        primary_key=True,
        unique=True,
        help_text=_('Required. 30 characters or fewer. Letters, digits and @/./+/-/_ only.'),
        validators=[
            RegexValidator(
                r'^[\w.@+-]+$',
                _('Enter a valid username. This value may contain only '
                  'letters, numbers ' 'and @/./+/-/_ characters.')
            ),
        ],
        error_messages={
            'unique': _("A user with that username already exists."),
        },
    )
    email = models.EmailField(max_length=254, unique=True)
    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['username']
    objects = UserManager()

My UserSerializer is this:

class UserSerializer(serializers.ModelSerializer):
    username = serializers.CharField(validators=[UniqueValidator(queryset=User.objects.all(), message='Lo sentimos, existe un fichaje con este nombre de usuario')])
    email = serializers.EmailField(validators=[UniqueValidator(queryset=User.objects.all(), message='Lo sentimos, alguien ya ha sido fichado con este correo electrónico')])

    class Meta:
        model = User
        fields = ('url', 'username', 'password', 'first_name','last_name',
                  'age','other fields ...',)

My UserViewSet is the following:

class UserViewSet(viewsets.ModelViewSet):
    """
    API endpoint that allows users to be viewed or edited.
    """
    queryset = User.objects.all().order_by('-date_joined')
    serializer_class = UserSerializer
    filter_fields = ('username', 'is_player', 'first_name', 'last_name', 'team' , 'email', )

The router is defined og this way in urls.py

router = routers.DefaultRouter()
router.register(r'users', UserViewSet)

When I create an user with . character for example like bacalao.cevichica in te username field, the user is created, but when I go to localhost:8000/api/users/

I get this message:

File "/home/bgarcial/.virtualenvs/fuupbol2/lib/python3.5/site-packages/django/urls/resolvers.py", line 392, in _reverse_with_prefix
    (lookup_view_s, args, kwargs, len(patterns), patterns)
django.urls.exceptions.NoReverseMatch: Reverse for 'user-detail' with arguments '()' and keyword arguments '{'pk': 'bacalao.cevichica'}' not found. 2 pattern(s) tried: ['api/users/(?P<pk>[^/.]+)\\.(?P<format>[a-z0-9]+)/?$', 'api/users/(?P<pk>[^/.]+)/$']

enter image description here

I am not very familiarized with the regular expresions, and is possible that the RegexValidator is not well formed?

Also, is possible that my problem is in the UserSerializer or UserViewSet.

By the moment I have not clear this topic, any orientation is highly appreciated. :)

bgarcial
  • 2,915
  • 10
  • 56
  • 123
  • 1
    It just sounds like the URL pattern doesn't support periods. Can you include the regex it's using in plaintext? – TankorSmash Mar 16 '17 at 16:13
  • @TankorSmash in theory the regex which I am using is the code section of `RegexValidator( r'^[\w.@+-]+$', _('Enter a valid username. This value may contain only ' 'letters, numbers ' 'and @/./+/-/_ characters.') ),` in the username field in model User ... ? My apologies, I am newbie with regular expressions – bgarcial Mar 16 '17 at 16:16

1 Answers1

4

If you look at the error you'll notice that it tried to match against some url, but failed. This is because the default regex ([^./]) excludes . and / characters

You can add a lookup_value_regex to your ViewSet so that the URL knows what format your primary key should be in:

class UserViewSet(viewsets.ModelViewSet):
    """
    API endpoint that allows users to be viewed or edited.
    """
    lookup_value_regex = '[\w.@+-]+'
    queryset = User.objects.all().order_by('-date_joined')
    serializer_class = UserSerializer
    filter_fields = ('username', 'is_player', 'first_name', 'last_name', 'team' , 'email', )
TankorSmash
  • 12,186
  • 6
  • 68
  • 106
Resley Rodrigues
  • 2,218
  • 17
  • 17