Django Error NoReverseMatch at /invest/(?P1\d+)/ - python

So I am trying to update a value in django. But when clicking on submit it is throwing me a error.
NoReverseMatch at /invest/(?P1\d+)/
Reverse for 'invest' with keyword arguments '{'pk': ''}' not found. 1 pattern(s) tried: ['invest/\\(\\?P(?P<pk>[^/]+)\\\\d\\+\\)/$']
Request Method: POST
Request URL: http://127.0.0.1:8000/invest/(%3FP1%5Cd+)/
Django Version: 3.1.7
Exception Type: NoReverseMatch
Exception Value:
Reverse for 'invest' with keyword arguments '{'pk': ''}' not found. 1 pattern(s) tried: ['invest/\\(\\?P(?P<pk>[^/]+)\\\\d\\+\\)/$']
Exception Location: C:\Users\Harsh-PC\AppData\Roaming\Python\Python37\site-packages\django\urls\resolvers.py, line 685, in _reverse_with_prefix
Python Executable: C:\Program Files\Python37\python.exe
Python Version: 3.7.9
Python Path:
['E:\\Colosseum 2021\\django_colo',
'C:\\Program Files\\Python37\\python37.zip',
'C:\\Program Files\\Python37\\DLLs',
'C:\\Program Files\\Python37\\lib',
'C:\\Program Files\\Python37',
'C:\\Users\\Harsh-PC\\AppData\\Roaming\\Python\\Python37\\site-packages',
'C:\\Users\\Harsh-PC\\AppData\\Roaming\\Python\\Python37\\site-packages\\win32',
'C:\\Users\\Harsh-PC\\AppData\\Roaming\\Python\\Python37\\site-packages\\win32\\lib',
'C:\\Users\\Harsh-PC\\AppData\\Roaming\\Python\\Python37\\site-packages\\Pythonwin',
'C:\\Program Files\\Python37\\lib\\site-packages']
Server time: Mon, 22 Mar 2021 09:21:50 +0000
I am calling invest page from brand.html page in this manner
<a href="{% url 'invest' pk=marking.id %}";><button type="button" class="btn btn-primary" data-toggle="modal" >Invest</button></a>
I am passing the value properly in my html code
<script>
$(document).on('submit', '#post-form',function(e){
// console.log("Amount="+$('input[name="amount"]').val());
e.preventDefault();
// getting the value entered
amount = $('input[name="amount"]').val();
product_title = $('input[name="product_title"]').val();
console.log("Product title="+product_title);
console.log("Amount entered by user="+amount);
$.ajax({
type:'POST',
url:"{% url 'invest' pk=context.id %}",
data:{
product_title: product_title,
amount: amount,
csrfmiddlewaretoken: '{{ csrf_token }}',
action: 'post'
},
success: function(xhr, errmsg, err){
window.location = "brand"
},
error : function(xhr,errmsg,err) {
$('#results').html("<div class='alert-box alert radius' data-alert>Oops! We have encountered an error: "+errmsg+
" <a href='#' class='close'>×</a></div>");
console.log(xhr.status + ": " + xhr.responseText);
}
});
});
</script>
urls.py
path('invest/(?P<pk>\d+)/', views.invest, name='invest'),
views.py
def invest(request, pk):
# fetching the current event details
event_data = MarketingMaestro.objects.get(pk = pk)
context = {
'id' : event_data.id,
'product_title' : event_data.product_title,
'total_value' : event_data.total_value,
'total_votes' : event_data.total_votes,
}
# fetching user details
user_data = MarketingInvesment.objects.get(emailID = request.user.email)
user_details = {
'name' : user_data.name,
'emailID' : user_data.emailID,
'remaining_amount' : user_data.remaining_amount
}
total_value_db = event_data.total_value
# updating the user amount
# try:
# checking if the user exist in UserProfile through the logged in email id
if request.POST.get('action') == 'post':
response_data = {}
name = request.user.username
emailID = request.user.email
# remaining amount from db
remaining_amount = user_data.remaining_amount
product_title = request.POST.get('product_title')
# getting user amount
user_amount = request.POST.get('amount')
user_amount_final = int(user_amount)
user_amount_db = total_value_db + user_amount_final
final_amount = remaining_amount - user_amount_final
response_data['name'] = name
response_data['emailID'] = emailID
response_data['remaining_amount'] = remaining_amount
response_data['product_title'] = product_title
# updating the current logged in user values
user_data = MarketingInvesment.objects.get(emailID = request.user.email)
if(user_data.emailID == request.user.email):
MarketingInvesment.objects.filter(emailID = request.user.email).update(
name = name,
emailID = emailID,
remaining_amount = final_amount,
product_title = product_title,
total_investment = user_amount_db
)
return render(request, 'invest.html')
return render(request, 'invest.html', {'context' : context, 'user_details' : user_details})

I think you should use url when working with URL regex, because path doesn't support regex here is the docs for path(). you can use regex in url like this:
from django.conf.urls import url
url(r'^invest/(?P<pk>[\w-]+)/', views.invest, name='invest'),
...
and I think you didn't add marking object in your context

SOLUTION
urls.py
path('investing/<int:pk>/', views.investing, name='investing'),
path('invest/<int:pk>/', views.invest, name='invest'),
views.py Just had to include JsonResponse as I was returning render which is wrong.
return JsonResponse(
{
'message': "success"
}

Related

Django -> 'WSGIRequest' object has no attribute 'data' -> Error in json.loads(request.data)

I saw a similar question but the answer is rather vague. I created a function based view for updateItem. I am trying to get json data to load based on my request. but am getting the error -> object has no attribute 'data'
Views.py file:
def updateItem(request):
data = json.loads(request.data)
productId = data['productId']
action = data['action']
print("productID", productId, "action", action)
customer = request.user.customer
product = Product.objects.get(id=productId)
order, created = Order.objects.get_or_create(customer=customer,complete=False)
orderItem, created = OrderItem.objects.get_or_create(order=order, product=product)
if action == 'add':
orderItem.quantity = (orderItem.quantity + 1)
elif action == 'remove':
orderItem.quantity = (orderItem.quantity - 1)
orderItem.save()
if orderItem.quantity <= 0:
orderItem.delete()
return JsonResponse("Item was added!", safe=False)
JS File:
function updateUserOrder(productId, action) {
console.log('User is logged in...');
let url = '/update_item/';
fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': csrftoken,
},
body: JSON.stringify({ productId: productId, action: action }),
})
.then((res) => {
return res.json();
})
.then((data) => {
console.log('data', data);
});
}
urls python file:
urlpatterns = [
path("",views.store,name="store"),
path("cart/",views.cart,name="cart"),
path("checkout/",views.checkout,name="checkout"),
path("update_item/",views.updateItem,name="update_item"),
]
The Error seems to also occur in my fetch function in the JS file. With my method POST. Can't find a solution, what am I doing wrong here?
The main problem is that you are trying to access 'request.data', there is no such attribute. What you want is to retrieve data from the POST request.
(Also, note that good practice is to have your views and variable names in snake_case form, whereas camelCase is used for classes):
def updateItem(request):
data = json.loads(request.POST.get('data'))
...
return JsonResponse("Item was added!", safe=False)
Although, to complete my answer, I must say that I had problems with your JS function, with the csrf token not being properly attached. My test solution:
views.py
from django.shortcuts import render
from django.http import JsonResponse
import json
def update_item(request):
return render(request, 'update_item.html', {})
def update_item_ajax(request):
data = json.loads(request.POST.get('data'))
print(data)
...
return JsonResponse({'message': '"Item was added!"'}, safe=False)
# output of update_item_ajax print
{'productId': 1, 'action': 'myaction'}
urls.py
from django.urls import path
from core import views
app_name = 'core'
urlpatterns = [
path('update/item/', views.update_item, name='update-item'),
path('update/item/ajax/', views.update_item_ajax, name='update-item-ajax'),
]
update_item.html
{% extends 'base.html' %}
{% block content %}
<button onclick="updateUserOrder(1, 'action')"> update item </button>
{% endblock %}
{% block script %}
<script>
function updateUserOrder(productId, action) {
console.log('User is logged in...');
let url = "{% url 'core:update-item-ajax' %}";
var payload = {
productId: productId,
action: action
};
var data = new FormData();
data.append( 'data' , JSON.stringify( payload ) );
data.append('csrfmiddlewaretoken', '{{ csrf_token }}');
fetch(url,
{
method: 'POST',
body: data,
})
.then(function(res){ return res.json(); })
.then(function(data){ console.log(data); });
}
</script>
{% endblock %}
Try:
data = json.loads(request.body)
Because the request doesn't have data, since you pass the data as body: JSON.stringify({ productId: productId, action: action }),

Theme Choosing Option for a Django Project not working properly

Helloo,
I am following a tutorial to allow User to select Light/Dark Mode using HTML, CSS, JS.
I have following documentation and tutorial but the issue is that the content of the page itself is not showing and I am not sure the reason.
So what I did is I created 2 css files dark and light, and create a mode application with the settings.
I am currently receiving an error:
django.contrib.auth.models.User.setting.RelatedObjectDoesNotExist: User has no setting.
To start here is the base.html
<link id="mystylesheet" href="{% static 'css/app-light.css' %}" type="text/css" rel="stylesheet">
<!-- Mode -->
<div id="mode" class="section" style="padding-top: 1rem; padding-bottom: 3rem;text-align: right">
<button onclick="swapStyle('css/app-light.css')" type="button" class="btn btn-secondary">Light Mode</button>
<button onclick="swapStyle('css/app-dark.css')" type="button" class="btn btn-dark">Dark Mode</button>
</div>
<!-- Mode -->
<script type="text/javascript">
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');
var cssFile = "{% static 'css' %}"
function swapStyles(sheet){
document.getElementById('mystylesheet').href = cssFile + '/' + sheet
localStorage.setItem('theme', sheet)
updateTheme(sheet)
}
function loadSettings(){
//Call data and set local storage
var url = "{% url 'mode:user_settings' %}"
fetch(url, {
method:'GET',
headers:{
'Content-type':'application/json'
}
})
.then((response) => response.json())
.then(function(data){
console.log('Data:', data)
var theme = data.value;
if (theme == 'light.css' || null){
swapStyles('light.css')
}else if(theme == 'dark.css'){
swapStyles('dark.css')
}
})
}
loadSettings()
function updateTheme(theme){
var url = "{% url 'mode:update_theme' %}"
fetch(url, {
method:'POST',
headers:{
'Content-type':'application/json',
'X-CSRFToken':csrftoken,
},
body:JSON.stringify({'theme':theme})
})
}
</script>
Here is the model.py
class Setting(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
name = models.CharField(max_length=200)
value = models.CharField(max_length=200)
def __str__(self):
return self.name
here is the views.py
def index(request):
return render(request, 'base.html')
def userSettings(request):
user, created = User.objects.get_or_create(id=1)
setting = user.setting
seralizer = UserSerailizer(setting, many=False)
return JsonResponse(seralizer.data, safe=False)
def updateTheme(request):
data = json.loads(request.body)
theme = data['theme']
user, created = User.objects.get_or_create(id=1)
user.setting.value = theme
user.setting.save()
print('Request:', theme)
return JsonResponse('Updated..', safe=False)
Here is the serializer.py
from .models import *
class UserSerailizer(serializers.ModelSerializer):
class Meta:
model = Setting
fields = '__all__'
Here is urls.py
app_name = 'mode'
urlpatterns = [
path('', views.index, name="index"),
path('user_settings/', views.userSettings, name="user_settings"),
path('update_theme/', views.updateTheme, name="update_theme"),
]
Here is the traceback
Traceback (most recent call last):
File "C:\Users\Ahmed\Desktop\Project\venv\lib\site-packages\django\core\handlers\exception.py", line 47, in inner
response = get_response(request)
File "C:\Users\Ahmed\Desktop\Project\venv\lib\site-packages\django\core\handlers\base.py", line 179, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\Users\Ahmed\Desktop\Project\mode\views.py", line 17, in userSettings
setting = user.setting
File "C:\Users\Ahmed\Desktop\Project\venv\lib\site-packages\django\db\models\fields\related_descriptors.py", line 421, in __get__
raise self.RelatedObjectDoesNotExist(
django.contrib.auth.models.User.setting.RelatedObjectDoesNotExist: User has no setting.
You need to handle the case when a user will not have a setting in userSettings function.
def userSettings(request):
user, created = User.objects.get_or_create(id=1)
setting = getattr(user, 'setting', None)
if setting:
seralizer = UserSerailizer(setting, many=False)
return JsonResponse(seralizer.data, safe=False)
else:
return JsonResponse({'message': "User don't have a setting."}, safe=False)
And also make sure that updateTheme function works perfectly. If it doesn't work try following.
def updateTheme(request):
data = json.loads(request.body)
theme = data['theme']
user, created = User.objects.get_or_create(id=1)
setting = Setting.objects.get_or_create(user=user, value=theme, name='a name')
setting.save()
print('Request:', theme)
return JsonResponse('Updated..', safe=False)
Note that in the name field of Setting model you didn't pass null=True. So you have to pass name when creating a setting of a user.
Also in your base.html you are using onclick="swapStyle()" yet your javascript function is function swapStyles(){}. Change this
setting = getattr(user, 'setting', None)

Error in Django Get request that dosen't make sense

I have a basic Django app right now which allows users to add items to a database. When the product is added, the list of items should update when a new item is added via the form, and display that Product and all the other Products already in the database. Here is the code I have so far:
This is the views.py file with my current implementation of the method that should get the products at the bottom:
from django.shortcuts import render
from django.views.decorators.csrf import csrf_exempt
from products.models import Product
from django.http import HttpResponse, JsonResponse
def index(request):
return render(request, 'index.html')
#csrf_exempt
def createProduct(request):
if request.method == 'POST':
name = request.POST.get('name')
description = request.POST.get('description')
price = request.POST.get('price')
newProduct = Product(
name = name,
description = description,
price = price
)
newProduct.save()
return HttpResponse('')
def viewProduct(request):
if request.method == 'GET':
ProductList = Product.objects.all()
products=[]
for Product in ProductList:
products.append({"name": Product.name, "description": Product.description, "price": Product.price})
return JsonResponse(products)
The index.html page:
<!DOCTYPE html>
<html>
<body>
<div>
<h2 id="title">Create product</h2>
<input id="name">Name</input>
<br>
<input id="description">Description</input>
<br>
<input id="price">Price</input>
<br>
<button id="add-product">ADD PRODUCT</button>
</div>
<div id="productList">
</div>
</body>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script type="text/javascript">
document.getElementById('add-product').onclick = function(){
sendData();
getData();
}
function sendData(){
var order = {
name: document.getElementById('name').value,
description: document.getElementById('description').value,
price: document.getElementById('price').value
};
$.ajax({
type: "POST",
url: 'create/product',
data: order,
success: function(newProduct){
console.log("success"),
$('#name').val(""),
$('#description').val(""),
$('#price').val("")
}
});
};
function getData(){
$.ajax({
url: 'view/product',
dataType: 'json',
type: 'GET',
success: function(data){
$.each(data.Product, function(index, element){
$('body').append($('productList', {
text: element.name
}));
});
}
});
}
</script>
</html>
And the urls.py file:
from django.contrib import admin
from django.urls import path
from products import views
urlpatterns = [
path('admin/', admin.site.urls),
path('', views.index),
path('create/product', views.createProduct),
path('view/product', views.viewProduct)
]
So far, adding a product in is fine and causes no issues. However, after writing the getData() method and including it, this part dosen't work and returns the following error:
File "C:\Users\install\Documents\tutorial\products\views.py", line 29, in viewProduct
ProductList = Product.objects.all()
UnboundLocalError: local variable 'Product' referenced before assignment
I'm confused by this error as I'm not assigning Product anywhere else in this file so not sure why it's returning this error. When I do this same assignment in the Shell, it doesn't have a problem with it and returns all the objects. Can someone help me resolve this? Thanks.
The problem is here:
def viewProduct(request):
if request.method == 'GET':
ProductList = Product.objects.all()
products=[]
for Product in ProductList: # <= This is where cause the problem
products.append({"name": Product.name, "description": Product.description, "price": Product.price})
return JsonResponse(products)
You have to change for Product in ProductList to Something else like for _Product in ProductList
Try this one:
def viewProduct(request):
if request.method == 'GET':
ProductList = Product.objects.all()
products=[]
for prod in ProductList:
products.append({"name": prod.name, "description": prod.description, "price": prod.price})
return JsonResponse(products)

Django - Filtering objects using ajax post call data returns nothing

I have the following Ajax POST call:
$.ajax({
type: "POST",
url: "{% url 'meds:prescription' %}",
data: {selected:'selected' , csrfmiddlewaretoken: "{{ csrf_token }}"},
success: function(result) {
window.location = "{% url 'meds:prescription' %}";
}
});
Where selected is an array of ids for example [5, 9, 17]
And the following view:
class PrescriptionView(generic.ListView):
template_name = 'meds/prescription.html'
context_object_name = 'meds'
model = Medicament
def post(self, request, **kwargs):
selected_ids = self.request.POST.getlist('selected[]')
meds = self.get_queryset().filter(id__in=selected_ids)
return render(request, self.template_name, {'meds': meds})
def get_queryset(self):
ids = self.request.POST.getlist('selected[]')
return Medicament.objects.filter(id__in=ids)
def get_context_data(self, **kwargs):
ids = self.request.POST.getlist('selected[]')
context = super(PrescriptionView, self).get_context_data(**kwargs)
context.update({
'meds': Medicament.objects.filter(id__in=ids),
'date': datetime.now()
})
return context
What I'm trying to do is just to be redirected to the prescription template with the objects filtered using the data from the post call, but instead my template is just empty, I'm not sure what I'm doing wrong..
You are sending a string selected:'selected' not an array. Remove single quotes around selected in your ajax handler:
data: {selected:'selected' , csrfmiddlewaretoken: "{{ csrf_token }}"},
should be:
data: {selected: selected, csrfmiddlewaretoken: "{{ csrf_token }}"},

Likes feature in Django

I'm trying to implement a Like feature for my web app. Here is the code:
Model:
class Like(models.Model):
user = models.ManyToManyField(User, related_name='likes')
doctor = models.ForeignKey(Doctor)
date = models.DateTimeField(auto_now_add=True)
total_likes = models.IntegerField(default=0)
View:
def like(request):
vars = {}
if request.method == 'POST':
user = request.user
slug = request.POST.get('slug', None)
doctor = get_object_or_404(Doctor, slug=slug)
liked, created = Like.objects.create(Doctor=doctor)
try:
user_liked = Like.objects.get(Doctor=doctor, user=user)
except:
user_liked = None
if user_liked:
user_liked.total_likes -= 1
liked.user.remove(request.user)
user_liked.save()
else:
liked.user.add(request.user)
liked.total_likes += 1
liked.save()
return HttpResponse(simplejson.dumps(vars),
mimetype='application/javascript')
URL:
url(r'^like/(?P<id>\d+)/$', views.like, name='like'),
Template:
<input type="button" id="like" name="{{doctor_slug}}" value="Like" />
<script>
$('#like').click(function(){
$.ajax({
type: "POST",
url: "{% url like %}",
data: {'slug': $(this).attr('name'), 'csrfmiddlewaretoken': '{{csrf_token}}'},
dataType: "text",
success: function(response) {
alert('You liked this')
},
error: function(rs, e) {
alert(rs.responseText);
}
});
})
</script>
When I open my template page, I get the error NoReverseMatch at /docprofile/1/
'url' requires a non-empty first argument. The syntax changed in Django 1.5, see the docs. I looked at the docs but couldn't find anything that I could use here. The problem seems to be in the template at "url: "{% url like %}",". This is inside Ajax.
As the error says, you should see the docs. You need to pass the path to the view function or the name of the url to the url template tag as a string.
<script>
$('#like').click(function(){
$.ajax({
type: "POST",
url: "{% url 'like' %}",
data: {'slug': $(this).attr('name'), 'csrfmiddlewaretoken': '{{csrf_token}}'},
dataType: "text",
success: function(response) {
alert('You liked this')
},
error: function(rs, e) {
alert(rs.responseText);
}
});
})
</script>

Categories

Resources