Search code examples
pythondjangodjango-allauth

Cannot resolve keyword 'username' into field. Choices are: city, id, phone, etc


I would like to ask for help in these issue. I do know that it seems similar to other questions regarding the same issue, but I did look around and there was nothing that actually could solve my issue. Btw, it is my second asking here, so please tell me if this message is too long. Thanks!

I am using AllAuth with Django 1.8 and Python 3.5

I want to implement a simple profile page based on the username provided from AllAuth. The issue is, I didn't specify the username or e-mail field in my model, I have only extended it to add some information that I would like to have, but it seems that Django only identifies the fields that I extended and I cannot find the right way to grab that information from AllAuth.

Here is my code (some of the custom fields are in Portuguese, but all the core stuff is in english):

profiles/models.py

from django.conf import settings
from django.db import models
from django.db.models.signals import post_save
from django.utils.encoding import smart_text

UF_CHOICES = (
    ('SP', 'SP'),
    ('RJ', 'RJ')
)

class Profile(models.Model):
    user = models.OneToOneField(settings.AUTH_USER_MODEL)

    uf = models.CharField(
                        max_length = 2,
                        blank=False,
                        default = 'SP',
                        choices = UF_CHOICES,
                        verbose_name = 'UF',
                        )
    cidade = models.CharField(max_length=120, null=True, blank=True, default="Rio de Janeiro")
    telefone = models.CharField(max_length = 20, blank=True, null=True, verbose_name = 'Telefone para Contato')

    def __str__(self):
        return smart_text(self.user)



def post_save_user_model_receiver(sender, instance, created, *args, **kwargs):
    if created:
        try:
            Profile.objects.create(user=instance)
        except:
            pass

post_save.connect(post_save_user_model_receiver, sender=settings.AUTH_USER_MODEL)

profiles/forms.py

from django import forms
from .models import Profile

class ProfileForm(forms.ModelForm):
    class Meta:
        model = Profile
        fields = [
            "uf",
            "cidade",
            "telefone",
        ]

    def profile(self, request, user):
        user.uf = self.cleaned_data['uf']
        user.cidade = self.cleaned_data['cidade']
        user.telefone = self.cleaned_data['telefone']
        user.save()

profiles/admin.py

from django.contrib import admin

# Register your models here.

from .models import Profile

admin.site.register(Profile)

profiles/views.py

from django.contrib.auth.decorators import login_required
from django.shortcuts import render, get_object_or_404
from .models import Profile

# Create your views here.

@login_required
def profile_detail(request, username=None):
    obj = get_object_or_404(Profile, username=username)
    context = {
        "object": obj,
    }
    template = 'profile_detail.html'
    return render(request, template, context)

profiles/adapter.py [note that here the username shows up] like the documentations specifies: http://django-allauth.readthedocs.io/en/latest/advanced.html

from django.conf import settings
from allauth.account.adapter import DefaultAccountAdapter

class MyAccountAdapter(DefaultAccountAdapter):

    def get_login_redirect_url(self, request):
        path = "/profiles/{username}/"
        return path.format(username=request.user.username)

profiles/urls.py

from django.conf.urls import url
from .views import profile_detail

urlpatterns = [

    url(r'^(?P<username>[\w.@+-]+)/$', profile_detail, name='profile_detail'),
]

Finally, the error message:

Environment:


Request Method: GET
Request URL: http://localhost:8000/profiles/Sofia/

Django Version: 1.8.17
Python Version: 3.5.2
Installed Applications:
('django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.sites',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'allauth',
 'allauth.account',
 'allauth.socialaccount',
 'allauth.socialaccount.providers.facebook',
 'crispy_forms',
 'newsletter',
 'profiles',
 'properties')
Installed Middleware:
('django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware',
 'django.middleware.security.SecurityMiddleware')


Traceback:
File "/Users/Alex/Desktop/Hunters/lib/python3.5/site-packages/django/core/handlers/base.py" in get_response
  132.                     response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/Users/Alex/Desktop/Hunters/lib/python3.5/site-packages/django/contrib/auth/decorators.py" in _wrapped_view
  22.                 return view_func(request, *args, **kwargs)
File "/Users/Alex/Desktop/Hunters/src/profiles/views.py" in profile_detail
  9.     obj = get_object_or_404(Profile, username=username)
File "/Users/Alex/Desktop/Hunters/lib/python3.5/site-packages/django/shortcuts.py" in get_object_or_404
  155.         return queryset.get(*args, **kwargs)
File "/Users/Alex/Desktop/Hunters/lib/python3.5/site-packages/django/db/models/query.py" in get
  325.         clone = self.filter(*args, **kwargs)
File "/Users/Alex/Desktop/Hunters/lib/python3.5/site-packages/django/db/models/query.py" in filter
  679.         return self._filter_or_exclude(False, *args, **kwargs)
File "/Users/Alex/Desktop/Hunters/lib/python3.5/site-packages/django/db/models/query.py" in _filter_or_exclude
  697.             clone.query.add_q(Q(*args, **kwargs))
File "/Users/Alex/Desktop/Hunters/lib/python3.5/site-packages/django/db/models/sql/query.py" in add_q
  1310.         clause, require_inner = self._add_q(where_part, self.used_aliases)
File "/Users/Alex/Desktop/Hunters/lib/python3.5/site-packages/django/db/models/sql/query.py" in _add_q
  1338.                     allow_joins=allow_joins, split_subq=split_subq,
File "/Users/Alex/Desktop/Hunters/lib/python3.5/site-packages/django/db/models/sql/query.py" in build_filter
  1150.         lookups, parts, reffed_expression = self.solve_lookup_type(arg)
File "/Users/Alex/Desktop/Hunters/lib/python3.5/site-packages/django/db/models/sql/query.py" in solve_lookup_type
  1036.         _, field, _, lookup_parts = self.names_to_path(lookup_splitted, self.get_meta())
File "/Users/Alex/Desktop/Hunters/lib/python3.5/site-packages/django/db/models/sql/query.py" in names_to_path
  1397.                                      "Choices are: %s" % (name, ", ".join(available)))

Exception Type: FieldError at /profiles/Sofia/
Exception Value: Cannot resolve keyword 'username' into field. Choices are: cidade, id, telefone, uf, user, user_id

Solution

  • Okay, I found out the issue. Took me very long because I wasn't looking at it the right way.

    The issue wasn't in the code itself, it was more about which model was actually storing the information I needed. In this case I wanted to get the User and Profile information from the database without realizing that they were two separate modules. I was trying to get from Profile information stored by the User.

    The original was:

    profiles.views.py (old and wrong)

    from django.contrib.auth.decorators import login_required
    from django.shortcuts import render, get_object_or_404
    from .models import Profile
    
    # Create your views here.
    
    @login_required
    def profile_detail(request, username=None):
        obj = get_object_or_404(Profile, username=username)
        context = {
            "object": obj,
        }
        template = 'profile_detail.html'
        return render(request, template, context)
    

    profiles.views.py (new and working) -- note how the import changed from Profile to User and how I created a new user obj from obj.profile

    from django.contrib.auth.decorators import login_required
    from django.contrib.auth.models import User
    from django.shortcuts import render, get_object_or_404
    
    # Create your views here.
    
    @login_required
    def profile_detail(request, username=None):
        obj = get_object_or_404(User, username=username)
        user = obj.profile
        context = {
            "object": obj,
            "user": user,
        }
        template = 'profile_detail.html'
        return render(request, template, context)
    

    Many thanks for all the help!