I am Unable to Send My email in django backend app - django

When i can send post request for contact view so try block can't run and except block should be run.
Here i cant unable to send mail.
Here error in send_mail function.
So please Help me.
In Here my setting.py code
settings.py
EMAIL_BACKEND='django.core.mail.backend.smtp.EmailBackend'
EMAIL_HOST='smtp.gmail.com'
EMAIL_PORT=587
EMAIL_HOST_USER='kalp2002prajapati#gmail.com'
EMAIL_HOST_PASSWORD='******'
EMAIL_USE_TLS = True
EMAIL_USE_SSL = 0
view.py
from rest_framework import permissions
from rest_framework.views import APIView
from .models import Contact
from django.core.mail import
send_mail,EmailMessage
from rest_framework.response import Response
class ContactCreateView(APIView):
permission_classes = (permissions.AllowAny, )
def post(self, request, format=None):
data = self.request.data
print(data)
try:
send_mail(
data['subject'],
'Name: '+ data['name']
+ '\nEmail: '+data['email']+'\nMessage:'+ data['message'],
'kalpprajapati2002#gmail.com',
['kalp2002prajapati#gmail.com'],
fail_silently=False
)
contact = Contact(name=data['name'], email=data['email'], subject=data['subject'], message=data['message'])
contact.save()
return Response({'success': 'Message sent successfully'})
except:
return Response({'error': 'Message failed to send'})
urls.py
from django.urls import path
from .views import ContactCreateView
urlpatterns = [
path('', ContactCreateView.as_view())
]
models.py
from django.db import models
from datetime import datetime
class Contact(models.Model):
name=models.CharField(max_length=200)
email=models.CharField(max_length=100)
subject=models.CharField(max_length=100)
message=models.TextField(blank=True)
contact_date=models.DateTimeField(default=datetime.now,blank=True)
def __str__(self):
return self.email

just delete all the self from the view, you need only the request.
if this doesn't make your code work, post the error you are getting

Related

TypeError: Object of type User is not JSON serializable

I am quite new to Django and I am building a simple referral system where a code is autogenerated for the user and when this code is called, the API should return the user by which this code was referred. However I am experiencing some difficulties to return the username, getting the error TypeError: Object of type User is not JSON serializable. Below I am posting my code (please ignore the unused imports, I was trying many things and I need to clean the code later)
views.py
`
from rest_framework.decorators import api_view
from rest_framework.response import Response
import json, requests
from rest_framework.views import APIView
from django.http import JsonResponse, HttpResponse
from django.core import serializers
from django.core.serializers import serialize
import ast
from rest_framework.parsers import JSONParser
class MainView(APIView):
def post(self, request):
code = request.data["ref_code"]
print(str(code))
try:
profile = ReferralSys.objects.get(code=code)
print(profile)
request.session["ref_profile"] = profile.user
username = profile.user.username
print(username)
print(type(username))
# return HttpResponse("user is here", user)
except:
pass
print(request.session.get_expiry_date())
return Response(f"{profile.user.username}")
models.py
from django.db import models
from django.contrib.auth.models import User
from .utils import generate_ref_code
class ReferralSys(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
bio = models.TextField(blank=True)
code = models.CharField(max_length=12, blank=True)
recommented_by = models.ForeignKey(
User, on_delete=models.CASCADE, blank=True, null=True, related_name="ref_by"
)
updated = models.DateTimeField(auto_now=True)
created = models.DateTimeField(auto_now_add=True)
def __str__(self):
return f"{self.user.username}-{self.code}"
def get_recommended_profiles(self):
pass
def save(self, *args, **kwargs):
if self.code == "":
code = generate_ref_code()
self.code = code
super().save(*args, **kwargs)
utils.py
import uuid
def generate_ref_code():
code = str(uuid.uuid4()).replace("-", "")[:12]
return code
urls.py
from django.contrib import admin
from django.urls import path
from .views import MainView
urlpatterns = [
path("admin/", admin.site.urls),
path("", MainView.as_view()),
path("str:<ref_code>", MainView.as_view()),
]
Thank you in advance for the help.
PS: I am following this tutorial https://www.youtube.com/watch?v=QZfflGvRQrc&t, but instead of using templates I want to use APIView.
What happens is that Django sessions serializes data using JSON. When writing:
request.session["ref_profile"] = profile.user
You are trying to insert a model inside the session, thus the error. One basic and simple way, is to parse the desired data into a JSON:
from rest_framework.response import Response
from rest_framework.views import APIView
from .models import ReferralSys
import json
class MainView(APIView):
def post(self, request, code=None):
if code is None:
code = request.data['code']
try:
profile = ReferralSys.objects.get(code=code)
user = {
'username': profile.user.username,
'email': profile.user.email
}
user_json = json.dumps(user)
request.session["ref_profile"] = user_json
except:
pass
print(request.session.get_expiry_date())
return Response(f"{profile.user.username}")
Of course, there are tradeoffs and I recommend you to read the documentation in order to understand them. There is also another mistake in the form of how you are passing (and retrieving) the extra keyword argument in the URL, the right syntax:
path("<str:code>/", MainView.as_view()),

Django Testing for Login and token collection

Trying to write test for Django login. I want to request to login, collect token and access different view functions. How do I write a test in python for this.
It depends on your authentication system, if you use Django default auth, you can just use its helper method login(**credentials) or force_login https://docs.djangoproject.com/en/4.1/topics/testing/tools/#django.test.Client.login
If you use Django Rest Framework with additional 3rd auth system you can use its testing class
from rest_framework.test import APITestCase
class TestMyProtectedView(APITestCase):
def setUp(self) -> None:
self.client.login(user, password)
def test_view(self):
# now you can access your view with logged-in user in setUp
response = self.client.get('/api/views/')
Just like described in Django and DRF documentations. It would be something like:
tests.py
from django.test import TestCase
from django.urls import reverse
from django.contrib.auth import get_user_model
from rest_framework.authtoken.models import Token
from rest_framework.test import APIClient
from rest_framework import status
# Create your tests here.
class UserLoginTestCase(TestCase):
def setUp(self):
self.client = APIClient()
self.admin_user = get_user_model().objects.create_superuser(
email='admin#example.com',
password='testpass123',
)
def test_user_create_or_collect_token(self):
"""User check token created if in post save signal format"""
token = Token.objects.get(user__email=self.admin_user.email)
self.assertTrue(token.key)
def test_user_authenticated(self):
"""Check if user is authenticated"""
token = Token.objects.get(user__email=self.admin_user.email)
self.client.credentials(HTTP_AUTHORIZATION='Token ' + token.key)
r = self.client.get(reverse('user:me'))
self.assertEqual(r.status_code, status.HTTP_200_OK)
def test_user_login(self):
"""test user login"""
url = reverse('user:login')
data = {
'username': 'admin#example.com',
'password': 'testpass123'
}
r = self.client.post(url, data, format='json')
self.assertEqual(r.status_code, status.HTTP_200_OK)
self.assertTrue(r.data['token'])
urls.py
from .api.views import CustomAuthToken, UserAuthenticated
from django.urls import path
app_name = 'user'
urlpatterns = [
path('login/', CustomAuthToken.as_view(), name='login'),
path('me/', UserAuthenticated.as_view(), name='me'),
]
views.py
from rest_framework.views import APIView
from rest_framework.authtoken.views import ObtainAuthToken
from rest_framework.authtoken.models import Token
from rest_framework.response import Response
from rest_framework import authentication, permissions
from core.models import User
class CustomAuthToken(ObtainAuthToken):
def post(self, request, *args, **kwargs):
serializer = self.serializer_class(data=request.data,
context={'request': request})
serializer.is_valid(raise_exception=True)
user = serializer.validated_data['user']
token, created = Token.objects.get_or_create(user=user)
return Response({
'token': token.key,
'user_name': user.name,
'email': user.email
})
class UserAuthenticated(APIView):
queryset = User.objects.all()
authentication_classes = [authentication.TokenAuthentication]
permission_classes = [permissions.IsAdminUser]
def get(self, request):
""" Check if user is authenticated by checking token against db """
is_authenticated = True
return Response({'isAuthenticated': is_authenticated})
Usually, tests are written for both positive and negative outcomes.
Note that in this case in particular I have a custom user model, and also extended the built-in ObtainAuthToken view.

Django Download csv after post request

I want to create an endpoint, in this endpoint its possible to send POST request, if the POST request
is validated, then the page download a csv
I created the serializer form to make a easy validation of the data received
My problem is that the csv its easy downloaded in a HttpResponse, but i need neccesary to make a endpoint and a validation of the data in a post request.
My principal problem is that i can´t return the export function next of the validation
This are my files
#urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^hello-view/', views.HelloApiView.as_view()),
]
Serializers
#serializers.py
from rest_framework import serializers
class HelloSerializer(serializers.Serializer):
"""Serializes a name field """
name = serializers.CharField(max_length=100)
seller_id = serializers.CharField(max_length=100)
def validate_name(self, dob):
UnitOfMeasureName = ["Each", "Grams", "Ounces", "Pounds", "Kilograms", "Metric Tons"]
if dob in UnitOfMeasureName:
return dob
else:
raise serializers.ValidationError('Wrong username')
And the views files
In this file i created the export function to try to export the csv data, but doesnt works
import csv
from django.shortcuts import render
from django.http import HttpResponse
from rest_framework import viewsets
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from . import serializers
class HelloApiView(APIView):
def export(self, request):
response = HttpResponse(content_type='text/csv')
writer = csv.writer(response)
writer.writerow(['First name', 'Last name', 'ID'])
response['Content-Disposition'] = 'attachment; filename="one.csv"'
return response
serializer_class = serializers.HelloSerializer
def get(self, request, format=None):
an_apiview = [
'Uses HTTP METHOD as function',
'Its is similar to a traditional django view'
]
return Response({'message': 'Hello', 'anapi': an_apiview})
def post(self, request):
serializer = serializers.HelloSerializer(data = request.data)
if serializer.is_valid():
in this place i want to return the file
else:
return Response(
serializer.errors, status = status.HTTP_400_BAD_REQUEST)
Add a new endpoint to your urls.py file
#urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^hello-view/', views.HelloApiView.as_view()),
url(r'^csv_download/$', views.csv_download, name="csv_download"),
]
Then in your views.py file, add a function called csv_download and move all of your stuff there (This might be unnecessary, but it sure makes for cleaner, more readable code)
# views.py
import csv
from django.shortcuts import render
from django.http import HttpResponse
from rest_framework import viewsets
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from . import serializers
class HelloApiView(APIView):
def get(self, request, format=None):
an_apiview = [
'Uses HTTP METHOD as function',
'Its is similar to a traditional django view'
]
return Response({'message': 'Hello', 'anapi': an_apiview})
def csv_download(request):
if request.method == 'POST':
serializer_class = serializers.HelloSerializer
serializer = serializers.HelloSerializer(data = request.data)
if serializer.is_valid():
response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename="one.csv"'
writer = csv.writer(response,delimiter=',') # I always like to specify the delimeter
writer.writerow(['First name', 'Last name', 'ID'])
#Then you may actually want to write some data to the CSV file, currently, you've only defined the headers (first row). An example would be like:
for value in list_of_objects:
writer.writerow([
value.first_name,
value.last_name,
value.id
])
return response
else:
return Response(
serializer.errors, status = status.HTTP_400_BAD_REQUEST)
else:
# redirect them or do something here if they hit this URL without a POST request

How do you return 404 when resource is not found in Django REST Framework

When a user inputs a url that is wrong, my Django app returns an HTML error. How can I get DRF to return a json formatted error?
Currently my urls is
from django.conf.urls import url
from snippets import views
urlpatterns = [
url(r'^snippets/$', views.snippet_list),
url(r'^snippets/(?P<pk>[0-9]+)/$', views.snippet_detail),
]
but if a user goes to 127.0.0.1:8000/snip They get the html formatted error rather than a json formatted error.
Simply way to do it, you can use raise Http404, here is your views.py
from django.http import Http404
from rest_framework import status
from rest_framework.response import Response
from rest_framework.views import APIView
from yourapp.models import Snippet
from yourapp.serializer import SnippetSerializer
class SnippetDetailView(APIView):
def get_object(self, pk):
try:
return Snippet.objects.get(pk=pk)
except Snippet.DoesNotExist:
raise Http404
def get(self, request, pk, format=None):
snippet = self.get_object(pk)
serializer = SnippetSerializer(snippet)
return Response(serializer.data, status=status.HTTP_200_OK)
You also can handle it with Response(status=status.HTTP_404_NOT_FOUND), this answer is how to do with it: https://stackoverflow.com/a/24420524/6396981
But previously, inside your serializer.py
from rest_framework import serializers
from yourapp.models import Snippet
class SnippetSerializer(serializers.ModelSerializer):
user = serializers.CharField(
source='user.pk',
read_only=True
)
photo = serializers.ImageField(
max_length=None,
use_url=True
)
....
class Meta:
model = Snippet
fields = ('user', 'title', 'photo', 'description')
def create(self, validated_data):
return Snippet.objects.create(**validated_data)
To test it, an example using curl command;
$ curl -X GET http://localhost:8000/snippets/<pk>/
# example;
$ curl -X GET http://localhost:8000/snippets/99999/
Hope it can help..
Update
If you want to handle for all error 404 urls with DRF, DRF also provide about it with APIException, this answer may help you; https://stackoverflow.com/a/30628065/6396981
I'll give an example how do with it;
1. views.py
from rest_framework.exceptions import NotFound
def error404(request):
raise NotFound(detail="Error 404, page not found", code=404)
2. urls.py
from django.conf.urls import (
handler400, handler403, handler404, handler500)
from yourapp.views import error404
handler404 = error404
Makesure your DEBUG = False
from rest_framework import status
from rest_framework.response import Response
# return 404 status code
return Response({'status': 'details'}, status=status.HTTP_404_NOT_FOUND)
An easier way is to use get_object_or_404 method in django:
as described in this link:
get_object_or_404(klass, *args, kwargs)
- Calls get() on a given model manager, but it raises Http404 instead of the model’s DoesNotExist exception.
- klass: A Model class, a Manager, or a QuerySet instance from which to get the object.
As an example, pay attention to
obj = get_object_or_404(Snippet, pk=pk)
return obj
in the following code:
from django.shortcuts import get_object_or_404
from snippets.models import Snippet
from snippets.serializers import SnippetSerializer
from rest_framework.views import APIView
from rest_framework.response import Response
class SnippetDetail(APIView):
"""
Retrieve, update or delete a snippet instance.
"""
def get_object(self, pk):
obj = get_object_or_404(Snippet, pk=pk)
return obj
def get(self, request, pk, format=None):
snippet = self.get_object(pk)
serializer = SnippetSerializer(snippet)
return Response(serializer.data)
...
Or simply, you can use the same structure of DRF, without losing I18N and keep the same DRF error message:
from rest_framework import viewsets, status, exceptions
from rest_framework.decorators import action
from rest_framework.response import Response
try:
codename = get_or_bad_request(self.request.query_params, 'myparam')
return Response(self.get_serializer(MyModel.objects.get(myparam=codename), many=False).data)
except MyModel.DoesNotExist as ex:
exc = exceptions.NotFound()
data = {'detail': exc.detail}
return Response(data, exc.status_code)

DJANGO Rest API Invalid Syntax error

I'm trying to create a Django Rest API using this link, but I get an invalid syntax error. Here is my code:
urls.py
from django.conf.urls.defaults import *
from polls.views import *
# Uncomment the next two lines to enable the admin:
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
(r'^polls/$',index),
(r'^polls/(?P<poll_id>\d+)/$',detail),
(r'^polls/(?P<poll_id>\d+)/results/$',results),
(r'^polls/(?P<poll_id>\d+)/vote/$',vote),
(r'^admin/', include(admin.site.urls)),
(r'^xml/polls/(.*?)/?$',xml_poll_resource),
)
views.py
from django_restapi.model_resource import Collection
from django_restapi.responder import XMLResponder
from django_restapi.responder import *
from django_restapi_tests.polls.models import Poll, Choice
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render_to_response, get_object_or_404
from polls.models import Poll, Choice
from django.http import Http404
from django.template import RequestContext
import pdb
def index(request):
latest_poll_list = Poll.objects.all().order_by('-pub_date')[:5]
return render_to_response('index.html',{'latest_poll_list': latest_poll_list})
def detail(request, poll_id):
pdb.set_trace()
p = get_object_or_404(Poll, pk=poll_id)
return render_to_response('detail.html', {'poll': p},
context_instance=RequestContext(request))
def results(request, poll_id):
return HttpResponse("Hello, world.Youre at the poll index.")
def vote(request, poll_id):
p = get_object_or_404(Poll, pk=poll_id)
try:
selected_choice = p.choice_set.get(pk=request.POST['choice'])
except (KeyError, Choice.DoesNotExist):
# Redisplay the poll voting form.
return render_to_response('polls/detail.html', {
'poll': p,
'error_message': "You didn't select a choice.",
}, context_instance=RequestContext(request))
else:
selected_choice.votes += 1
selected_choice.save()
# Always return an HttpResponseRedirect after successfully dealing
# with POST data. This prevents data from being posted twice if a
# user hits the Back button.
return HttpResponseRedirect(reverse('results', args=(p.id,)))
xml_poll_resource = Collection(
queryset = Poll.objects.all(),
permitted_methods = ('GET', 'POST', 'PUT', 'DELETE'),
responder = XMLResponder(paginate_by = 10))
)
Models.py
from django.db import models
class Poll(models.Model):
question = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')
def __unicode__(self):
return self.question
class Choice(models.Model):
poll = models.ForeignKey(Poll)
choice = models.CharField(max_length=200)
votes = models.IntegerField()
def __unicode__(self):
return self.choice
This application is based on the tutorial that is given in the Django Website. It was working well but started failing once I implemented the logic for rest APIs.
(r'^xml/polls/(.*?)/?$',xml_poll_resource),
The URL that I'm trying: http://127.0.0.1:8000/xml/polls/
Error
SyntaxError at /xml/polls/
invalid syntax (views.py, line 49)
Request Method: GET
Request URL: http://127.0.0.1:8000/xml/polls/
Django Version: 1.3.1
Exception Type: SyntaxError
Exception Value: invalid syntax (views.py, line 49)
Probably not the answer you are looking for, however I recommand you to have a look at this Django REST framwork: django-rest-framework.org