I'm making a cart for an ecommerce project that I am working on, at the moment the cart does work. However it only works for one model and I'm not sure how to make it work with more than one.
This is my contexts.py file in my cart folder:
from django.shortcuts import get_object_or_404
from courses.models import Course
from food_order.models import Food_order
def cart_contents(request):
"""
Ensures that the cart contents are available when rendering
every page
"""
cart = request.session.get('cart', {})
cart_items = []
total = 0
course_count = 0
for id, quantity in cart.items():
course = get_object_or_404(Course, pk=id)
total += quantity * course.price
course_count += quantity
cart_items.append({'id': id, 'quantity': quantity, 'course': course})
return {'cart_items': cart_items, 'total': total, 'course_count': course_count}
Here is my views.py
from django.shortcuts import render, redirect, reverse
# Create your views here.
def view_cart(request):
"""A View that renders the cart contents page"""
return render(request, "cart.html")
def add_to_cart(request, id):
"""Add a quantity of the specified product to the cart"""
quantity = int(request.POST.get('quantity'))
cart = request.session.get('cart', {})
if id in cart:
cart[id] = int(cart[id]) + quantity
else:
cart[id] = cart.get(id, quantity)
request.session['cart'] = cart
return redirect(reverse('index'))
def adjust_cart(request, id):
"""
Adjust the quantity of the specified product to the specified
amount
"""
quantity = int(request.POST.get('quantity'))
cart = request.session.get('cart', {})
if quantity > 0:
cart[id] = quantity
else:
cart.pop(id)
request.session['cart'] = cart
return redirect(reverse('view_cart'))
So I have 2 different classes I would like to be able to add to the cart from 2 different places on the ecommerce site. I am just uncertain how to acheive this.
If I do something along the lines of:
from django.shortcuts import get_object_or_404
from courses.models import Course
from food_order.models import Food_order
def cart_contents(request):
"""
Ensures that the cart contents are available when rendering
every page
"""
cart = request.session.get('cart', {})
cart_items = []
total_food_order = 0
total_course = 0
total = 0
product_count = 0
for id, quantity in cart.items():
course = get_object_or_404(Course, pk=id)
food_order = get_object_or_404(Food_order, pk=id)
total_course += quantity * course.price
total_food_order += quantity * food_order.price
product_count += quantity
cart_items.append({'id': id, 'quantity': quantity, 'course': course, 'food_order':food_order})
total = total_course + total_food_order
return {'cart_items': cart_items, 'total': total, 'product_count': product_count}
Then the resulting cart_items will be:
[{'id': '1', 'quantity': 1, 'course': <Course: Basic Order Taking>, 'food_order': <Food_order: Onions>}, {'id': '2', 'quantity': 3, 'course': <Course: Advanced Order Taking>, 'food_order': <Food_order: Peppers>}]
I understand why it's doing this, but I cannot think of a way to adjust my code to get the desired result. Any pointers would be very appreciated.
Thank you for your time.
I would suggest making an base model for all your models that need to be added to the cart, and use multi-table inheritence.
class BaseCartItem(models.Model):
price = models.DecimalField()
item_type = models.CharField(max_length=20, editable_false)
....
def save(*args, **kwargs):
self.item_type = self._get_item_type()
return super().save(*args, **kwargs)
def _get_item_type(self):
raise NotImplementedError
class Course(BaseCartItem):
....
def _get_item_type(self):
return "Course"
class FoodOrder(BaseCartItem):
....
def _get_item_type(self):
return "Food Order"
# if you want to add to the db
class Cart(models.Model)
item = models.ForeignKey(BaseCartItem, on_delete=models.CASCADE)
quantity = models.PositiveIntegerField()
....
And in the views everything remains the same. You just use the ids of the base model rather than the child models.
The cart_contents is simplified a bit
def cart_contents(request):
"""
Ensures that the cart contents are available when rendering
every page
"""
cart = request.session.get('cart', {})
cart_items = []
item_groups = defaultdict(int)
total = 0
product_count = 0
items_map = {
item.id: item
for item in BaseCartItem.objects.filter(id__in=cart.keys()
}
for id, quantity in cart.items():
item = items_map[id]
item_group[item.item_type] += quantity * item.price
product_count += quantity
cart_items.append({'id': id, 'quantity': quantity, 'course': item, 'food_order':item})
total = sum(item_groups.values())
return {'cart_items': cart_items, 'total': total, 'product_count': product_count}
Related
Got AttributeError when attempting to get a value for field user on serializer cart_serializer.
The serializer field might be named incorrectly and not match any attribute or key on the QuerySet instance.
Original exception text was: 'QuerySet' object has no attribute 'user.
Views.py
class view_cart(APIView):
permission_classes = [IsAuthenticated]
def get(self, request, total=0, quantity = 0, cart_items=None):
grand_total = 0
delivery=0
cart = Cart.objects.get(user=request.user)
cart_items = CartItems.objects.filter(cart=cart)
print(cart_items)
for item in cart_items:
total += item.product.price * item.quantity
quantity += item.quantity
delivery = 150
grand_total = total + delivery
serializer = cart_serializer(
cart_items,
context={"total": total, "grand_total": grand_total, "delivery": delivery},
)
return Response(serializer.data)
Seralizer.py
class cart_serializer(ModelSerializer):
total = SerializerMethodField()
delivery = SerializerMethodField()
grand_total = SerializerMethodField()
class Meta:
model = Cart
fields = ["id", "user", "total", "delivery", "grand_total"]
def get_total(self, *args, **kwargs):
return self.context["total"]
def get_delivery(self, *args, **kwargs):
return self.context["delivery"]
def get_grand_total(self, *args, **kwargs):
return self.context["grand_total"]
Models.py
class Cart(models.Model):
user = models.ForeignKey(Account, on_delete=models.CASCADE)
date_added = models.DateTimeField(auto_now_add=True)
class Meta:
verbose_name_plural = 'Cart'
def __str__(self):
return self.user.email
class CartItems(models.Model):
cart = models.ForeignKey(Cart, on_delete=models.CASCADE)
product = models.ForeignKey(Products, on_delete=models.CASCADE)
quantity = models.IntegerField()
class Meta:
verbose_name_plural = 'Cart Items'
def sub_total(self):
return self.product.price * self.quantity
def __str__(self):
return self.product.product_name
Don't know why this error shows
The cart_serializer expect a Cart instance not a CartItems queryset.
class view_cart(APIView):
permission_classes = [IsAuthenticated]
def get(self, request, total=0, quantity = 0, cart_items=None):
grand_total = 0
delivery=0
cart = Cart.objects.get(user=request.user)
cart_items = CartItems.objects.filter(cart=cart)
print(cart_items)
for item in cart_items:
total += item.product.price * item.quantity
quantity += item.quantity
delivery = 150
grand_total = total + delivery
serializer = cart_serializer(
cart, # ==> Here use the cart instance..
context={"total": total, "grand_total": grand_total, "delivery": delivery},
)
return Response(serializer.data)
I'm trying to build reservation app. I tried to find the solution but I have no idea.
I want to compare date of reservation from check_availibility with date from form. In form I've made:
check_in = forms.DateField(required=True, input_formats=["%Y-%m-%dT%H:%M", ])
check_out = forms.DateField(required=True, input_formats=["%Y-%m-%dT%H:%M", ])
import datetime
def check_availability(room, check_in, check_out):
avail_list = []
booking_list = Booking.objects.filter(room=room)
for booking in booking_list:
if booking.check_in > check_out or booking.check_out < check_in:
avail_list.append(True)
else:
avail_list.append(False)
return all(avail_list)
from hotelbooking.booking_funkctions.availibility import check_availability
class BookingView(FormView):
form_class = AvalilabilityForm
template_name = 'availability_form.html'
def form_valid(self, form):
data = form.cleaned_data
room_list = Room.objects.filter(category=data['room_category'])
available_rooms=[]
for room in room_list:
if check_availability(room, data['check_in'], data['check_out']):
available_rooms.append(room)
if len(available_rooms)>0:
room = available_rooms[0]
booking = Booking.objects.create(
user = self.request.user,
room = room,
check_in = data['check_in'],
check_out = data['check_out']
)
booking.save()
return HttpResponse(booking)
else:
return HttpResponse('this category of rooms are booked')
Since you're cleaning the date it should already convert the date strings to date objects, so you can do this:
def check_availability(room, check_in, check_out):
avail_list = []
booking_list = Booking.objects.filter(room=room)
for booking in booking_list:
if booking.check_in.date() > check_out.date() or booking.check_out.date() < check_in.date():
avail_list.append(True)
else:
avail_list.append(False)
return all(avail_list)
Just call the .date() method for the datetime one:
from datetime import datetime, date
is_today_today = datetime.now().date() == date.today() # valid
print(is_today_today) # True # (the only time that is real is the present)
I don't understand why my test doesn't work. I have a page with product. There is a form with button 'Buy product'. After pushing this button, if a client have enough money, the item will bought and the amount of money in the account will change. But in my test the amount of money will be the same after buying a product, although the object(purchased item) will be created.
Purchased item model:
class BoughtItem(models.Model):
name = models.CharField(max_length=100, verbose_name='Название товара или акции', blank=True)
price = models.IntegerField(verbose_name='Цена', blank=True)
created_at = models.DateTimeField(auto_now_add=True)
Profile model:
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
money = models.IntegerField(default=0)
form:
class BuyForm(forms.ModelForm):
class Meta:
model = BoughtItem
fields = ('name',)
widgets = {'name': forms.HiddenInput()}
view:
class ItemDetailView(generic.DetailView):
model = Item
template_name = 'item_detail.html'
context_object_name = 'item'
def get_object(self, queryset=None):
return get_object_or_404(Item, pk=self.kwargs.get('pk'))
def post(self, request, *args, **kwargs):
buy_form = BuyForm(request.POST)
if buy_form.is_valid():
purchase = buy_form.save(commit=False)
item = self.get_object()
user = Profile.objects.get(user__username=request.user.username)
if user.money >= item.price:
sum_difference = user.money - item.price
user.money = sum_difference
user.save()
purchase.name = item.name
purchase.price = item.price
purchase.save()
return HttpResponseRedirect(reverse('account', kwargs={'username': request.user.username}))
else:
return HttpResponseRedirect(reverse('purchase_error'))
else:
return render(request, 'item_detail.html',
context={'buy_form': buy_form, 'object': self.get_object()})
urls:
urlpatterns = [
path('shop_list/', ShopListView.as_view(), name='shop_list'),
path('<str:name>', ItemListView.as_view(), name='shop_detail'),
path('item/<int:pk>', ItemDetailView.as_view(), name='item_detail'),
path('purchase_error/', purchase_error, name='purchase_error'),
]
test:
class ShopTest(TestCase):
#classmethod
def setUpTestData(cls):
Shop.objects.create(
name='Samsung',
description='Магазин электроники',
)
Item.objects.create(
name='Телефон Samsung A50',
description='Описание телефона',
price=20000,
shop_id=Shop.objects.get(name='Samsung').pk
)
user = User.objects.create(username='testuser')
user.set_password('12345')
user.save()
Profile.objects.create(
user=user,
money=100000
)
def test_if_change_field_money_after_purchase(self):
self.client.login(username='testuser', password='12345')
user = Profile.objects.get(user__username='testuser')
item = Item.objects.get(pk=1)
self.client.post(reverse('item_detail', kwargs={'pk': item.pk}))
self.assertNotEquals(user.money, 100000)
The changes have been saved to the DB but your object still contains the old data, call instance.refresh_from_db() to get the latest data from the DB
def test_if_change_field_money_after_purchase(self):
self.client.login(username='testuser', password='12345')
user = Profile.objects.get(user__username='testuser')
item = Item.objects.get(pk=1)
user.refresh_from_db()
self.assertNotEquals(user.money, 100000)
I am trying to adjust the cleaned_data that I get from the modelform to save certain values to the model based on the users input. These inputs can vary greatly, please see the model below along with the forms and views.
Should I call the model methods into the model form or should I do all the calculations in the modelForm itself. The figures can change depending on the contract selected and the start date selected as it will count the number of days and base it on this price for the contract, however if it is a half day then it will just divide the number by 2.
I am still new to Django but trying to figure out where all this information should be put, I am certainly clueless on this and trying to learn Django myself through real lifelike applications instead so appreciate your help.
Model
class AdminData(models.Model):
year1 = models.IntegerField()
year3 = models.IntegerField()
year1_fortnight = models.IntegerField()
year3_fortnight = models.IntegerField()
#property
def fortnight_dayrate_year1(self):
return self.year1_fortnight / weeksinyear / 5
#property
def fortnight_dayrate_year3(self):
return self.year3_fortnight / weeksinyear / 5
#property
def day_rate_year1(self):
return self.year1 / weeksinyear / 5
#property
def day_rate_year3(self):
return self.year3 / weeksinyear / 5
class Price(models.Model):
year_choice = Choices('1-Year Weekly', '3-Year Weekly','1-Year Fortnightly', '3-Year Fortnightly')
day_choice = Choices('Full Day', 'Half Day')
name = models.CharField(max_length=100)
contract = StatusField(choices_name='year_choice')
time_daily = StatusField(choices_name='day_choice')
start_date = models.DateField(default=datetime.now)
end_date = models.DateField(default=datetime(2021,3,31))
weeksinyear = 52
hours = 6.5
epoch_year = date.today().year
year_start = date(epoch_year, 1, 4)
year_end = date(epoch_year, 3, 31)
#property
def day_count(self):
return year_end - self.start_date
# #property
# def price_year1_weekly(self):
# if self.contract == self.year_choice[0]
# return AdminData.year1 * self.day_count
def __str__(self):
return self.name
Forms.py
class PriceForm(forms.ModelForm):
class Meta:
model = Price
fields = ['name', 'contract','time_daily','start_date']
Views.py
def price_detail(request):
if request.method == 'POST':
form = PriceForm(request.POST)
if form.is_valid():
price_instance = form.cleaned_data
form.save()
return render(request,'confirmation.html',{'form_data': price_instance})
else:
form = PriceForm()
return render(request, 'main.html', {'form': form})
For at the time of transaction calculations, the views.py is a good place for this, ie. a purchase, where the price is agreed upon at that moment and will never change.
If the business logic requires that the data updates the transaction, then the model is better.
views.py
def price_detail(request):
form = PriceForm(request.POST or None)
if form.is_valid():
price_instance = form.save() // this returns a saved instance
... do calculations here ...
price_instance.calculated_field = 1 + 1 // example calculations
price_instance.confirmed = False // consider adding a confirmed boolean, to not allow users to alter the data in the next step.
price_instance.save()
return render(request, 'confirmation.html', {'price_instance': price_instance})
else:
return render(request, 'main.html', {'form': form})
An example of doing the calculations every time the model is saved by overriding the model's save() method.
models.py
class Price(models.Model):
year_choice = Choices('1-Year Weekly', '3-Year Weekly','1-Year Fortnightly', '3-Year Fortnightly')
day_choice = Choices('Full Day', 'Half Day')
name = models.CharField(max_length=100)
contract = StatusField(choices_name='year_choice')
time_daily = StatusField(choices_name='day_choice')
start_date = models.DateField(default=datetime.now)
end_date = models.DateField(default=datetime(2021,3,31))
weeksinyear = 52
hours = 6.5
epoch_year = date.today().year
year_start = date(epoch_year, 1, 4)
year_end = date(epoch_year, 3, 31)
#property
def day_count(self):
return year_end - self.start_date
def save(self, *args, **kwargs):
... do calculations here ...
self.calculated_field = 1 + 1 // calculations
super().save(*args, **kwargs)
def __str__(self):
return self.name
I'm trying to make quiz_application by referring this one.https://github.com/tomwalker/django_quiz
When i try to access category page, i get this error.
NoReverseMatch at /quiz/category/
Reverse for 'quiz_category_list_matching' with arguments '()' and keyword arguments '{}' not found. 1 pattern(s) tried: ['quiz/category/(?P<category_name>[\\w-]+)/$']
My files are following,
urls.py
from django.conf.urls import patterns, url
from .views import QuizListView, CategoriesListView,\
ViewQuizListByCategory, QuizUserProgressView, QuizDetailView
urlpatterns = patterns('quiz.views',
url(regex=r'^$',
view=QuizListView.as_view(),
name='quiz_index'),
url(regex=r'^category/$',
view=CategoriesListView.as_view(),
name='quiz_category_list_all'),
url(regex=r'^category/(?P<category_name>[\w.-]+)/$',
view=ViewQuizListByCategory.as_view(),
name='quiz_category_list_matching'),
url(regex=r'^progress/$',
view=QuizUserProgressView.as_view(),
name='quiz_progress'),
# passes variable 'quiz_name' to quiz_take view
url(regex=r'^(?P<slug>[\w-]+)/$',
view=QuizDetailView.as_view(),
name='quiz_start_page'),
url(regex=r'^(?P<quiz_name>[\w-]+)/take/$',
view='quiz_take',
name='quiz_question'),
)
views.py
import random
from django.contrib.auth.decorators import login_required
from django.shortcuts import get_object_or_404, render, render_to_response
from django.template import RequestContext
from django.utils.decorators import method_decorator
from django.views.generic import DetailView, ListView, TemplateView
from .models import Quiz, Category, Progress, Sitting, Question
class QuizListView(ListView):
model = Quiz
class QuizDetailView(DetailView):
model = Quiz
slug_field = 'url'
class CategoriesListView(ListView):
model = Category
class ViewQuizListByCategory(ListView):
model = Quiz
template_name = 'view_quiz_category.html'
def get_context_data(self, **kwargs):
context = super(ViewQuizListByCategory, self)\
.get_context_data(**kwargs)
category = get_object_or_404(Category,
category=self.kwargs['category_name'])
context['category'] = category
return context
def get_queryset(self):
category = get_object_or_404(Category,
category=self.kwargs['category_name'])
queryset = super(ViewQuizListByCategory, self).get_queryset()
return queryset.filter(category=category)
class QuizUserProgressView(TemplateView):
template_name = 'progress.html'
#method_decorator(login_required)
def dispatch(self, request, *args, **kwargs):
return super(QuizUserProgressView, self)\
.dispatch(request, *args, **kwargs)
def get_context_data(self, **kwargs):
context = super(QuizUserProgressView, self).get_context_data(**kwargs)
progress = get_object_or_404(Progress, user=self.request.user)
context['cat_scores'] = progress.list_all_cat_scores()
context['exams'] = progress.show_exams()
return context
def quiz_take(request, quiz_name):
quiz = Quiz.objects.get(url=quiz_name.lower())
if request.user.is_authenticated() is True:
return user_load_sitting(request, quiz)
else: # anon user
return anon_load_sitting(request, quiz)
def user_load_sitting(request, quiz):
if quiz.single_attempt is True and\
Sitting.objects.filter(user=request.user,
quiz=quiz,
complete=True)\
.count() > 0:
return render(request, 'single_complete.html')
try:
sitting = Sitting.objects.get(user=request.user,
quiz=quiz,
complete=False)
except Sitting.DoesNotExist:
sitting = Sitting.objects.new_sitting(request.user, quiz)
except Sitting.MultipleObjectsReturned:
sitting = Sitting.objects.filter(user=request.user,
quiz=quiz,
complete=False)[0]
finally:
return user_load_next_question(request, sitting, quiz)
def user_load_next_question(request, sitting, quiz):
previous = False
if 'guess' in request.GET:
progress, created = Progress.objects.get_or_create(user=request.user)
guess = request.GET['guess']
question = sitting.get_first_question()
is_correct = question.check_if_correct(guess)
if is_correct is True:
sitting.add_to_score(1)
progress.update_score(question.category, 1, 1)
else:
sitting.add_incorrect_question(question)
progress.update_score(question.category, 0, 1)
if quiz.answers_at_end is not True:
previous = {'previous_answer': guess,
'previous_outcome': is_correct,
'previous_question': question,
'answers': question.get_answers(),
'question_type': {question.__class__.__name__: True}}
sitting.remove_first_question()
next_q = sitting.get_first_question()
if next_q is False:
# no questions left
return final_result_user(request, sitting, quiz, previous)
return render_to_response('question.html',
{'quiz': quiz,
'question': next_q,
'question_type': {next_q.__class__.__name__:
True},
'answers': next_q.get_answers(),
'previous': previous},
context_instance=RequestContext(request))
def final_result_user(request, sitting, quiz, previous):
score = sitting.get_current_score
incorrect = sitting.get_incorrect_questions()
max_score = quiz.get_max_score
incorrect_score = max_score - score
percent = sitting.get_percent_correct
sitting.mark_quiz_complete()
if quiz.exam_paper is False: # if we do not plan to store the outcome
sitting.delete()
if quiz.answers_at_end is False:
return render_to_response('result.html',
{'quiz': quiz,
'score': score,
'max_score': max_score,
'incorrect_score':incorrect_score,
'percent': percent,
'previous': previous},
context_instance=RequestContext(request))
else:
questions = quiz.get_questions()
return render_to_response('result.html',
{'quiz': quiz,
'score': score,
'max_score': max_score,
'incorrect_score':incorrect_score,
'percent': percent,
'questions': questions,
'incorrect_questions': incorrect},
context_instance=RequestContext(request))
def anon_load_sitting(request, quiz):
if quiz.single_attempt is True:
return render(request, 'single_complete.html')
if quiz.anon_q_list() in request.session:
return load_anon_next_question(request, quiz)
else:
return new_anon_quiz_session(request, quiz)
def new_anon_quiz_session(request, quiz):
"""
Sets the session variables when starting a quiz for the first time
"""
request.session.set_expiry(259200) # expires after 3 days
questions = quiz.get_questions()
question_list = [question.id for question in questions]
if quiz.random_order is True:
random.shuffle(question_list)
# session score for anon users
request.session[quiz.anon_score_id()] = 0
# session list of questions
request.session[quiz.anon_q_list()] = question_list
return load_anon_next_question(request, quiz)
def load_anon_next_question(request, quiz):
previous = False
if 'guess' in request.GET:
previous = question_check_anon(request, quiz)
request.session[quiz.anon_q_list()] = (request.
session[quiz.anon_q_list()][1:])
if not request.session[quiz.anon_q_list()]:
return final_result_anon(request, quiz, previous)
next_question_id = request.session[quiz.anon_q_list()][0]
next_question = Question.objects.get_subclass(id=next_question_id)
question_type = {next_question.__class__.__name__: True}
return render_to_response('question.html',
{'quiz': quiz,
'question': next_question,
'question_type': question_type,
'previous': previous},
context_instance=RequestContext(request))
def question_check_anon(request, quiz):
question = Question.objects.get_subclass(id=request.GET['question_id'])
is_correct = question.check_if_correct(request.GET['guess'])
if is_correct is True:
request.session[quiz.anon_score_id()] += 1
anon_session_score(request, 1, 1)
else:
anon_session_score(request, 0, 1)
if quiz.answers_at_end is not True:
return {'previous_answer': request.GET['guess'],
'previous_outcome': is_correct,
'previous_question': question}
else:
return {}
def anon_session_score(request, to_add=0, possible=0):
"""
Returns the session score for non-signed in users.
If number passed in then add this to the running total and
return session score
examples:
anon_session_score(1, 1) will add 1 out of a possible 1
anon_session_score(0, 2) will add 0 out of a possible 2
x, y = anon_session_score() will return the session score
without modification
"""
if "session_score" not in request.session:
request.session["session_score"] = 0
request.session["session_score_possible"] = 0
if possible > 0:
request.session["session_score"] = (request.session["session_score"] +
to_add)
request.session["session_score_possible"] = \
(request.session["session_score_possible"] + possible)
return request.session["session_score"], \
request.session["session_score_possible"]
def final_result_anon(request, quiz, previous):
score = request.session[quiz.anon_score_id()]
max_score = quiz.get_max_score
incorrect_score = max_score - score
percent = int(round((float(score) / max_score) * 100))
if score is 0:
score = "0"
session_score, session_possible = anon_session_score(request)
del request.session[quiz.anon_q_list()]
if quiz.answers_at_end is False:
return render_to_response('result.html',
{'score': score,
'max_score': max_score,
'incorrect_score':incorrect_score,
'percent': percent,
'previous': previous,
'session': session_score,
'possible': session_possible},
context_instance=RequestContext(request))
else:
questions = quiz.get_questions()
return render_to_response('result.html',
{'score': score,
'max_score': max_score,
'incorrect_score':incorrect_score,
'percent': percent,
'questions': questions,
'session': session_score,
'possible': session_possible},
context_instance=RequestContext(request))
category_list.html
{% extends 'base.html' %}
{% block title %}All Quizzes{% endblock %}
{% block content %}
<h2>Category list</h2>
<ul>
{% for cat in category_list %}
<li>
<a href="{% url 'quiz_category_list_matching' category_name=cat.category %}">
{{ cat.category }}
</a>
</li>
{% endfor %}
</ul>
{% endblock %}
I think the problem is url.py because i got some information when i searched.
Which part is wrong?
i understand the problem is that i cannot pass category_name in category_list.html to urls.py because when i remove <a href="{% url 'quiz_category_list_matching' category_name=cat.category %}">, it works even though the category list is not linked.
could you give me some idea to resolve this problem.
Django in CBV's by default assigns the model to object_list in order to override the assignment name change the context_object_name attribute:
class CategoriesListView(ListView):
model = Category
context_object_name = "category_list"