Object of type date is not JSON serializable (error in tests.py) - django-4.0

I wrote this view to register with the user's phone and the view itself works fine
But in test def test_signup_phone_post (self)
For response = self.client.post (reverse ('signup_phone'), self.user, follow = True)
This gives the error: TypeError: Object of type date is not JSON serializable
views.py
class SignupPhoneView(View):
def get(self, request):
form = SignupPhoneForm()
return render(request, 'user/signup_phone.html', {'form': form})
def post(self, request):
form = SignupPhoneForm(request.POST)
if User.objects.filter(username=request.POST.get("username") + "#mail.com"): # If username already exists
logger_warn.warning(f'class SignupPhoneView, {request.POST.get("username")}, Registration exists')
return redirect("/user/signup-phone/", messages.error(request, "Registration exists"))
elif form.is_valid():
token = random.randint(100000, 999999)
kave_negar_token_send(form.cleaned_data['recovery_phone'], token)
code = OtpCode.objects.create(phone_number=form.cleaned_data['recovery_phone'], code=token)
print(code)
request.session['signup_info'] = {
'username': form.cleaned_data['username'],
'password': form.cleaned_data['password'],
'first_name': form.cleaned_data['first_name'],
'last_name': form.cleaned_data['last_name'],
'birthday': form.cleaned_data['birthday'],
'gender': form.cleaned_data['gender'],
'country': form.cleaned_data['country'],
'recovery_phone': form.cleaned_data['recovery_phone']
}
messages.success(request, f'{request.POST.get("username")} please enter your verification code')
return redirect("/user/phone-verify/")
else:
logger_error.error(f'class SignupEmailView, {request.POST.get("username")}, Registration failed')
messages.error(request, "Registration failed")
return redirect("/user/signup-phone/")
tests.py
class SignupPhoneTest(TestCase):
def setUp(self):
self.user = {
'username': 'testuser',
'password': '7895146',
'recovery_phone': '09874563215',
'first_name': 'lina',
'last_name': 'wong',
'birthday': '01/10/2000',
'gender': 'f',
'country': 'England'
}
def test_signup_phone_page_url(self):
response = self.client.get("/user/signup-phone/")
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, template_name='user/signup_phone.html')
def test_signup_phone_post(self):
response = self.client.post(reverse('signup_phone'), self.user, follow=True)
self.assertEqual(response.status_code, 200)
self.assertEqual(response.redirect_chain, [(reverse('phone_verify'), 302)])

Related

The view system.views.Login didn't return an HttpResponse object. It returned None instead

I'm newbie to Django. I'm stuck at one thing that, valueError at /login/. I've tried my best to search and try to solve this but i didn't find my problem solution. In Following First Code Sample From Which I Got Error,
class Login(View):
template = 'login.html'
form = forms.LoginForm
def get(self, request):
if request.user.is_authenticated:
username = request.user
stud = Stud.objects.filter(adm=username).exists()
cord = Cord.objects.filter(staff_no=username).exists()
if stud:
return redirect('appStatus')
elif cord:
return redirect('cordIndex')
else:
return redirect('admin')
else:
form = self.form(None)
return render(request, self.template, {'form': form})
def post(self, request):
form = self.form(request.POST)
username = request.POST['username']
password = request.POST['password']
user = authenticate(request, username=username, password=password)
if user is not None:
login(request, user)
stud = Stud.objects.filter(adm=username).exists()
cord = Cord.objects.filter(staff_no=username).exists()
adv = adv.objects.filter(staff_no=username).exists()
if stud:
return redirect('studIndex')
elif cord:
return redirect('cordIndex')
elif adv:
return redirect('advIndex')
else:
context ={
'form': self.form(request.POST),
'errors': 'Either username or password is wrong'
}
return render(request, self.template, context)
Error traced from terminal:
ValueError: The view system.views.Login didn't return an HttpResponse object. It returned None instead.

Cannot resolve keyword

I recevied an error when I request any page in the blog project I am working on, and I have no idea what is going wrong. Please help!
views.py
def post(request, id):
post = get_object_or_404(Post, id=id)
PostView.objects.get_or_create(user=request.user, post=post)
form = CommentForm(request.POST or None)
if request.method == "POST":
if form.is_valid():
form.instance.user = request.user
form.instance.post = post
form.save()
return redirect(reverse("post-detail", kwargs={
'id': post.id
}))
context = {
'post': post,
'form': form,
}
return render(request, 'post.html', context)
here is the model.py:
class Post(models.Model):
title = models.CharField(max_length=50)
overview = models.TextField()
timestamp = models.DateTimeField(auto_now_add=True)
content = HTMLField()
author = models.ForeignKey(Author, on_delete=models.CASCADE)
#thumbanail = models.ImageField()
#comment_count = models.IntegerField(default= 0)
#view_count = models.IntegerField(default= 0)
categories = models.ManyToManyField(Category)
featured = models.BooleanField()
def get_absolute_url(self):
return reverse('post-detail', kwargs={
'id': self.id
})
def get_update_url(self):
return reverse('post-update', kwargs={
'id': self.id
})
def get_delete_url(self):
return reverse('post-delete', kwargs={
'id': self.id
})
class Meta:
verbose_name_plural = 'Posts'
def __str__(self):
return f'{self.title}'
#property
def get_comments(self):
return self.comments.all().order_by('-timestamp')
#property
def comment_count(self):
return Comment.objects.filter(post=self).count()
#property
def view_count(self):
return PostView.objects.filter(post=self).count()
This is the I am receiving:
FieldError at /
Cannot resolve keyword 'comment_count' into field. Choices are: author, author_id, categories, comments, content, featured, id, overview, postview, timestamp, title
*
Like Hisahm__Pak said
remove #comment_count = models.IntegerField(default= 0)
comment_count = models.IntegerField(default= 0)
then save and make migrations
python manage.py makemigrations
python manage.py migrate
then run the server
python manage.py runserver

How to Pass an Image File to a API Endpoint

I have a web services with DRF, I have POSTMAN passing the right all fields right with success including the image file ['avatar']
[]1
Now how do i pass the image file from a Django Form, but i keep getting Error 400, Bad request. Please how do i encode the image file to be passed into the API endpoint .
html
<form method="post" action="#" enctype="multipart/form-data">
{% csrf_token %}
<label for="phone">Enter Phone</label>
{{ form.phone }} <br />
<label for="bvn">Enter BVN</label>
{{ form.bvn }} <br />
<label for="avatar">Upload Avatar</label>
{{ form.avatar }} <br />
<button type="submit" class="btn btn-primary" >Submit</button>
</form>
views.py
def form_valid(self, form):
token = self.request.session['session_token']
headers = {"Content-Type": 'application/json', "Authorization": "Token " + token}
parameters = {
'bvn': form.cleaned_data['bvn'],
'phone': form.cleaned_data['phone'],
'avatar': self.request.FILES['avatar']
}
response = requests.put(str(settings.API_END_POINT + '/customer_profile_api/'), data=parameters,
headers=headers)
if response.status_code in settings.SUCCESS_CODES:
messages.success(self.request, 'Successfully updated profile')
else:
messages.error(self.request, 'API Error %s' % response.status_code)
return super(CustomerDashboard, self).form_valid(form)
form.py
class ProfileUpdateForm(forms.Form):
"""customer profile update form"""
phone = forms.CharField(required=False, widget=NumberInput(attrs={'class': 'form-control',
'type': 'number', 'id': 'phone',
'placeholder': 'Enter Phone Number'}))
bvn = forms.CharField(required=False, widget=NumberInput(attrs={'class': 'form-control',
'type': 'number', 'id': 'bvn',
'placeholder': 'Enter BVN'}))
avatar = forms.ImageField(required=False, widget=ClearableFileInput(attrs={'class': 'form-control',
'type': 'file', 'id': 'avatar',
'placeholder': 'Upload Avatar'}))
Yours headers is wrong.
headers = {"Content-Type": 'application/json', "Authorization": "Token " + token}
change to:
headers = {"Content-Type": 'multipart/form-data', "Authorization": "Token " + token}
When you upload some file you should use multipart/form-data instead of application/json
(If you certainly do not send the file as base64)
Should someone else run into the same issue, The only way i was able to solve it is to have separate views to handle image and other text fields. What i did so far that worked.
If you noticed, the content-type header for the view that handles the image wasnt inserted, Just remove it and let it your API handle it by itself, several times i set it as multipart/form-data, i will hit response code 200/201, but file never get saved.
my API views.py
class CustomerApiView(generics.UpdateAPIView, generics.ListAPIView):
"""Customer Api View to update customer profile"""
http_method_names = ['put', 'get']
renderer_classes = [renderers.JSONRenderer]
authentication_classes = [authentication.TokenAuthentication]
serializer_class = CustomerSerializer
queryset = Profile.objects.all()
permission_classes = [IsAuthenticated]
def get_queryset(self):
user = self.request.user
return self.queryset.filter(user=user)
def get_object(self):
queryset = self.filter_queryset(self.get_queryset())
# make sure to catch 404's below
obj = queryset.get(user_id=self.request.user.id)
self.check_object_permissions(self.request, obj)
return obj
class CustomerAvatarApiView(generics.UpdateAPIView):
"""Customer Avatar/DP API View"""
serializer_class = CustomerAvatarSerializer
queryset = Profile.objects.all()
authentication_classes = [authentication.TokenAuthentication]
permission_classes = [IsAuthenticated]
renderer_classes = [renderers.JSONRenderer]
http_method_names = ['put', 'get']
def get_object(self):
queryset = self.filter_queryset(self.get_queryset())
# make sure to catch 404's below
obj = queryset.get(user_id=self.request.user.id)
self.check_object_permissions(self.request, obj)
return obj
serializer.py
class CustomerSerializer(serializers.ModelSerializer):
"""Customer Profile Serializer"""
class Meta:
"""Class Meta"""
model = Profile
fields = ('pk', 'phone', 'bvn', 'avatar')
extra_kwargs = {'pk': {'read_only': True}, }
class CustomerAvatarSerializer(serializers.ModelSerializer):
"""Separate Serializer to handle upload of file"""
class Meta:
"""Class Meta"""
model = Profile
fields = ('avatar', )
my view.py
class CustomerDashboard(LoginRequiredMixin, generic.FormView):
"""customer dashboard view"""
template_name = 'customer/dashboard.html'
form_class = ProfileUpdateForm
raise_exception = False
success_url = reverse_lazy('customer_dashboard')
def get_profile_api(self):
"""get profile api call to fetch profile; passing in the token from session"""
token = self.request.session['session_token']
headers = {"Content-Type": 'application/json', "Authorization": "Token " + token}
response = requests.get(str(settings.API_END_POINT + '/customer_profile_api/'), headers=headers)
json_response = response.json()
return json_response
def get_initial(self):
initial = ''
try:
initial = super(CustomerDashboard, self).get_initial()
initial['phone'] = self.get_profile_api()[0]['phone']
initial['bvn'] = self.get_profile_api()[0]['bvn']
except:
pass
return initial
def get_context_data(self, **kwargs):
"""overriding get_context_data to pass data to template"""
context = super(CustomerDashboard, self).get_context_data()
if self.get_profile_api()[0]['bvn'] != '': # if BVN has been filled before pass True or False to template
context['bvn_initial'] = True # Todo Validate BVN from API Before calling save method on it
else:
context['bvn_initial'] = False
return context
def form_valid(self, form):
token = self.request.session['session_token']
if 'updateAvatar' in self.request.POST:
headers = {"Authorization": "Token " + token}
avatar = form.cleaned_data['avatar']
file = {'avatar': (str(avatar), avatar)}
response = requests.put(str(settings.API_END_POINT + '/customer_profile_avi_api/'), files=file,
headers=headers)
message = 'Avatar changes successfully'
if response.status_code in settings.SUCCESS_CODES:
messages.success(self.request, message)
else:
messages.error(self.request, 'API Error %s' % response)
elif 'updateProfile' in self.request.POST:
headers = {"Content-Type": "application/json", "Authorization": "Token " + token}
parameters = {
'bvn': form.cleaned_data['bvn'],
'phone': form.cleaned_data['phone'],
}
response = requests.put(str(settings.API_END_POINT + '/customer_profile_api/'), json=parameters,
headers=headers)
message = 'Profile changes successfully'
if response.status_code in settings.SUCCESS_CODES:
messages.success(self.request, message)
else:
messages.error(self.request, 'API Error %s' % response)
return super(CustomerDashboard, self).form_valid(form)

how do i get the username variable from a user to use it in models.py django

I want to get the username variable of the logged in user to use it as the default value of create a Post form
in html i can access that by doing {{ user.username}}but when i do that as a default value in my models.py i get the default value as {{ user.username}} just as a text not a variable and when i remove the two curly braces it saids that user is not defined
models.py
class Payment(models.Model):
Author = models.CharField(max_length=255)
Product = models.CharField(max_length=255)
Payment_ID = models.BigIntegerField(default=0)
Status = models.CharField(max_length=5, default="X")
Review_result = models.CharField(max_length=255, default="Not yet reviewed")
created = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ['-created']
def __unicode__(self):
return u'%s'% self.Status
def __str__(self):
return self.Status
and for the login i use the default form of django
forms.py
from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
from .models import Payment
class RegistrationForm(UserCreationForm):
email = forms.EmailField(required=True)
first_name = forms.CharField(required=True)
last_name = forms.CharField(required=True)
class Meta:
model = User
fields = (
'username',
'first_name',
'last_name',
'email',
'password1',
'password2',
)
def save(self, commit=True):
user = super(RegistrationForm, self).save(commit=False)
user.first_name = self.cleaned_data['first_name']
user.last_name = self.cleaned_data['last_name']
user.email = self.cleaned_data['email']
if commit:
user.save()
return user
class PayForm(forms.ModelForm):
class Meta:
model = Payment
fields = ['Author', 'Product', 'Price', 'Payment_ID']
views.py
from django.shortcuts import render, render_to_response , get_object_or_404, redirect
from .models import Post
from django.contrib.auth import authenticate, login
from .forms import RegistrationForm, PayForm
# Create your views here.
def index(request):
posts=Post.objects.all()
return render(request, 'Index.html', {"posts": posts})
def post(request, slug):
return render(request, 'post.html', {'post': get_object_or_404(Post, slug=slug)})
def register(request):
if request.method == 'POST':
form = RegistrationForm(request.POST)
if form.is_valid():
form.save()
username = form.cleaned_data['username']
password = form.cleaned_data['password1']
user = authenticate(username=username, password=password)
login(request, user)
return redirect('index')
else:
form = RegistrationForm()
context = {'form' : form}
return render(request, 'registration/register.html', context)
def new_payment(request):
template ='payment.html'
form = PayForm(request.POST or None)
if form.is_valid():
form.save()
return redirect('index')
else:
form = PayForm()
context = {
'form' : form,
}
return render(request, template, context)
In your view, you can override the initial values of form:
def new_payment(request):
template ='payment.html'
if request.method == 'POST'
form = PayForm(request.POST)
if form.is_valid():
form.save()
return redirect('index')
else:
print('form invalid')
else:
form = PayForm({'Author':request.user.username})
context = {
'form' : form,
}
return render(request, template, context)

why is my code skipping my index page?

Whenever I go to the login site (0.0.0.0:5000/), the page immediately reverts to 0.0.0.0:5000/admin. Any ideas on why this is happening?
running through yocto on intel edison. editing via putty
#app.errorhandler(404)
#app.errorhandler(500)
def errorpage(e):
return render_template('404.html')
def login_required(f):
#wraps(f)
def wrap(*args, **kwargs):
if 'logged_in' in session:
return f(*args, **kwargs)
else:
flash('please login first.')
return redirect (url_for('index'))
return wrap
#app.route('/', methods=['GET','POST'])
def index():
error = None
if request.method == 'POST':
if request.form['username'] != 'admin' or request.form['password'] != 'password':
error = 'invalid attempt.'
else:
session['logged_in'] = True
return redirect(url_for('admin'))
return render_template('index.html', error = error)
#app.route('/logout')
def logout():
session.pop('logged_in', None)
return render_template('/logout.html')
#app.route('/admin',methods=['GET','POST'])
#login_required
def admin():
It looks like as soon as anyone hits the page with a GET, it's set as logged_in = True and redirects to /admin
#app.route('/', methods=['GET','POST'])
def index():
error = None
if request.method == 'POST':
if request.form['username'] != 'admin' or request.form['password'] != 'password':
error = 'invalid attempt.'
else: # this is always triggered for GETs, even if not logged in!
session['logged_in'] = True
return redirect(url_for('admin'))
return render_template('index.html', error = error)
Instead, you should be checking that they're already logged in, and set the logged_in property in the POST block instead, after credentials have been checked.
Actually, it just looks like your indenting is off on your else block:
#app.route('/', methods=['GET','POST'])
def index():
error = None
if request.method == 'POST':
if request.form['username'] != 'admin' or request.form['password'] != 'password':
error = 'invalid'
else: # this indenting should work now
session['logged_in'] = True
return redirect(url_for('admin'))
return render_template('index.html', error = error)