Django serves zero byte response - python

This just happened to one of my sites and I have no idea what caused it.
This happens for any URL that is served by mod_wsgi for a particular application, which used to work fine.
Syntax errors in settings.py cause HTTP 500.
Syntax errors in urls.py don't influence anything—seems like this file is never loaded.
What is there to check?

The culprit was this line:
from django.contrib.auth.forms import AuthenticationForm
in middleware.py.
Moving the import into the function that uses AuthenticationForm solved the problem:
from django.http import HttpResponseRedirect
from django.conf import settings
from django.contrib import messages
from django.contrib.auth import login
#from django.contrib.auth.forms import AuthenticationForm <-- THE LINE WAS HERE
class LoginFormMiddleware(object):
def process_request(self, request):
if request.method == 'POST' and 'is_top_login_form' in request.POST:
from django.contrib.auth.forms import AuthenticationForm # <-- MOVED HERE
form = AuthenticationForm(data=request.POST)
is_valid = form.is_valid()
if is_valid:
login(request, form.get_user())
program = request.user.get_profile().first_intern.program
NavigationMiddleware.set_program(request, program)
return HttpResponseRedirect('%s?quick' % program.get_absolute_url())
else:
messages.error(request, request.POST['username'], extra_tags='login')
return HttpResponseRedirect(request.get_full_path())
I still have no idea why the code used to work, why it suddenly broke and why doing this solved the problem.
There has to be some magick in Python, after all.

Related

Django. ImportError: attempted relative import beyond top-level package

I'm a newbie. And I just started writing a django project. It is called the iRayProject and consists of two applications iRay_user_authentication and iRay_working_with_notes:
project structure here
iRay_user_authentication - this is a standard django app for registration
Here is his urls.py
from django.urls import path
from .views import login_user, registration
urlpatterns = [
path('', login_user, name='login_user'),
path('registration', registration, name='registration'),
]
In views.py registered user using redirect I want to send to the second application of the project
from django.shortcuts import render, redirect
from django.contrib.auth.forms import UserCreationForm, AuthenticationForm
from django.contrib.auth.models import User
from django.db import IntegrityError
from django.contrib.auth import login, logout, authenticate
from ..iRay_working_with_notes.views import list_notes
def login_user(request):
if request.method == 'GET':
return render(request, 'iRay_user_authentication/login.html', {'form': AuthenticationForm})
def registration(request):
if request.method == 'GET':
return render(request, 'iRay_user_authentication/registration.html', {'form': UserCreationForm})
else:
if '_guest' in request.POST:
pass
else:
if request.POST['password1'] == request.POST['password2']:
try:
user = User.objects.create_user(request.POST['username'], password=request.POST['password1'])
user.save()
login(request, user)
return redirect(list_notes)
except IntegrityError:
return render(request, 'iRay_user_authentication/registration.html', {'form': UserCreationForm,
'error': 'name is busy '
})
else:
return render(request, 'todo_app/registration.html', {'form': UserCreationForm,
'error': 'passwords not math'})
But when trying to import a function from the second views.py
from django.shortcuts import render
def list_notes(request):
return render(request, 'iRay_working_with_notes/list_notes.html')
I get an error:
ImportError: attempted relative import beyond top-level package
And I found a lot of theoretical information about why this error occurs.
But I still couldn 't figure out if there is an easy way for relative or absolute import , or I just didn 't structure my project correctly ??
import is wrong
from ..iRay_working_with_notes.views import list_notes
should be
from iRay_working_with_notes.views import list_notes
redirect needs view name from the urls-pattern:
redirect('name-of-my-view-pattern')
So please create a url-pattern entry for the list_notes view and give the pattern name as parameter to the redirect.
Why? because a redirect is telling the browser on the client side to load the target redirect page, so it needs an url (that is generated by django via the url-pattern), as the target page will be called from the browser.
Technically of course you can import a view and call it from another module directly as it is just a python function - but that is not a http redirect (and would not change the url in the browser to the redirected page) and additionally that is not really the idea of the django request/response architecture.

Stripe subscription cancel: KeyError 'HTTP_STRIPE_SIGNATURE'

I'm trying to configure Django Stripe Subscriptions for WebApp.
I want to let Subscribed users cancel the subscription themselves.
The code below is to delete user's information from StripeAPI and Django StripeCustomer model.
Here is view.py
import stripe
from django.conf import settings
from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import User
from django.http.response import JsonResponse, HttpResponse
from django.shortcuts import render
from django.views.decorators.csrf import csrf_exempt
from django.contrib.auth import get_user_model
from subscriptions.models import StripeCustomer
#login_required
#csrf_exempt
def cancel_subscription(request):
if request.user.is_authenticated:
endpoint_secret = settings.STRIPE_ENDPOINT_SECRET
payload = request.body
event = None
sig_header = request.META['HTTP_STRIPE_SIGNATURE']
event = stripe.Webhook.construct_event(
payload, sig_header, endpoint_secret
)
session = event['data']['object']
stripe_customer = StripeCustomer.objects.get(user=request.user)
stripe.api_key = settings.STRIPE_SECRET_KEY
sub_id = stripe.Subscription.retrieve(stripe_customer.stripeSubscriptionId)
client_reference_id = session.get('client_reference_id')
user = get_user_model().objects.get(id=client_reference_id)
try:
#delete from stripeapi
stripe.Subscription.delete(sub_id)
#delete from StripeCustomer model
StripeCustomer.objects.delete(
user=user,
stripeCustomerId=stripe_customer_id,
stripeSubscriptionId=stripe_subscription_id,
)
print(user.username + ' unsubscribed.')
except Exception as e:
import traceback
traceback.print_exc()
return JsonResponse({'error': (e.args[0])}, status =403)
return render(request, 'home.html')
When I excecute the code error occuerd at
sig_header = request.META['HTTP_STRIPE_SIGNATURE']
The error message is below
Exception Type: keyError
Exception Value: 'HTTP_STRIPE_SIGNATURE'
I don't understand why the error occurs at request.META['HTTP_STRIPE_SIGNATURE'],because other part of this view can execute this code.
I just mentioned the above settings in this question but still if more code is required then tell me I'll update my question with that information. Thank you
I think you're mixing up a webhook handler and a regular POST request route as part of your application here. You either need one or the other, and I suspect you don't need the webhook stuff at all given what you're trying to to.

django messages syntaxerror useing f string

i am trying to send a message to the user of my site when they register i used django message import but i did not work
here is my views.py code
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.http import HttpResponse
from django.shortcuts import render, redirect
from .models import cooking
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth import login, logout, authenticate
from django.contrib import messages
# Create your views here.
def homepage(request):
return render(request=request,template_name='main/home.html',context={"cooking": cooking.objects.all})
def register(request):
if request.method == "POST":
form = UserCreationForm(request.POST)
if form.is_valid():
user = form.save()
username = form.cleaned_data.get('username')
messages.succees(request, f"new account created: {username}")#error on this line
login(request, user)
return redirect("main:homepage")
else:
for msg in form.error_messages:
messages.error(request, form.error_messages[msg])
form = UserCreationForm
return render(request,"main/register.html",context={"form":form })
f-strings have been introduced in Python 3.6, you're probably using a previous version.
If you really wanted to use them you could install future-fstrings but I'm not sure it's worth.
A probably better solution would be to either upgrade Python to a version greather or equal to 3.6 or use one of the alternative formatting options:
"new account created: {}".format(username)
"new account created: %s" % username

Taking input in form and then comparing it with values stored in databse in django

I was working on a project where the user inputs the answer to the question and then the user input needs to be checked on clicking submit button. If input matches the answer stored in database in the admin portal then it should redirect it to a new page else it should give an error wrong answer.
What's happening is that for every user input i am redirected to the other page. But never shows Wrong Answer even if input other than that in database answer is entered. How do I tackle this?
forms.py
from django import forms
from .models import Answer
from django.core.exceptions import ObjectDoesNotExist
class CheckAnswer(forms.Form):
your_answer=forms.CharField(label='Answer')
def clean(self):
cleaned_data=super(CheckAnswer,self).clean()
response=cleaned_data.get("your_answer")
try:
p = Answer.objects.filter(answer__contains=response)
except Answer.DoesNotExist:
raise forms.ValidationError("Wrong Answer")
models.py
from django.db import models
from django.contrib.auth import get_user_model
User=get_user_model()
users=User.objects.all()
class Answer(models.Model):
name=models.CharField(max_length=10,unique=True)
answer=models.CharField(max_length=100)
def __str__(self):
return self.name
class Meta:
ordering= ["-name"]
views.py
from django.shortcuts import render,redirect
from django.views.generic import *
from . import models
from django import forms
from .forms import CheckAnswer
def Arena1(request):
if request.method=='POST':
form = CheckAnswer(request.POST)
if form.is_valid():
return redirect('thanks')
else:
form=CheckAnswer()
return render(request,'levels/arena1.html',{'form':form})
The Model Managers filter method does not raise DoesNotExist, you should use Answer.objects.get(answer__contains=response) to raise DoesNotExist, keep in mind that this can also return a MultipleObjectsReturned error if there is more than one answer matching your response, filter will just return an empty list.
The other option is to use Answer.objects.filter(answer__contains=response).exists() and check if it returns true or false.

How import and use csrf token in django 1.11?

Pease help use csrf token in django 1.11
in view.py i use follow code:
from django.shortcuts import render_to_response, redirect
from django.contrib import auth
from django.views.decorators.csrf import csrf
def login(request):
args = {}
args.update(csrf(request))
if request.POST:
username = request.POST.get('username', '')
password = request.POST.get('password', '')
user = auth.authenticate(username=username, password=password)
if user is not None:
auth.login(request, user)
return redirect('/')
else:
args['login_error'] = 'Пользователь не найден';
return render_to_response('login.html', args)
else:
return render_to_response('login.html', args)
but console display follow error message:
File "/home/kalinin/django/login/views.py", line 3, in from
django.views.decorators.csrf import csrf ImportError: cannot import
name 'csrf'
in django 1.8 i use similar code, but import csrf:
from django.core.context_processors import csrf
and applications is running without problems
Please help run my application for django 1.11
In Django 1.8 the template context processor was moved to django.template.context_processors.csrf, so the import would be:
from django.template.context_processors import csrf
However, you don't need to import it at all. Stop using render_to_response, it's obsolete. Use the render shortcut instead.
from django.shortcuts import render
return render(request, 'login.html', args)
When you use the render shortcut, then you don't need to worry about the csrf token in the view, and you can remove this line.
args.update(csrf(request))

Categories