I am using Django-registration-email in my Django project. In there documentation (Django-Registration-Email), I am instructed to add REGISTRATION_EMAIL_REGISTER_SUCCESS_URL in the settings.py. However, this is causing the type error:
'str' object is not callable
In the settings.py, I set the redirect url as such:
REGISTRATION_EMAIL_REGISTER_SUCCESS_URL = '/accounts/register/complete/'
And the the url is copied as such:
url(
r'^accounts/register/$',
RegistrationView.as_view(
template_name='registration/registration_form.html',
form_class=CustomEmailRegistrationForm,
get_success_url=getattr(
settings,'REGISTRATION_EMAIL_REGISTER_SUCCESS_URL',
lambda request, user:'/'),
),
name='registration_register',
),
And the debug information told me that the first error comes from /local/lib/python2.7/site-packages/registration/views.py in form_valid
The indicated error line is
success_url = self.get_success_url(request, new_user)
The whole block is
def form_valid(self, request, form):
new_user = self.register(request, **form.cleaned_data)
success_url = self.get_success_url(request, new_user)
# success_url may be a simple string, or a tuple providing the
# full argument set for redirect(). Attempting to unpack it
# tells us which one it is.
try:
to, args, kwargs = success_url
return redirect(to, *args, **kwargs)
except ValueError:
return redirect(success_url)
The traceback is:
Traceback:
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/core/handlers/base.py" in get_response
114. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/views/generic/base.py" in view
69. return self.dispatch(request, *args, **kwargs)
File "/Library/Python/2.7/site-packages/registration/views.py" in dispatch
79. return super(RegistrationView, self).dispatch(request, *args, **kwargs)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/views/generic/base.py" in dispatch
87. return handler(request, *args, **kwargs)
File "/Library/Python/2.7/site-packages/registration/views.py" in post
35. return self.form_valid(request, form)
File "/Library/Python/2.7/site-packages/registration/views.py" in form_valid
83. success_url = self.get_success_url(request, new_user)
Exception Type: TypeError at /accounts/register/
Exception Value: 'str' object is not callable
Can anyone help me to solve this issue? Thanks a lot! I am stuck by this problem for one whole day!
OK, when you use
get_success_url=getattr(
settings,'REGISTRATION_EMAIL_REGISTER_SUCCESS_URL',
lambda request, user:'/'),
)
in your url handler, you are setting get_success_url as a string. You are then calling it in form_valid, as a function, trying to pass it variables.
Finally, I find where is the problem: REGISTRATION_EMAIL_REGISTER_SUCCESS_URL is expecting a function rather than a string
So, I should add an one-line function in the settings.py
REGISTRATION_EMAIL_REGISTER_SUCCESS_URL = lambda request, user: '/activate/complete/'
Anyway, I still would like to move to allauth since django-registration-email is no longer maintained.
Related
In the webapp, to retrieve all the objects from a specific user I am using user pk. But to make url more readable I want to use username. The problem is in the django view, user pk in kwargs giving the correct values, but when I use username it shows error.
Here are my codes using 'username' as kwargs, that is returning keyerror,
views.py
class UserAllQuestionView(generic.ListView):
model = Question
template_name = 'mechinpy/user_profile_question.html'
context_object_name = 'user_all_questions'
def get_queryset(self):
return Question.objects.filter(user=self.kwargs['username'])
urls.py
path('m/user/<str:slug>/questions/', views.UserAllQuestionView.as_view(), name='user_profile_question_all'),
html
All User Questions
Traceback:
File "C:\Users\Bidhan\AppData\Local\Programs\Python\Python35\lib\site-packages\django\core\handlers\exception.py" in inner
34. response = get_response(request)
File "C:\Users\Bidhan\AppData\Local\Programs\Python\Python35\lib\site-packages\django\core\handlers\base.py" in _get_response
126. response = self.process_exception_by_middleware(e, request)
File "C:\Users\Bidhan\AppData\Local\Programs\Python\Python35\lib\site-packages\django\core\handlers\base.py" in _get_response
124. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\Users\Bidhan\AppData\Local\Programs\Python\Python35\lib\site-packages\django\views\generic\base.py" in view
68. return self.dispatch(request, *args, **kwargs)
File "C:\Users\Bidhan\AppData\Local\Programs\Python\Python35\lib\site-packages\django\views\generic\base.py" in dispatch
88. return handler(request, *args, **kwargs)
File "C:\Users\Bidhan\AppData\Local\Programs\Python\Python35\lib\site-packages\django\views\generic\list.py" in get
142. self.object_list = self.get_queryset()
File "C:\Users\Bidhan\Desktop\Startup\mysite\mechinpy\views.py" in get_queryset
454. return Question.objects.filter(user=self.kwargs['username'])
Exception Type: KeyError at /m/user/bidhan/questions/
Exception Value: 'username'
Mismatch in URL parameter names
Given I understand your question correctly, you pass the username as a slug to the view, like:
path(
'm/user/<str:slug>/questions/',
views.UserAllQuestionView.as_view(),
name='user_profile_question_all'
),
You name this parameter slug however, but in your view, you call self.kwargs['username']. You thus need to change one of the two. For example:
path(
'm/user/<str:username>/questions/',
views.UserAllQuestionView.as_view(),
name='user_profile_question_all'
),
Furthermore it will probably still not work. If I understand it correctly, your Question class has a ForeignKey to the User model. A User is not the same as its textual representation (for example by means of a username), so the filter will look like:
class UserAllQuestionView(generic.ListView):
model = Question
template_name = 'mechinpy/user_profile_question.html'
context_object_name = 'user_all_questions'
def get_queryset(self):
return Question.objects.filter(user__username=self.kwargs['username'])
Using the user_id instead
That being said, it might be better to user the id of the User instead, which will likely introduce less confusion (for example what if a user manages to use a username with a slash in it, then the URL will no longer work). So a more safe approach might be:
path(
'm/user/<int:userid>/questions/',
views.UserAllQuestionView.as_view(),
name='user_profile_question_all'
),
class UserAllQuestionView(generic.ListView):
model = Question
template_name = 'mechinpy/user_profile_question.html'
context_object_name = 'user_all_questions'
def get_queryset(self):
return Question.objects.filter(user_id=self.kwargs['userid'])
and in the template write it like:
All User Questions
i am trying to use django reverse to route back to a page which take an argument vendor_id.
I am trying to do it this way using this post as reference: POST
return HttpResponseRedirect(reverse('vendor_data', kwargs={'vendor_id':vendor_id}))
My view method which should be called:
def vendorData(request):
vendors = Vendors()
if request.method == 'GET':
vendor_id = request.GET.get('vendor_id')
if vendors.checkValidVendorId(vendor_id) == False:
return HttpResponse('<h2>404<br>Invalid Vendor Id.</h2>')
else:
vendor_details = vendors.getVendorData(vendor_id)
.....
return render(request, 'vendor_data.html', context_dict)
my urls.py:
url(r'^vendor_data/', views.vendorData, name='vendor_data'),
If i dont pass any argument then it shows the HttpResponse from my views method.
If i pass argument vendor_id like this:
return HttpResponseRedirect(reverse('vendor_data', kwargs={'vendor_id':vendor_id}))
It throws an error. The traceback is:
Traceback:
File "C:\Python27\lib\site-packages\django\core\handlers\base.py" in get_response
132. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\Users\Manish\Desktop\ScratcherAdmin\ScratcherAdmin\vendors\views.py" in editVendorData
162. return HttpResponseRedirect(reverse('vendor_data', kwargs={'vendor_id':vendor_id}))
File "C:\Python27\lib\site-packages\django\core\urlresolvers.py" in reverse
579. return force_text(iri_to_uri(resolver._reverse_with_prefix(view, prefix, *args, **kwargs)))
File "C:\Python27\lib\site-packages\django\core\urlresolvers.py" in _reverse_with_prefix
496. (lookup_view_s, args, kwargs, len(patterns), patterns))
Exception Type: NoReverseMatch at /update_vendor_data/
Exception Value: Reverse for 'vendor_data' with arguments '()' and keyword arguments '{'vendor_id': u'20150001'}' not found. 1 pattern(s) tried: ['vendor_data/']
How to solve this?
What you are expecting inside your view is a GET parameter from query string. Something your expected URL should be something like,
www.example.com/vendor/?vendor_id=12345
And below,
return HttpResponseRedirect(reverse('vendor_data', kwargs={'vendor_id':vendor_id}))
will redirect you to something like,
www.example.com/vendor/12345
For which your view should expect an additional parameter vendor_id,
def vendorData(request, vendor_id):
and accordingly your rest of the code might change.
Solution to your problem:
return HttpResponseRedirect("{}?vendor_id={}".format(reverse('vendor_data'), vendor_id))
I am configuring an app that operates subscriptions only with emails, all runs perfectly except a part of my form that should encode all email received.
This is the error obtained when i sign up with an email:
**Unicode-objects must be encoded before hashing**
Traceback: File "/home/draicore/SUNFLOWER/AMBIENTE1/lib/python3.4/site-packages/django/core/handlers/base.py" in get_response
132. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/draicore/SUNFLOWER/AMBIENTE1/lib/python3.4/site-packages/django/views/generic/base.py" in view
71. return self.dispatch(request, *args, **kwargs)
File "/home/draicore/SUNFLOWER/AMBIENTE1/lib/python3.4/site-packages/django/views/generic/base.py" in dispatch
89. return handler(request, *args, **kwargs)
File "/home/draicore/SUNFLOWER/AMBIENTE1/lib/python3.4/site-packages/django/views/generic/edit.py" in post
214. if form.is_valid():
File "/home/draicore/SUNFLOWER/AMBIENTE1/lib/python3.4/site-packages/django/forms/forms.py" in is_valid
184. return self.is_bound and not self.errors
File "/home/draicore/SUNFLOWER/AMBIENTE1/lib/python3.4/site-packages/django/forms/forms.py" in errors
176. self.full_clean()
File "/home/draicore/SUNFLOWER/AMBIENTE1/lib/python3.4/site-packages/django/forms/forms.py" in full_clean
393. self._clean_form()
File "/home/draicore/SUNFLOWER/AMBIENTE1/lib/python3.4/site-packages/django/forms/forms.py" in _clean_form
417. cleaned_data = self.clean()
File "/home/draicore/SUNFLOWER/GIRASOL/apps/newsletter/forms.py" in clean
47. self.cleaned_data['activation_key'] = generate_activation_key(data['email'])
File "/home/draicore/SUNFLOWER/GIRASOL/apps/newsletter/forms.py" in generate_activation_key
16. salt = hashlib.md5(str(random.random())).hexdigest()[:10]
Exception Type: TypeError at /request/
Exception Value: Unicode-objects must be encoded before hashing
I have this code that is responsible of encoding emails on my forms.py:
def generate_activation_key(email):
if isinstance(email, str):
email = email.encode('utf-8')
salt = hashlib.md5(str(random.random()).encode('utf-8')).hexdigest()[:10]
return hashlib.md5(salt+email).hexdigest()
class EmailSubscriberForm(forms.ModelForm):
email = forms.EmailField(max_length=256, label=_('Email'), required=True)
captcha = CaptchaField(label=_('Security code'))
activation_key = forms.CharField(widget=forms.HiddenInput(), required=False)
activation_request_sent_at = forms.DateField(widget=forms.HiddenInput(), required=False)
class Meta:
model = EmailSubscriber
fields = (
'email',
'activation_key',
'activation_request_sent_at',
)
def clean_email(self):
email = self.cleaned_data['email'].strip()
try:
self.instance = EmailSubscriber.objects.get(email__iexact=email)
if self.instance is not None:
return email.lower()
except EmailSubscriber.DoesNotExist:
return email.lower()
raise forms.ValidationError(_('This email is already subscribed.'))
def clean(self):
data = self.cleaned_data
if 'email' in data:
self.cleaned_data['activation_key'] = generate_activation_key(data['email'])
self.cleaned_data['activation_request_sent_at'] = timezone.now()
return self.cleaned_data
I believe that this issue is caused for an incompatibility of version of python (i have Python 3.4.1) and i was trying to looking for solutions here in other questions and i found answers that say about a new format to set the .encode('utf-8'). and I dont know what i should change.
apologizeme in advance if I overlook something. Any contribution is wellcome, Thanks for evaluate!
Have a great day!!
You should also encode your random salt string:
str(random.random()).encode('utf-8')
However, then you'll receive a new error...because email is bytes and salt is a string. I'll leave it up to you to determine how you want to normalize these so that they can be added together.
I'm using django-rest-auth for user signup and verify email.
I'm able to successfully send the email when a user signs up. Howvever, on email verification, I'm getting this error with the following traceback:
File "/Library/Python/2.7/site-packages/django/core/handlers/base.py" in get_response
111. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/Library/Python/2.7/site-packages/django/views/generic/base.py" in view
69. return self.dispatch(request, *args, **kwargs)
File "/Library/Python/2.7/site-packages/django/views/generic/base.py" in dispatch
87. return handler(request, *args, **kwargs)
File "/Library/Python/2.7/site-packages/django/views/generic/base.py" in get
155. return self.render_to_response(context)
File "/Library/Python/2.7/site-packages/django/views/generic/base.py" in render_to_response
130. template=self.get_template_names(),
File "/Library/Python/2.7/site-packages/django/views/generic/base.py" in get_template_names
142. "TemplateResponseMixin requires either a definition of "
Exception Type: ImproperlyConfigured at /rest-auth/registration/account-confirm-email/vjohhnrf6xpkmn1jxbzaopdn0g79tdyofumeeuyuehcuja8slyz7nzq1idyifcqk/
Exception Value: TemplateResponseMixin requires either a definition of 'template_name' or an implementation of 'get_template_names()'
Any idea on how to fix this ?
While Ricardo's answer is correct, it didn't do much to help me solve my problem. This is what I needed to do for my master urls.py:
from allauth.account.views import confirm_email
.....
url(r'^accounts-rest/registration/account-confirm-email/(?P<key>.+)/$', confirm_email, name='account_confirm_email'),
Make sure that the beginning of the url spec starts with whatever path you are using for allauth REST calls.
Of course, the above is for using the built-in view handling the confirmation.
When you use confirmation email you have two ways to do it.
Using the specified by the API or creating yours. By default it uses django-allauth and a TemplateView on reverse can be used.
If you create yours, you may have to override account_confirm_email and then post to verification_mail.
In urls.py it is defined just reverse so, depending on what you are trying to do you will have first to create your own account_confirm_email, get the required key and post it to verify-email. Here there is more information about this bug.
For the new Django versions re_path url resolver method works properly with this (?P.+) url regex.
from django.urls import re_path
re_path('rest-auth/registration/account-confirm-email/(?P<key>.+)/', CustomConfirmEmailView.as_view(), name='account_confirm_email')
Also I have customized allauth ConfirmEmailView get() method in order to redirect properly
from allauth.account.views import ConfirmEmailView
from django.contrib.auth import get_user_model
class CustomConfirmEmailView(ConfirmEmailView):
def get(self, *args, **kwargs):
try:
self.object = self.get_object()
except Http404:
self.object = None
user = get_user_model().objects.get(email=self.object.email_address.email)
redirect_url = reverse('user', args=(user.id,))
return redirect(redirect_url)
I also have the problem as I read the tutorialHere is the link ,it shows the problem as TemplateResponseMixin requires either a definition of 'template_name' or an implementation of 'get_template_names()'
solution:
I change the location of templates filer and change the templates in the setting.py
1. In the App_Name file,I add the New folder Named:templates
2. In the settings.py: TEMPLATES = [{'DIRS': [BASE_DIR+"/templates",],}]
I am currently playing around with REST and backbone.js and ran into this issue:
'LoginView' object has no attribute 'COOKIES'
Here comes the following code for might have caused the problem. I have commented out a few things in the javascript, since I wanted it to load directly to the server instead, but I thought it would be just as good to bring it along.
I can also add that I have checked for the csrf-token in the form and it is there.
views.py
class LoginView(TemplateView):
authentication_form=LoginForm
form_class = LoginForm
redirect_field_name=REDIRECT_FIELD_NAME
template_name = 'front/login.html'
initial = {'key': 'value'}
def get(self, request, *args, **kwargs):
form = self.form_class(initial=self.initial)
return render(request, self.template_name, {'form': form})
#method_decorator(sensitive_post_parameters())
#csrf_protect
#never_cache
#api_view(['GET', 'POST'])
def post(self, request, *args, **kwargs):
form = self.form_class(request.POST)
print request.COOKIES('csrftoken')
print request.POST.get('csrfmiddlewaretoken')
if form.is_valid():
#if not is_safe_url(url=redirect_to, host=request.get_host()):
# redirect_to = resolve_url(settings.LOGIN_REDIRECT_URL)
print request.POST.get('email')
#user = self.get_user(request.POST.get('email'))
#print user
#auth = UserDataAuthentication(request, user)
user = authenticate(email=request.POST.get('email'), password=request.POST.get('password'))
if user is not None:
auth_login(request, user)
return Response(user, status=status.HTTP_201_CREATED)
return HttpResponseRedirect('/login/')
login.js
var csrftoken = $('meta[name="csrf-token"]').attr('content');
SigninView = Backbone.View.extend({
events: {
//"click button[type=submit]": "sendRequest"
},
sendRequest: function( event ){
//event.preventDefault();
var csrftoken = $.cookie('csrftoken');
var url = '/login/validate/';
var email = $("#id_email").val();
var password = $("#id_password").val();
var items = {
email: email,
password: password,
csrfmiddlewaretoken: csrftoken
};
console.log(csrftoken);
$.ajax({
url:url,
type:'POST',
dataType:"json",
data: items,
success: function (data) {
var json = $.parseJSON(data);
console.log(data);
},
error: function (xhr, textStatus, error) {
$("#form_error").css('padding','7px').css('border-radius','4px').html('Error recieved: ' + error).fadeIn();
console.log("Status: "+textStatus);
console.log("Type: "+error);
}
});
}
});
var signin_view = new SigninView({
el: $("#login_form")
});
We are two people working on this, I have taken upon myself to work with Python, while my friend takes care of the js-part. I have yet to experience enough of Django to actually find what might have caused an error to arise due to cookies. I try, most of the time, to stay away from cookies, if I can, but it seems difficult here.
And of course: The traceback:
Traceback:
File "/home/ryuu/Programming/Python/tabr/venv/local/lib/python2.7/site-packages/django/core/handlers/base.py" in get_response
114. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/ryuu/Programming/Python/tabr/venv/local/lib/python2.7/site-packages/django/views/generic/base.py" in view
69. return self.dispatch(request, *args, **kwargs)
File "/home/ryuu/Programming/Python/tabr/venv/local/lib/python2.7/site-packages/django/views/generic/base.py" in dispatch
87. return handler(request, *args, **kwargs)
File "/home/ryuu/Programming/Python/tabr/venv/local/lib/python2.7/site-packages/django/utils/decorators.py" in _wrapper
29. return bound_func(*args, **kwargs)
File "/home/ryuu/Programming/Python/tabr/venv/local/lib/python2.7/site-packages/django/views/decorators/debug.py" in sensitive_post_parameters_wrapper
75. return view(request, *args, **kwargs)
File "/home/ryuu/Programming/Python/tabr/venv/local/lib/python2.7/site-packages/django/utils/decorators.py" in bound_func
25. return func(self, *args2, **kwargs2)
File "/home/ryuu/Programming/Python/tabr/venv/local/lib/python2.7/site-packages/django/utils/decorators.py" in _wrapped_view
95. result = middleware.process_view(request, view_func, args, kwargs)
File "/home/ryuu/Programming/Python/tabr/venv/local/lib/python2.7/site-packages/django/middleware/csrf.py" in process_view
111. request.COOKIES[settings.CSRF_COOKIE_NAME])
Exception Type: AttributeError at /login/validate/
Exception Value: 'LoginView' object has no attribute 'COOKIES'
You used functions decorators on a method.
This won't work: the function as returned by the decorator expects its first argument to be a request, and receives self instead.
Use:
from django.utils.decorators import method_decorator
csrf_protected_method = method_decorator(csrf_protect)
# and so on
Check the documentation for more details.