Trying to use Ajax to calculate and display the sum before I submit anything to the database. At the moment this is what I have, but I can't seem to get anything to display. I'm trying to start small and see if I'm even able to display the values in the fields.. Is my view for final_price wrong? Or did I mess up somewhere in the Jquery? I'm still new to Ajax, so I'm not sure where I went wrong (following tutorials)
Book Price: $10 (input field)
Delivery charge: $3 (input field)
Delivery type: $5 (input field)
[calculate] [submit]
Final Result: $18 (result of adding the fields above when user clicks the calculate button)
calculate button will display $18
submit button will finalize the results and send the values to the database.
This is my model for the table
class book(models.Model):
user = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
)
book_price = models.IntegerField()
delivery_charge = models.IntegerField()
delivery_type = models.IntegerField()
final_result = models.IntegerField()
def save(self, *args, **kwargs):
self.final_result = self.book_price + self.delivery_charge + self.delivery_type
print(self.final_result)
super(book, self).save(*args, **kwargs)
views.py for the form
def final_price(request):
response_data = {}
if request.method == 'POST':
form = RequestForm(request.POST)
book_price = request.POST.get('book_price')
delivery_charge = request.POST.get('delivery_charge')
delivery_type = request.POST.get('delivery_type')
response_data['book_price'] = book_price
response_data['delivery_charge'] = delivery_charge
response_data['delivery_type'] = delivery_type
book.objects.create(book_price=book_price, delivery_charge=delivery_charge,delivery_type=delivery_type)
return JsonResponse(response_data)
if form.is_valid():
instance = form.save(commit=False)
instance.user = request.user
instance.save()
return redirect('final_price')
else:
form = RequestForm()
args = {'form': form}
return render(request, 'final_price.html', args)
Model for to allow me to edit the fields in my book module
class RequestForm(forms.ModelForm):
class Meta:
model = book
fields = (
'book_price',
'delivery_charge',
'delivery_type',
)
Html file
{% extends 'base.html' %}
{% block content %}
<form class="post" method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" name="button">Submit</button>
</form>
<br>
<button onclick="myFunction()">Get Quote</button>
<script type="text/javascript">
function myFunction(){
$('.ajaxProgress').show();
$.ajax({
type: "POST",
url: "/final_price",
dataType: "json",
async: true,
data:{
csrfmiddlewaretoken: '{{ csrf_token }}',
book_p: $('#book_price').val(),
},
success: function(json){
$('#output').html(json.message);
$(.ajaxProgress).hide();
}
});
}
</script>
{% endblock %}
urls.py
urlpatterns = [
path('', views.home, name='home'),
path('final_price/', views.final_price, name='final_price'),
]
Related
I'm trying to implement a comment system without reloading the page, but it doesn't work. Comments are inserted only after the page is reloaded, but AJAX does not work.
<!-- COMMENT -->
<div class="comment-section">
<form action="{% url 'love:comment_urls' %}" method="POST" class='comment-form'>
{% csrf_token %}
<input type="hidden" name="post_id" value={{i.pk}}>
{{ comment_form }}
<button type="submit" name="submit_c_form">
Опубликовать
</button>
</form>
</div>
<hr>
<div class="comment_set">
{% if i.quotes_comment.all %}
{% for com in i.quotes_comment.all %}
<b>{{ com.user }}:</b>
{{ com.body }}
{% endfor %}
{% endif %}
</div>
</div>
JS code
// COMMENT
$(document).ready(function () {
$('.comment-form').submit(function () {
event.preventDefault();
console.log($(this).serialize());
var url = $(this).attr('action')
$.ajax({
type: 'POST',
url: url,
data: $(this).serialize(),
dataType: 'html',
success: function (response) {
console.log('Заработало')
$('.comment-section').html(response['form']);
},
error: function (rs, error) {
console.log(rs, error)
}
})
})
})
#csrf_exempt
def create_comment(request):
profile = Profile.objects.get(user=request.user)
data = json.loads(request.body)
post_id = data['post_id']
body = data['body']
comment_form = CommentModelForm(data)
if comment_form.is_valid():
print('Form is valid')
instance = comment_form.save(commit=False)
instance.user = profile
instance.quotes = QuotesHonors.objects.get(
id=post_id)
instance.save()
comment_form = CommentModelForm()
return JsonResponse({
'content': body
})
return redirect("love:home_urls")
As I said, comments are inserted only after a reboot, but when I click publish, nothing happens. If you change the dataType to 'json', the parser error pops up. Can you explain what I'm doing wrong?
Hard to say what you are doing wrong overall there is code missing. But from what you shared, csrf_token is not in AJAX request header. And mainly, by using JQuery .serialize(), you are trying to pass data in URL-encoded notation and not as a JSON object.
This .serialize() output would be used to pass data as a query string by appending it to a base URL. And, at the view accessing it with request.GET.get('parameter'). Instead, what we want is to pass data as JSON and access it through request.body at view level.
Here is a full example:
models.py
class Post(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='posts')
title = models.CharField(max_length=30)
body = models.CharField(max_length=255)
created_at = models.DateTimeField(auto_now_add=timezone.now())
class Comment(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='comments')
body = models.CharField(max_length=255)
post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='comments', blank=True)
created_at = models.DateTimeField(auto_now_add=timezone.now())
urls.py
from .views import post_detail, comment_create
app_name = 'love'
urlpatterns = [
path('post/<int:pk>/', post_detail, name='post-detail'),
path('comment/create/', comment_create, name='comment-create'),
]
Two views, one to render the template and another to handle the AJAX request. The tricky part was trying to find a way to format date in the same way as the template.
views.py
from django.utils.formats import date_format
from django.shortcuts import get_object_or_404
from django.http import JsonResponse
import json
def post_detail(request, pk):
post = get_object_or_404(Post, id=pk)
has_commented = post.comments.filter(user=request.user).exists()
context = {
'post': post,
'has_commented': has_commented
}
return render(request, 'post_detail.html', context)
def comment_create(request):
data = json.loads(request.body)
post_id = data['post_id']
comment_body = data['body']
post = get_object_or_404(Post, id=post_id)
comment = Comment.objects.create(
user=request.user,
body=comment_body,
post=post
)
created_at = date_format(comment.created_at, format='M. d, Y, h:m a', use_l10n=True)
return JsonResponse({
'user': comment.user.username,
'body': comment.body,
'created_at': created_at
})
In this first template part we just display data, note that {# % if not has_commented % #} is commented out, when first writing the code I limited the number comments to one per User.
post_detail.html (HTML & DTL):
{% extends 'base.html' %}
{% block content %}
<h1>{{post.title}}</h1>
<h4>{{post.created_at}}</h4>
<p>{{post.body}}</p>
<hr>
<div id="comment-div">
{# % if not has_commented % #}
<form action="{% url 'love:comment-create' %}" id="comment-form">
<input type="hidden" id="post-id" value="{{post.id}}">
<textarea id="comment-body" maxlength="255" rows="4" cols="50"></textarea>
<br>
<button type="submit" id="submit-comment">Comment</button>
</form>
<hr>
{# % endif % #}
</div>
<div id="comment-list">
<h2> Comments </h2>
{% if post.comments.all %}
{% for comment in post.comments.all %}
<p>At {{comment.created_at|date:"M. d, Y, h:m a"}} {{comment.user}} commented:</p>
<p>{{comment.body}}</p>
{% endfor %}
{% endif %}
</div>
This second part, containing the <script> is responsible for every event in the template after adding a new comment. The first function is used to retrieve csrftoken value from cookies.
Then, on submit click we collect data and send the AJAX request. Attention to a few lines. First, where csrf header name is set headers: {'X-CsrfToken': csrftoken}. Second, where data is converted to JSON string data: JSON.stringify({ post_id: post_id, body: body }).
post_detail.html (JS):
<script>
function getCookie(name) {
let cookieValue = null;
if (document.cookie && document.cookie !== '') {
const cookies = document.cookie.split(';');
for (let i = 0; i < cookies.length; i++) {
const cookie = cookies[i].trim();
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
$('#submit-comment').click( function (e) {
e.preventDefault();
var url = $('#comment-form').attr("action");
var post_id = $('#post-id').attr("value");
var body = $('#comment-body').val();
const csrftoken = getCookie('csrftoken');
$.ajax({
method: "POST",
url: url,
headers: {'X-CsrfToken': csrftoken},
data: JSON.stringify({ post_id: post_id, body: body }),
success: function(comment) {
// $('#comment-div').prop("hidden", true);
$('#comment-body').val('');
$('#comment-list').append(
`<p>At ${comment.created_at} ${comment.user} commented:</p>
<p>${comment.body}</p>`
);
}
});
});
</script>
{% endblock %}
Lastly, on success, clear body input and update the template by appending data to <div id="comment-list">. To limit to one comment per user, uncomment $('#comment-div').prop("hidden", true);
I am building a simple flask blog and there I am trying to implement like functionality using ajax and jquery. It works without ajax but the page reloads. So I need to use the ajax but when I am using ajax then I got my site redirected to the JSON file which is not expected. Please Help me with this. The code is
<div class="likers" id = 'result{{ slide.id }}'>
{% if current_user.has_liked_slide(slide) %}
<a class="unlike" id="unlike_{{slide.id}}" href="{{ url_for('like_action', slide_id=slide.id, action='unlike') }}">unlike</a>
{% else %}
<a class="like" id="like_{{slide.id}}" href="{{ url_for('like_action', slide_id=slide.id, action='like') }}">like</a>
{% endif %}
<div id = 'like-count'>
{{ slide.likes | count }}
</div>
</div>
#app.route('/like/<int:slide_id>/<action>', methods = ['GET', 'POST'])
#login_required
def like_action(slide_id, action):
slide = Slide.query.filter_by(id=slide_id).first_or_404()
if action == 'like':
current_user.like_slide(slide)
db.session.commit()
return jsonify({'slide_id': slide_id, 'action': action})
if action == 'unlike':
current_user.unlike_slide(slide)
db.session.commit()
return jsonify({'slide_id': slide_id, 'action': action})
$(document).ready(function(event) {
$('.like, .unlike').click(function(){
var id = this.id;
var split_id = id.split('_');
var text = split_id[0];
var slide_id = split_id[1];
$.ajax({
url: '/like/<int:slide_id>/<action>',
type: 'post',
data : {slide_id:slide_id, action:text},
dataType:'html',
success: function(data){
$("like_" + slide_id).html(data);
$('unlikes_' + slide_id).html(data);
}
});
});
});
I have three forms like this:
<form id = "myForm" style="list-style-type: none;display: none;" class="form_class">
{% csrf_token %}
item1:
<input type="text" name="item1" style="width:10%;height:5%">
<br>
item2:
<input type="text" name="item2" style="width:10%;height: 5%">
<br>
item2:
<input type="text" name="item2" style="width:10%;height: 5%">
<br>
item2:
<input type="text" name="item2" style="width:10%;height: 5%">
<br>
item2:
<input type="text" name="item2" style="width:10%;height: 5%">
<br><br>
<input id="close_form" type="reset" value="reset">
</form>
Below is the code I used to click the button so it will go the javascript method:
<form method="post">
{% csrf_token %}
<input class="bg-yellow text-white" value="RUN" name="runModel" type="submit"
onclick="sendValuesToBack()">
</form>
In the JavaScript method, I'm getting all three form's values. I want to send those to the Django Framework to perform several operations. How do I send this data from JavaScript to Django?
You can do this using JQuery Ajax in the template and by creating an "API view" in your views.py that is basically just a regular view that returns a JSONResponse after checking to verify the request is Ajax. As an example of the "API" option, using JQuery:
In your urls.py:
...
path('/api/post_form/', post_form_api, name="post_form_api"),
...
For the POST method in your views.py:
from django.http import JsonResponse
def post_form_api(request):
data = {}
if request.method == "POST":
form = MyDjangoForm(request.POST)
# do something with the form data
...
if successful:
data['result'] = True
data['message'] = "Form data saved"
if request.is_ajax():
return JsonResponse(data)
else:
return HttpResponseBadRequest()
In your template:
<script type="text/javascript">
$("#myFormSubmitButton").click(function(){
var form_data = $("#formID").serialize();
$.ajax({ url: '{% url 'post_form_api' %}',
type: "POST",
dataType: "json",
data: form_data,
cache: false
}).done(function(data) {
if (data.result === true){
alert(data.message);
}
});
});
});
</script>
Alternatively, you can get the fields from all your forms individually, then send them in the Ajax data like so:
<script type="text/javascript">
$("#myFormSubmitButton").click(function(){
var csrfToken = $("input[name='csrfmiddlewaretoken']");
var item_1 = $("#item1").val();
var item_2 = $("#item2").val();
...
$.ajax({ url: '{% url 'post_form_api' %}',
type: "POST",
dataType: "json",
data: {'item1': item_1, 'item2': item_2, 'csrfmiddlewaretoken':csrfToken.val()},
cache: false
}).done(function(data) {
if (data.result === true){
alert(data.message);
}
});
});
});
</script>
If you have multiple forms you want to use this API for and are only submitting them one at a time, you can put a hidden field in your forms and do something like this in your views.py:
def post_form_api(request):
data = {}
if request.method == "POST":
form_name = request.POST.get('form_name', None) #the name of the hidden field identifying the form
if form_name is not None:
if form_name == "MyDjangoForm":
form = MyDjangoForm(request.POST)
# do something with the form data
...
elif form_name == "MyOtherForm":
form = MyOtherForm(request.POST)
# do something with the form data
...
if successful:
data['result'] = True
data['message'] = "Form data saved"
if request.is_ajax():
return JsonResponse(data)
else:
return HttpResponseBadRequest()
If you are getting the data from all three forms in your template at once, you can do something like this in your views.py after sending all of the data using JQuery Ajax as above:
def post_form_api(request):
data = {}
if request.method == "POST":
item_1 = request.POST.get('item_1', None)
item_2 = request.POST.get('item_2', None)
item_3 = request.POST.get('item_3', None)
...
# do something with the collected form data here
...
if successful:
data['result'] = True
data['message'] = "Form data saved"
if request.is_ajax():
return JsonResponse(data)
else:
return HttpResponseBadRequest()
When you are sending data via POST don't forget to pass along your CSRF token as in the example above (it should be in the serialized form data). This assumes you have a form on the page you can get it from, otherwise you can use something like this to get it:
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie !== '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = cookies[i].trim();
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
var csrftoken = getCookie('csrftoken');
If you don't want to deal with the CSRF token, you can mark the view with the #csrf_exempt decorator and remove the 'csrfmiddlewaretoken' data element from the Ajax call in the template, but it may not be ideal or the most secure. An example of that:
from django.views.decorators.csrf import csrf_exempt
from django.http import JsonResponse
#csrf_exempt()
def post_form_api(request):
...
Now, without knowing more, this is basically just pseudocode (plus I just wrote this off the top of my head so it may have errors). This also depends on what type of views you are using, and whether you want to use the Django REST framework or not (the examples above are for regular, not class-based, views and do not require the Django REST framework to work).
If you post more details I can update my answer, but I think this should get you started.
I am trying to display a User's name on top of a box where they enter their Employee # in a form, without having to refresh the page.
For example, they enter their # and then after they click/tab onto the next field, it renders their name on top, which comes from the database, so the user knows they've entered the correct info. This name is stored in a separate model, so I try to retrieve it using the "id/number".
I am not too familiar with AJAX but after reading a few similar questions it seems like an AJAX request would be the most appropriate way to achieve this. I tried to make a function get_employee_name that returns the name of the person based on the way I saw another ajax request worked, but I'm not sure how to implement this so it displays after the # is entered.
My page currently loads, but there is never a call to the function/url that searches for the name to display it on the page (because there isn't one). I'm not sure where I might be missing the part that connects these two areas of the code or how to connect these, as I am not too familiar with html and Django, most of this has been trial and error.
models.py
class EmployeeWorkAreaLog(TimeStampedModel, SoftDeleteModel, models.Model):
employee_number = models.ForeignKey(Salesman, on_delete=models.SET_NULL, help_text="Employee #", null=True, blank=False)
work_area = models.ForeignKey(WorkArea, on_delete=models.SET_NULL, null=True, blank=False)
station_number = models.ForeignKey(StationNumber, on_delete=models.SET_NULL, null=True, blank=True)
This is the model where the name is stored
alldata/models.py
class Salesman(models.Model):
slsmn_name = models.CharField(max_length=25)
id = models.IntegerField(db_column='number', primary_key=True)
I was reading I can add to the "attrs" in the widget an 'onchange' part, but I am not too familiar with how to approach this and tying it to the ajax request from forms and not the html.
forms.py
class WarehouseForm(AppsModelForm):
class Meta:
model = EmployeeWorkAreaLog
widgets = {
'employee_number': ForeignKeyRawIdWidget(EmployeeWorkAreaLog._meta.get_field('employee_number').remote_field, site, attrs={'id':'employee_number_field'}),
}
fields = ('employee_number', 'work_area', 'station_number')
views.py
def enter_exit_area(request):
form = WarehouseForm(request.POST or None)
if form.is_valid():
# Submission stuff/rules
return render(request, "operations/enter_exit_area.html", {
'form': form,
})
def get_employee_name(request):
employee_number = request.GET.get('employee_number')
try:
employee = Salesman.objects.get(id=employee_number)
except Salesman.DoesNotExist:
return JsonResponse({'error': 'Employee not found'}, status=404)
employee_name = employee.slsmn_name
return JsonResponse({'employee_name': employee_name})
urls.py
urlpatterns = [
url(r'enter-exit-area/$', EnterExitArea.as_view(), name='enter_exit_area'),
path('get-employee-name/', views.get_employee_name, name='get_employee_name'),
]
The ajax request I tried to create is at the end of this html. I modified a similar request I found, but it does not actually display anything on the screen, not sure if I'm missing an area where the request is actually never being called, as I am not too familiar with how these types of requests work.
enter_exit_area.html
{% extends "base.html" %}
{% block main %}
<form id="warehouseForm" action="" method="POST" novalidate >
{% csrf_token %}
<div>
<div>
<!-- Here is where I would want the name to render after the user enters their number and tabs out -->
{{ form.employee_number.help_text }}
{{ form.employee_number }}
</div>
<div>
{{ form.work_area.help_text }}
{{ form.work_area }}
</div>
</div>
<div>
<div>
<button type="submit" name="enter_area" value="Enter">Enter Area</button>
</div>
</div>
</form>
<script>
$("#id_employee_number").change(function () {
var employee_number = $(this).val();
var url = $("#warehouseForm").data("employee-name");
$.ajax({
url: url,
type:'GET',
data: {
'id': employee_number
},
success: function (data) {
var employee_name = data['employee_name'];
$('#employee_name').text(employee_name);
},
error : function (data) {
var error_message = data['error'];
$('#employee_name').text(error_message);
}
});
});
</script>
{% endblock main %}
How can I call the function from the HTML? Could I do it in such a way that when the user enters 6 numbers it checks? (All employee numbers are 6 digits)
The url has to be the endpoint url which you defined in your url.py file
<script>
$("#id_employee_number").change(function (e) {
e.preventDefault();
var employee_number = $(this).val();
var url = $("#warehouseForm").data("employee-name");
$.ajax({
url: "/get_employee_name", // Here
type:'GET',
data: {
'id': employee_number
},
success: function (data) {
var employee_name = data['employee_name'];
$('#employee_name').text(employee_name);
},
error : function (data) {
var error_message = data['error'];
$('#employee_name').text(error_message);
}
});
});
</script>
You can append to your GET request a url parameter like: /get-employee-name/<your employee number here>
I recommend taking a look at URL Dispatcher to create url parameters within your django url definitions
I also recommend using underscores NOT dashes in your url definitions.
So a pseudo working config would be
urls.py
urlpatterns = [
url(r'enter-exit-area/$', EnterExitArea.as_view(), name='enter_exit_area'),
path('get_employee_name/<int:employeeNum>', views.get_employee_name, name='get_employee_name'),
]
views.py
def get_employee_name(request, employeeNum): #You get the employeeNum variable from urls.py
try:
employee = Salesman.objects.get(id=employee_number)
except Salesman.DoesNotExist:
return JsonResponse({'error': 'Employee not found'}, status=404)
employee_name = employee.slsmn_name
return JsonResponse({'employee_name': employee_name})
script
<script>
$("#id_employee_number").change(function () {
var employee_number = $(this).val();
var employeeNum = $("#warehouseForm").data("employee-name");
$.ajax({
url: `/get_employee_name/${employeeNum}`,
type:'GET',
success: function (data) {
var employee_name = data['employee_name'];
$('#employee_name').text(employee_name);
},
error : function (data) {
var error_message = data['error'];
$('#employee_name').text(error_message);
}
});
});
</script>
I want users to be able to like my post so I implemented here. here's my code. It doesn't give any error which is frustrating.
models.py
class Post(models.Model):
title = models.CharField(max_length=100)
content = models.TextField(blank=True, null=True)
date_posted = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE)
url = models.URLField(max_length=250, blank=True, null=True)
views = models.IntegerField(default=0)
likes = models.ManyToManyField(User, related_name='likes')
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('post-detail', kwargs={'pk': self.pk})
def total_likes(self):
return self.likes.count()
views.py
def like(request):
if request.method == 'POST':
user = request.user # bring login user
post_pk = request.POST.get('pk', None)
post = Post.objects.get(pk = post_pk) #bring the post object.
if post.likes.filter(id = user.id).exists(): #if exit
post.likes.remove(user) #likes deleted.
message = 'You disliked this'
else:
post.likes.add(user)
message = 'You liked this'
context = {'likes_count' : post.total_likes, 'message' : message}
return HttpResponse(json.dumps(context), content_type='application/json')
urls.py
urlpatterns = [
path('', PostListView.as_view(), name='community-home'),
path('post/<int:pk>/', PostDetailView.as_view(), name='post-detail'),
path('post/<int:post_pk>/comment/new',views.comment_new, name='comment_new'),
path('post/<int:post_pk>/comment/<int:pk>/edit',views.comment_edit, name='comment_edit'),
path('post/<int:post_pk>/comment/<int:pk>/delete',views.comment_delete, name='comment_delete'),
path('like/', views.like, name='like'),
my html
<input type="button" class="like" name="{{ memo.id }}" value="Like">
<p id="count{{ memo.id }}">count : {{ memo.total_likes }}</p>
<script type="text/javascript">
for(i = 0; i < $(".writer_name").length; i++){
if($("#user_name").text() == $(".writer_name")[i].innerHTML){
$("#control_id"+i).removeClass("hidden");
}
}
$('.like').click(function(){
var pk = $(this).attr('name')
$.ajax({
type: "POST",
url: "{% url 'like' %}",
data: {'pk': pk, 'csrfmiddlewaretoken': '{{ csrf_token }}'},
dataType: "json",
success: function(response){
id = $(this).attr('name')
$('#count'+ pk).html("count : "+ response.likes_count);
alert(response.message);
alert("likes :" + response.likes_count);
},
error:function(request,status,error){
alert("code:"+request.status+"\n"+"message:"+request.responseText+"\n"+"error:"+error);
}
});
})
</script>
I'm not sure if my ajax is wrong or my python is wrong. but to me the logic here makes sense. if anyone can tell what the problem is I would be really appreciated. Thanks
You are using jquery, before using it you must wrap code inside:
$(document).ready(()=>{
...
});
def like(request):
response_json = request.POST
response_json = json.dumps(response_json)
data = json.loads(response_json)
post = Post.objects.get(pk =data['pk'])
if post.likes.filter(id = user.id).exists(): #if exit
post.likes.remove(user) #likes deleted.
message = 'You disliked this'
else:
post.likes.add(user)
message = 'You liked this'
context = {'likes_count' : post.total_likes, 'message' : message}
return JsonResponse(context, safe=False)
try like this. You are sending a JSON datatype so python has to interpret it as so.