use django model to get db information from json request - json

I'm using Django 1.9.6. I have a simplified User model which corresponds to the data in the database:
class User(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(_('email address'), unique=True)
is_active = models.BooleanField(_('active'), default=False,)
and I would like to the user information (is_active) from the email. My simplified User view is as follows:
def settings(self, request, **kwargs):
self.method_check(request, ['post'])
data = self.deserialize(
request, request.body,
format=request.META.get(
'CONTENT_TYPE',
'application/json; charset=UTF-8'
)
)
as_user = request.as_user
if as_user:
return self.create_response(request, {
'success': True,
'is_active': as_user.is_active,
})
return self.create_response(request, {
'success': False,
})
And the request body is a json that looks like:
{
"asUser": "user_email#company.com"
}
I'm not sure exactly what to do where I currently have the line:
as_user = request.as_user
to get the other information about the user in the model class.

If I understand well, you want to retrieve the user object associated with the email sent in request body:
as_user = models.User.objects.get(email=data['asUser'])
That will raise an models.User.DoesNotExist exception if email can not be found.

Related

Django/Django Channels - weird looking json response with double \ between each field

Hello I'm trying to do a real time friend request notification system and having this weird looking json response. I'm new to backend development and django (1st year software engineering student). Im just wondering if this is normal since i havent seen anything like this and if theres a way to fix it. Ive worked on a chat app before but it was just all text messages and so I got confused when it comes to django models. I have tried multiple ways I found but only this works. I think it might be because I called json.dumps twice but if i remove either of them, it wont work. Thank you
When a user sends a friend request, this is what i got back from the web socket(with double \ for each field)
Heres the code
//views.py
class SendRequestView(views.APIView):
permission_class = (permissions.IsAuthenticated,)
def post(self, request, *args, **kwargs):
receiver_username = self.kwargs['receiver_username']
if receiver_username is not None:
receiver = get_object_or_404(User, username=receiver_username)
request = ConnectRequest.objects.create(sender=self.request.user, receiver=receiver)
notification = ConnectNotification.objects.create(type='connect request', receiver=receiver, initiated_by=self.request.user)
channel_layer = get_channel_layer()
channel = f'notifications_{receiver.username}'
async_to_sync(channel_layer.group_send)(
channel, {
'type': 'notify',
'notification': json.dumps(ConnectNotificationSerializer(notification).data, cls=DjangoJSONEncoder),
}
)
data = {
'status': True,
'message': 'Success',
}
return JsonResponse(data)
// consumer.py
class ConnectNotificationConsumer(AsyncJsonWebsocketConsumer):
async def connect(self):
user = self.scope['user']
group_layer = f'notifications_{user.username}'
await self.accept()
await self.channel_layer.group_add(group_layer, self.channel_name)
async def disconnect(self, close_code):
user = self.scope['user']
group_layer = f'notifications_{user.username}'
await self.channel_layer.group_discard(group_layer, self.channel_name)
async def notify(self, event):
notification = event['notification']
await self.send(text_data=json.dumps({
'notification': notification
})
)

django url parameter creating in the process

I have no idea how to solve this problem:
I have a django webshop project. At the end of the order I would like to redirect the user to a new page about the confirmation.
urls.py:
`path('confirmation/<str:order_id>/', views.confirmation,` name="confirmation"),
views.py:
def confirmation(request, order_id):
items = OrderItem.objects.filter(order__id = order_id)
context = {'items':items}
return render(request, 'store/pages/confirmation.html', context)
I have a javascript part another view where I do a POST method. If it is successfully done I would like to navigate to the confirmation page.
In the data I get back the order_id.
var url = '/process_order/'
fetch(url,{
method: 'POST',
headers: {
'Content-Type':'application/json',
'X-CSRFToken':csrftoken,
},
body: JSON.stringify({'myForm':myFormData})
})
.then((response) => response.json())
.then((data) => {
window.location.href = "{% url 'confirmation' data %}"
})
I guess the problem is that in the very beginning of the execution there is no value of the data, because it is creating in the process. So the view can not render because of the parameter. (But my problem is that the order_id is creating after the POST method).
(The Exception Value:
Reverse for 'confirmation' with arguments '('',)' not found. 1 pattern(s) tried: ['confirmation/(?P<order_id>[^/]+)/$'] )
What would be the good solution of this situation?

Why is my model form failing to validate and save in Django?

I am sending django 2 forms in a post request 1 which works as intended and the other which fails to validate and as such is not saved.
the code for the form is here :
class Pick_Vulns(ModelForm):
class Meta:
model = ReportVuln
fields = "__all__"
widgets = {
'Vuln' : Select(attrs={'class':'form-control'}),
'Report' : HiddenInput(attrs={'Value': reportcount}),
}
This form loads correctly on the page with no issues but when the post request is sent it seems to be not be accepted and fails to validate.
an example of the post request :
a post request to the server the first param being a csrf token the next for being the working form the last two being part of the form that does not function.
The code for the post request within my django view is as follows :
def post(self, request):
forminput = Reportform(request.POST or None)
returnedvulns = Pick_Vulns(request.POST or None)
if request.user.is_staff == True:
if forminput.is_valid():
forminput.save()
if returnedvulns.is_valid():
returnedvulns.save()
forminput = Reportform
inoutform = {
'Reportform': forminput,
'reportvulns': pickvulns,
'ReportCount': Reportcount
}
return render(request, self.template_name, inoutform, )
the model to which the form is saved is here :
class ReportVuln(models.Model):
Vuln = models.ForeignKey(Vulnerability, on_delete=models.SET_NULL, null=True, related_name='Vulnerability')
Report = models.ForeignKey(Report, on_delete=models.SET_NULL, null=True) # allows for the referencing of reports
To my memory this has been working in the past and after some minor changes it seems to have broken.
error i recieve is :
ValueError at /reporting/Create
The ReportVuln could not be created because the data didn't validate.
Request Method: POST Request URL:
http://127.0.0.1:8000/reporting/Create Django Version: 3.0.2
Exception Type: ValueError Exception Value:
The ReportVuln could not be created because the data didn't validate.
if you need any more information please ask this is a key component and needs fixing. Thank you.

Django Post request not receiving data

I've spent hours looking up this issue with no avail.
I am having issue with post data from an html page I am sending {'username': 'username'} but when I do request.POST.get('username') it returns none, I alos tried {username, 'username'}
def test_post(request):
if request.method == 'POST':
print(request.POST.get('username'))
return HttpResponse("Good!")
else:
return HttpResponse("Bad.")
Console Development Server
None <<<<
[12/Feb/2018 19:39:53] "POST /test_post HTTP/1.1" 200 5
(edited)
I am sending the data as {'username': 'username'}
That works correctly how come I am unable to get it to show up?
This is the Javascript code that calls from the page:
document.getElementById('submit').addEventListener('click', function(e) {
e.preventDefault();
var username = document.getElementById("username").value;
data = {username: username};
console.log(data);
var request = new XMLHttpRequest();
request.open('POST', '/getuser', true);
request.setRequestHeader('Content-Type', 'x-www-form-urlencoded');
request.send(data);
});
In the django view test_post, request.POST is a Query Dict (aka Dictionary).
When you use the method .get(key), it looks for the key in the dictionary and returns you the value corresponding to the key.
In the test_post method, you have written request.POST.get('username') which means the string 'username' as a key should be present in the POST dictionary.
When you do a POST using Javascript, and do data = {username: username}; you are essentially making the key dynamic.
Eg. when you input "Bob" in username and click on submit, the variable data
will be {'Bob': 'Bob'}
Instead you should do:
data = {'username': username} //This ensures that the key remains same

Format ValidationError in Serializer

DjangoRestFramework seems to handle errors with a variety of ways. The ValidationError in the serializer class does not consistently return JSON the same.
Current response includes a JSON list/object string:
{"detail":["Unable to log in with provided credentials."]}
Looking to achieve:
{"detail":"Unable to log in with provided credentials."}
I realize that this response is a result of default functions. However, I've overridden the validate function:
class AuthCustomTokenSerializer(serializers.Serializer):
username = serializers.CharField(write_only=True)
password = serializers.CharField(write_only=True)
token = serializers.CharField(read_only=True)
def validate(self, validated_data):
username = validated_data.get('username')
password = validated_data.get('password')
# raise serializers.ValidationError({'detail': 'Unable to log in with provided credentials.'})
if username and password:
user = authenticate(phone_number=username, password=password)
try:
if UserInfo.objects.get(phone_number=username):
userinfo = UserInfo.objects.get(phone_number=username)
user = User.objects.filter(user=userinfo.user, password=password).latest('date_joined')
if user:
if user.is_active:
validated_data['user'] = user
return validated_data
else:
raise serializers.ValidationError({"detail": "User account disabled."})
except UserInfo.DoesNotExist:
try:
user = User.objects.filter(email=username, password=password).latest('date_joined')
if user.is_active:
validated_data['user'] = user
return validated_data
except User.DoesNotExist:
#raise serializers.ValidationError("s")
raise serializers.ValidationError({'detail': 'Unable to log in with provided credentials.'})
else:
raise serializers.ValidationError({"detail" : "Must include username and password."})
class Meta:
model = Token
fields = ("username", "password", "token")
I've tried adding a custom exception handler:
from rest_framework.views import exception_handler
def custom_exception_handler(exc, context):
# Call REST framework's default exception handler first,
# to get the standard error response.
response = exception_handler(exc, context)
# Now add the HTTP status code to the response.
if response is not None:
response.data['status_code'] = response.status_code
return response
views.py: if serializer.is_valid(raise_exception=True):
However, that only appends the currently raised error:
{"detail":["Unable to log in with provided credentials."],"status_code":400}
How should I use change the format of the returning text?
It only returns the JSON like this for this particular serializer within the validate function.
I've also looked into formatting the non_field_errors template, but it works with all my other serializers e.g:
{"detail": "Account exists with email address."}
Maybe you should try overriding json renderer class and hook up a custom one, where you can check for status code and detail key in response data, then re-format the value appropriately.
I never tried that, so I can't give you the exact codebase, but this is the only approach I can think of to have consistent response.