Pass parameters to view but not using them - django

I have a view:
def product_details(request, brand_id, slug, product_id):
product = get_object_or_404(Product, id=product_id)
return render(request, 'product_details.html',
{'product': product})
urls.py:
urlpatterns = patterns('',
url(r'^$', 'core.views.show_brands', name='brands'),
url(r'^(?P<brand_id>\d+)/(?P<slug>[-\w\d]+)/$', 'core.views.brand_products', name='brand_products'),
url(r'^(?P<brand_id>\d+)/(?P<slug>[-\w\d]+)/(?P<product_id>\d+)/$', 'core.views.product_details', name='product_detail'),
)
The question is: should I pass brand_id and slug if I don't use them? I pass for human-readable url. Url example: http://127.0.0.1:8000/brands/1/coca_cola/3/

If you don't need the parameters, you can make them optional for the view and leave them in the URL like so:
def product_details(request, product_id):
product = get_object_or_404(Product, id=product_id)
return render(request, 'product_details.html',
{'product': product})
urls.py:
urlpatterns = patterns('',
url(r'^(\d+)?/([-\w\d]+)?/(?P<product_id>\d+)/$', 'core.views.product_details', name='product_detail'),
)
Notice the "?" after the first two matched regular expressions, making them optional. This means you can leave them out of the view, but reverse('product_detail', brand_id, slug, product_id) will still return a legible URL.

views.py
def product(request, id, slug):
context = {}
context['product'] = get_object_or_404(Product, id=id, slug=slug)
return render(request, 'html', context)
urls.py
url(r'^product/(?P<slug>\w+)/(?P<id>\d+)/$', views.product, name='product')

Related

TypeError at /add-to-cart/1/

my add to cart was working fine and when i retry few pages later it gaves me that error
TypeError at /add-to-cart/1/
add_to_cart() missing 1 required positional argument: 'request'
My view:
def add_to_cart(LoginRequiredMixin, request, slug):
item = get_object_or_404(Item, slug=slug)
order_item, created = OrderItem.objects.get_or_create(
item=item,
user=request.user,
ordered=False
)
order_qs = Order.objects.filter(user=request.user, ordered=False)
if order_qs.exists():
order = order_qs[0]
# check if the order item is in the order
if order.items.filter(item__slug=item.slug).exists():
order_item.quantity += 1
order_item.save()
messages.info(request, "This item quantity was updated.")
return redirect("core:order-summary")
else:
order.items.add(order_item)
messages.info(request, "This item was added to your cart.")
return redirect("core:order-summary")
else:
ordered_date = timezone.now()
order = Order.objects.create(
user=request.user, ordered_date=ordered_date)
order.items.add(order_item)
messages.info(request, "This item was added to your cart.")
return redirect("core:order-summary")
my url:
urlpatterns = [
path('add-to-cart/<slug>/', add_to_cart, name='add_to_cart'),
]
Not sure what went wrong, help please.
You can not use the LoginRequiredMixin mixin [Django-doc] as parameter, this is a function, not a class. The Mixin is mixed in the method resolution order (MRO) of a class. You can use the #login_required decorator [Django-doc] on a function:
from django.contrib.auth.decorators import login_required
#login_required
def add_to_cart(request, slug):
# …
You can also restrict the slug parameter to only match on valid slugs with:
urlpatterns = [
path('add-to-cart/<slug:slug>/', add_to_cart, name='add_to_cart'),
]

Transform function to class based view (recall same site)

Very similar to these questions I want to transform my view. The difference is that I want to return to the same page and I have problems adjusting my urls.py (I think):
So on the product_all.html I press a button and end up on the same page after the product was deleted:
def delete_product(request, pk):
Product.objects.filter(id=pk).delete()
context = {'Product': Product.objects.all()}
return render(request, 'gbkiosk/product_all.html', context)
urls.py:
path("product_delete/<int:pk>", views.delete_product, name='product-delete'),
I wanted to recreate that using a TemplateView:
class DeleteProduct(TemplateView):
template_name = "gbkiosk/device_all.html"
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
Product.objects.filter(id=kwargs["product_id"]).delete()
context["products"] = Product.objects.all()
return context
but what would the corresponding urls.py entry be?:
path("product_delete/<int:product_id>", views.DeleteProduct.as_view(), name="product-delete")
This will not return me to product_all.html after clicking?
You should have a ListView to list the products and a DeleteView to delete the ones you like. That's cleaner.
So, it'd be something like:
views.py
class Products(ListView):
model = Product
class ProductDelete(DeleteView):
model = Product
success_url = reverse_lazy('product-list')
urls.py
from django.urls import path
from products.views import ProductListView
urlpatterns = [
path('', ProductListView.as_view(), name='product-list'),
path('<int:pk>', ProductDeleteView.as_view(), name='product-delete'
]
This is how I did it:
class ProductDeleteView(DeleteView):
model = Product
def get_success_url(self):
return reverse_lazy('product-list')
def get(self, request, *args, **kwargs):
return self.post(request, *args, **kwargs)
def get_context_data(self, **kwargs):
context = super(ProductDeleteView, self).get_context_data(**kwargs)
print(kwargs)
return(context)
urls:
path("product_delete/<int:pk>", views.ProductDeleteView.as_view(), name='product-delete'),

Django - changing ID field

So I understand it's not good practice to use the keyword - ID. So, I tried changing the id below to cid. However, when I do this I get: testing() got an unexpected keyword argument 'id'. If I change it back from cid to ID. Everything works just fine. What am I doing wrong?
def testing(request, cid):
"""Testing sheet for controls"""
if request.method == "GET":
testing_sheet = IsoControls.objects.get(pk=cid)
form = forms.ControlTesting(instance=testing_sheet)
return render(request, 'controls_app/testing_sheet.html', {'form':form})
else:
testing_sheet = IsoControls.objects.get(pk=cid)
form = forms.ControlTesting(request.POST, instance=testing_sheet)
if form.is_valid():
form.save()
return render(request, 'controls_app/testing_sheet.html', {'form':form})
Updating based on comments.
My URL is
urlpatterns = [
path('', views.home, name='home'),
path('<int:id>', views.testing, name='testing')
]
In my html
<td>
<i class="fas fa-edit"></i>
</td>
def testing(request, pk):
"""Testing sheet for controls"""
testing_sheet = IsoControls.objects.get(id=pk)
form = forms.ControlTesting(instance=testing_sheet)
if request.method=='POST':
form = forms.ControlTesting(request.POST, instance=testing_sheet)
if form.is_valid():
form.save()
return redirect('../your_given_path_name')
return render(request, 'controls_app/testing_sheet.html', {'form':form})
Ok - so this was a silly mistake. I changed it CID in my views but i also needed to change the URL partern to CID.
URL:
urlpatterns = [
path('', views.home, name='home'),
path('<int:cid>', views.testing, name='testing')
]
Views
def testing(request, cid):
"""Testing sheet for controls"""
if request.method == "GET":
testing_sheet = IsoControls.objects.get(pk=cid)
form = forms.ControlTesting(instance=testing_sheet)
return render(request, 'controls_app/testing_sheet.html', {'form':form})
else:
testing_sheet = IsoControls.objects.get(pk=cid)
form = forms.ControlTesting(request.POST, instance=testing_sheet)
if form.is_valid():
form.save()
return render(request, 'controls_app/testing_sheet.html', {'form':form})

How to redirect to a page after deleting in django?

I am trying to redirect to a page after deleting an object I don't know but it's not working. The object gets deleted but it doesn't redirect to any page can someone please help me ?
If you need more code you can ask me.
Thank you !
Views of deleting product
#login_required()
def delete_product(request, product_id):
delete = get_object_or_404(Product, pk=product_id)
form = NewPro(instance=delete)
if request.method == 'POST':
form = NewPro(request.POST, request.FILES, instance=delete)
if form.is_valid():
delete.delete()
return redirect('store_details')
else:
form = NewPro(instance=delete)
return render(request, "default/product_delete.html", {'form': form, 'delete': delete})
url pattern
from django.urls import path
from . import views
from stores.urls import views
app_name = 'stores'
urlpatterns = [
path('<int:store_id>/store_details/', views.store_details, name='store_details'),
]
urlpatterns = [
path('<int:product_id>/product', views.product, name='products_details'),
path('add_products/', views.pro, name='add_products'),
path('', views.index_products, name='index_products'),
path('<int:product_id>/detail_product', views.detail_product, name='detail_product'),
path('<int:product_id>/edit_product', views.edit_product, name='edit_product'),
path('<int:product_id>/delete_product', views.delete_product, name='delete_product')
]
The error indicate that django cannot resolve the path of the view store_details. You can use the reverse method from django.urls.
from django.urls import reverse
#login_required()
def delete_product(request, product_id):
delete = get_object_or_404(Product, pk=product_id)
form = NewPro(instance=delete)
if request.method == 'POST':
# if this form is not valid we rander it again, so no need for else statement
form = NewPro(request.POST, request.FILES, instance=delete)
if form.is_valid():
delete.delete()
return redirect(reverse('stores:store_details'))
# if it's not POST method render an empty form
else:
form = NewPro()
return render(request, "default/product_delete.html", {'form': form, 'delete': delete})
urls.py of product app:
from django.urls import path
from . import views
app_name = 'product'
urlpatterns = [
path('<int:product_id>/product', views.product, name='products_details'),
path('add_products/', views.pro, name='add_products'),
path('', views.index_products, name='index_products'),
path('<int:product_id>/detail_product', views.detail_product, name='detail_product'),
path('<int:product_id>/edit_product', views.edit_product, name='edit_product'),
path('<int:product_id>/delete_product', views.delete_product, name='delete_product')
]
urls.py of stores app:
from django.urls import path
from . import views
app_name = 'stores'
urlpatterns = [
path('<int:store_id>/store_details/', views.store_details, name='store_details'),
]
app_name attribute in the included URLconf module help in the reverse resolution of URLs
I hope this will help.
You're not setting the form for the post request, move the else: back a tab.
Correct Syntax:
#login_required()
def delete_product(request, product_id):
delete = get_object_or_404(Product, pk=product_id)
form = NewPro(instance=delete)
if request.method == 'POST':
form = NewPro(request.POST, request.FILES, instance=delete)
if form.is_valid():
delete.delete()
return redirect('store_details')
else:
form = NewPro(instance=delete)
return render(request, "default/product_delete.html", {'form': form, 'delete': delete})

Django Redirect treating view as a URL

For some reason, Redirect thinks my call to a view 'clients.views.teacher_profile' is a URL, putting it directly in the address bar as shown:
Page Not Found Screenshot
How do I link it to the view and not treat it as a URL?
Note: I have altered some settings to accommodate django-allauth.
My code:
#views.py
def teacher_profile(request, username):
user = get_object_or_404(User, username=username)
context = {
'user':user,
'teacher':user.teacher,
}
return render(request, 'clients/teacher_profile.html', context)
def edit_profile(request):
teacher = get_object_or_404(Teacher, user=request.user)
if request.method == 'POST':
form = TeacherForm(request.POST, instance=teacher)
if form.is_valid():
teacher = form.save(commit=False)
teacher.user = request.user
teacher.save()
return redirect('clients.views.teacher_profile', username=request.user.username)
else:
form = TeacherForm(instance=teacher)
return render(request, 'clients/edit_profile.html', {'form':form})
#urls.py
urlpatterns = [
url(r'^list/$', views.teacher_list, name='teacher_list'),
url(r'^(?P<username>[\w.#+-]+)/$', views.teacher_profile, name='teacher_profile'),
url(r'^accounts/settings/$', views.edit_profile, name='edit_profile'),
]
Don't use the view's module path in the call to redirect; use the name which you explicitly defined in the url pattern.
return redirect('teacher_profile', username=request.user.username)