0

У меня есть приложение django, которое использует Django Rest Framework.Сочетание обычных Django-представлений с Django Rest Framework View

Я пытаюсь создать пользователю сброса пароля потока с помощью формы на основе Django класса View. Для этого я определил URL, как:

url(r'^reset/confirm/(?P<uidb36>[0-9A-Za-z]+)-(?P<token>.+)/$', 
     views.PasswordResetConfirmView.as_view(), name='reset_confirm'), 
    url(r'^reset/$', views.ResetPasswordRequestView.as_view(), name='reset') 

Но проблема в том, что, когда я пытаюсь посетить URL сброса, он показывает следующее сообщение об ошибке.

Expected a `Response`, `HttpResponse` or `HttpStreamingResponse` to be returned from the view, but received a `<type 'NoneType'>` 

Я не уверен, разрешено ли смешивание представлений DRF и просмотров Django.

Что я делаю неправильно? Каким должен быть наилучший подход для создания потока сброса пароля с использованием только DRF.

Редактировать, код ResetPasswordRequestView

class ResetPasswordRequestView(FormView): 

    template_name = "users/password_reset_template.html" 
    form_class = PasswordResetRequestForm 
    success_url = "#" 

    @staticmethod 
    def validate_email_address(email): 
     try: 
      validate_email(email) 
      return True 
     except ValidationError: 
      return False 

      # default method to handle post requests 

    def post(self, request, *args, **kwargs): 
     form = self.form_class(request.POST) 
     if form.is_valid(): 
      email = form.cleaned_data['email'] 

     if self.validate_email_address(email) is True: 
      try: 
       user_profile = Profile.objects.get(email=email) 
      except Profile.DoesNotExist: 
       user_profile = None 
      if user_profile: 
       # send mail here 

       subject_template_name = 'registration/password_reset_subject.txt' 
       email_template_name = 'registration/password_reset_email.html' 

       subject = loader.render_to_string(subject_template_name, message) 

       # subject should not contain newlines 
       subject = ''.join(subject.splitlines()) 
       email = loader.render_to_string(email_template_name, message) 
       send_mail(subject, email, settings.DEFAULT_FROM_EMAIL, [user_profile.email], fail_silently=False) 
       result = self.form_valid(form) 
       messages.success(request, 'Email has been sent to ' + email + 
           "'s email address. Please check its inbox to " 
           "continue resetting password.") 
       return result 
      result = self.form_invalid(form) 
      messages.error(request, 'This username does not exist in the system.') 
      return result 
     messages.error(request, 'Invalid Input') 
     return self.form_invalid(form) 

Код для PasswordResetConfirmView

class PasswordResetConfirmView(FormView): 
    template_name = 'users/change_password.html' 
    success_url = "/" 
    form_class = ChangePasswordForm 

    def post(self, request, uidb64=None, token=None, *args, **kwargs): 
     form = self.form_class(request.POST) 
     assert uidb64 is not None and token is not None 
     try: 
      uid = urlsafe_base64_decode(uidb64) 
      user_profile = Profile.objects.get(pk=uid) 
     except (TypeError, ValueError, OverflowError, Profile.DoesNotExist): 
      user_profile = None 

     if user_profile is not None and default_token_generator.check_token(user_profile, token): 
      if form.is_valid(): 
       new_password = form.cleaned_data['password'] 
       user_profile.set_password(new_password) 
       user_profile.save() 
       messages.success(request, 'Password has been reset.') 
       return self.form_valid(form) 
      else: 
       messages.error(request, 'Password reset has not been unsuccessful.') 
       return self.form_invalid(form) 
     else: 
      messages.error(request, 'The reset password link is no longer valid.') 
      return self.form_invalid(form) 

StackTrace показывает следующее, изменили путь питона здесь (это правильно на моем компьютере)

Traceback: 
File "/[base path here]/local/lib/python2.7/site-packages/django/core/handlers/base.py" in get_response 
    132.      response = wrapped_callback(request, *callback_args, **callback_kwargs) 
File "/[base path here]/local/lib/python2.7/site-packages/django/views/decorators/csrf.py" in wrapped_view 
    58.   return view_func(*args, **kwargs) 
File "/[base path here]/local/lib/python2.7/site-packages/django/views/generic/base.py" in view 
    71.    return self.dispatch(request, *args, **kwargs) 
File "/[base path here]/local/lib/python2.7/site-packages/rest_framework/views.py" in dispatch 
    468.   self.response = self.finalize_response(request, response, *args, **kwargs) 
File "/[base path here]/local/lib/python2.7/site-packages/rest_framework/views.py" in finalize_response 
    396.    % type(response) 

Exception Type: AssertionError at /user/reset/ 
Exception Value: Expected a `Response`, `HttpResponse` or `HttpStreamingResponse` to be returned from the view, but received a `<type 'NoneType'>` 

urls.py

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

urlpatterns = [ 
    url(r'^signup/$', views.register), 
    url(r'^check-username/$', views.check_username), 
    url(r'^change-password/$', views.change_password), 
    url(r'^interests/$', views.get_all_interests), 
    url(r'^signin/$', 'rest_framework_jwt.views.obtain_jwt_token'), 
    url(r'^verify-token/$', 'rest_framework_jwt.views.verify_jwt_token'), 
    url(r'^(?P<user_id>[0-9]{1,6})/$', views.generate_feed), 
    url(r'^community/(?P<community_id>[0-9]{1,6})/' 
     r'(?P<user_id>[0-9]{1,6})/$', views.community_feed), 
    url(r'^(?P<username>[A-Za-z_\.]{1,20})/$', views.user_profile), 
    # url's for reset password 
    url(r'^reset/confirm/(?P<uidb36>[0-9A-Za-z]+)-(?P<token>.+)/$', 
     views.PasswordResetConfirmView.as_view(), name='reset_confirm'), 
    url(r'^reset/$', views.ResetPasswordRequestView.as_view(), name='reset'), 
] 

Редактировать: Он отлично работает, когда я устанавливаю URL-адреса перезагрузки перед другими URL-адресами, но до сих пор не знаю, как и почему?

+0

Проблема заключается в коде для 'views.ResetPasswordRequestView'. Можете ли вы опубликовать этот класс? – joerick

+0

@joerick добавлен код просмотра – ofnowhere

+0

@ofnowhereland Миксин двух «парадигм» полностью разрешен и действителен! –

ответ

0

Если вы посмотрите на трассировку стека, вы увидите, что ошибка возникает в коде Django Rest Framework. Этого не должно быть, потому что вы django.views.generic.FormView не имеет ничего общего с DRF, поэтому rest_framework.views.dispatch никогда не должен называться.

Весь код, который вы отправили, выглядит хорошо, проблема должна быть в другом месте. Я предполагаю, что что-то не так с urls.py, но это действительно просто догадка. В качестве первого шага я бы удостоверился, что правильный шаблон URL совпадает.

Обновление:

Регулярное выражение r'^(?P<username>[A-Za-z_\.]{1,20})/$' в шаблоне URL для views.user_profile матчей 'reset/'. Средство распознавания URL использует первый шаблон URL, который соответствует, поэтому вам нужно поместить шаблон URL для reset дальше в списке.

+0

Спасибо, проблема была в urls.py. Если место, в котором происходит сброс URL-адресов в начале он работает нормально, но я до сих пор не знаю почему. – ofnowhere

+0

@ofnowhereland, если мой ответ решает вашу проблему, было бы здорово, если бы вы могли принять его. Благодаря! –

+0

Я все еще искал причину. – ofnowhere