reverse_url is workin fine with a url that has-no/int:pk but does not work with a url that has /int:pk throws an error NoReverseMatch: Reverse for 'read_bty' with no arguments not found. 1 patterns tried:['read_bty/(?P[0-9]+)$']. The first (class=HBTYIndex) lists all customers created from the (class=HBTYCreateView) and the (class=HBTYReadView) displays the customers order records, the last (class=HBTYOrderView) is supposed to create an order and reverse_lazy to the url 'read_bty' but it keeps on throwing the above error when creating an order. Tried to change from int:pk to int:id still getting the same error. if i change the reverse_lazy to point to a url with no int:pk the record gets added and i get redirected to that page instead of staying on the same page and showing the new added record.
Views.py
class HBTYIndex(generic.ListView):
model = HbtyCustomers
context_object_name = 'bty'
paginate_by = 100
template_name = 'accounts/modals/bty/clientindex.html'
ordering = ['-id']
success_url = reverse_lazy('btylist')
def get_queryset(self):
qs = self.model.objects.all()
p_f = CustomerFilter(self.request.GET, queryset=qs)
return p_f.qs
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['filter'] = CustomerFilter(self.request.GET, queryset=self.get_queryset())
return context
# Create Customer
class HBTYCreateView(BSModalCreateView):
template_name = 'accounts/modals/bty/create_hbty.html'
form_class = btyForm
success_message = 'Success: Client was created.'
success_url = reverse_lazy('btylist')
# View Customer Orders History
class HBTYReadView(generic.ListView):
model = HbtyOrder
context_object_name = 'bty'
template_name = 'accounts/modals/bty/read_hbty.html'
allow_empty = False
pk_url_kwargs = 'hbtycustomer_pk'
paginate_by = 100
ordering = ['-id']
success_url = reverse_lazy('read_bty')
def get_queryset(self):
qs = self.model.objects.filter(hbtycustomer_id=self.kwargs['pk'])
p_f = HbtyOrdersFilter(self.request.GET, queryset=qs)
return p_f.qs
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['filter'] = HbtyOrdersFilter(self.request.GET, queryset=self.get_queryset())
return context
# Create New Order in the customer history page
class HBTYOrderView(BSModalCreateView):
template_name = 'accounts/modals/bty/create_hbty.html'
form_class = HairbtyOrderForm
success_message = 'Success: Order was created.'
success_url = reverse_lazy('read_bty')
read_hbty.html
<div class="row">
<div class="col-12 mb-3">
{% if filter.qs %}
{% include "accounts/modals/hairbty/vw_more.html" %}
{% else %}
<p class="no-books text-primary">No Client addeds yet.</p>
{% endif %}
</div>
</div>
Models.py
class HbtyCustomers(models.Model):
name = models.CharField(max_length=200, blank=False, null=True)
address = models.CharField(max_length=200, blank=False, null=True)
date = models.IntegerField(blank=False, null=True)
remarks = models.CharField(max_length=200, blank=False, null=True)
def __str__(self):
return self.name
class HbtyCategories(models.Model):
name = models.CharField(max_length=30)
def __str__(self):
return self.name
class HbtySubcategories(models.Model):
categ = models.ForeignKey(HbtyCategories, on_delete=models.CASCADE)
name = models.CharField(max_length=30)
def __str__(self):
return self.name
class HbtyOrder(models.Model):
STATUS = (
('Pending', 'Pending'),
('Out for delivery', 'Out for delivery'),
('Delivered', 'Delivered'),
)
categ = models.ForeignKey(HbtyCategories, on_delete=models.SET_NULL, blank=True, null=True)
subcateg = models.ForeignKey(HbtySubcategories, on_delete=models.SET_NULL, blank=True, null=True)
hbtycustomer = models.ForeignKey(HbtyCustomers, on_delete=models.SET_NULL, blank=True, null=True)
price = models.IntegerField(null=True)
date_created = models.DateTimeField(auto_now_add=True, null=True, blank=True)
status = models.CharField(max_length=200, null=True, choices=STATUS)
def __str__(self):
return str(self.id)
Urls.py
path('btylist/', views.HBTYIndex.as_view(), name="btylist"),
path('create_btycustomer/', views.HBTYCreateView.as_view(), name='create_btycustomer'),
path('create_btyorder/', views.HBTYOrderView.as_view(), name='create_btyorder'),
path('read_bty/<int:pk>', views.HBTYReadView.as_view(), name='read_bty'),
As you can tell from your urls.py, read_bty/HBTYReadView wants to see an int value named pk.
When you call that url in HBTYOrderView via reverse_lazy, you don't provide it, hence the error.
You can build out the success_url by creating a get_success_url method in your HBTYOrderView, rather than using a success_url property, something like:
def get_success_url(self):
return reverse_lazy('read_bty',kwargs={"pk": self.request.user.id} )
(I am assuming here that the ID that read_bty wants is the request.user.id )
Related
I have two models which I want to output on a template. But only if the parent class object matches to the child class object.
{% for market in markets %}
{% if object.market|slugify == market.market %}
>>> DO SOMETHING <<<
{% endif %}
{% endfor %}
The problem is when I use slugify on the Object it's giving me a string which starts with a small letter but market.market outputs a string with a capital letter.
Do someone know a solid solution for that?
UPDATE:
my Views:
class ItemDetailView(DetailView):
model = Item
template_name = "product.html"
def get_context_data(self, **kwargs):
context = super(ItemDetailView, self).get_context_data(**kwargs)
context['markets'] = Market.objects.all()
# And so on for more models
return context
def market_list(request):
context ={
'markets': Market.objects.all()
}
return render(request, "market-list.html", context)
My Models:
class Market(models.Model):
market = models.CharField(max_length=30)
branch = models.CharField(choices=BRANCH_CHOICES, max_length=1)
image = models.ImageField(blank=True)
slug = models.SlugField(blank=True)
def __str__(self):
return self.market
def get_absolute_url(self):
return reverse("core:market-product-list", kwargs={
'slug': self.slug
})
class Item(models.Model):
title = models.CharField(max_length=100)
market = models.ForeignKey(Market, related_name='children', on_delete=models.CASCADE, blank=True, null=True)
price = models.FloatField()
discount_price = models.FloatField(blank=True, null=True)
category = models.ForeignKey(ItemCategory, related_name='children', on_delete=models.CASCADE, blank=True, null=True)
label = models.CharField(choices=LABEL_CHOICES, max_length=1)
slug = models.SlugField()
description = models.TextField()
image = models.ImageField()
def __str__(self):
return self.title
I want my reviews that are on that particular product to be shown only on that product not on any other . I do not know how to filter it. Recently it is showing all the reviews on every product.
My models.py file is:
class Review(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
product = models.ForeignKey(Product , on_delete=models.CASCADE, null=True)
date = models.DateTimeField(auto_now_add=True)
text = models.TextField(max_length=3000 , blank=True)
rate = models.PositiveSmallIntegerField(choices=RATE_CHOICES)
likes= models.PositiveIntegerField(default=0)
dislikes = models.PositiveIntegerField(default=0)
def __str__(self):
return self.user.full_name
my product models.py is:
class Product(models.Model):
title = models.CharField(max_length=110)
slug = models.SlugField(blank=True, unique=True)
status = models.CharField(choices=CATEGORY_CHOICES, max_length=10)
price = models.DecimalField(decimal_places=2, max_digits=6)
quantity=models.IntegerField(default=1)
discount_price=models.FloatField(blank=True, null=True)
size = models.CharField(choices=SIZE_CHOICES, max_length=20)
color = models.CharField(max_length=20, blank=True, null=True)
image = models.ImageField(upload_to=upload_image_path)
description = RichTextField(max_length=1000)
featured = models.BooleanField(default=False)
author = models.ForeignKey(User, on_delete=models.CASCADE)
time_stamp = models.DateTimeField(auto_now_add=True)
my product detail views.py is:
class ProductDetailSlugView(ObjectViewedMixin,DetailView):
queryset = Product.objects.all()
context_object_name = "object_list"
template_name = "product_detail.html"
def get_context_data(self, *args ,**kwargs):
context = super(ProductDetailSlugView , self).get_context_data(*args, **kwargs)
context['reviews'] = Review.objects.all()
# context['reviews'] = Review.objects.filter(product=self.request.product)
cart_obj, new_obj = Cart.objects.new_or_get(self.request)
context['cart'] = cart_obj
# context['comments'] = Comment.objects.all()
return context
my product_detail.html is:
<!-- {% for review in reviews %}-->when i do this with my code it show me all the product
<!-- <h1>{{review.text}}{{review.rate}}</h1>-->
<!-- {% endfor %}-->
{% for review in product.review_set.all %}
{{ review.text }}
{% endfor %}
You do not need to make a query separately for your reviews. You can simply loop over them using your instance of Product in the template. Also for some reason you have set context_object_name = "object_list" try this:
{% for review in object.review_set.all %}
{{ review.text }}
{% endfor %}
Here review_set is simply the default related_name set by Django which is the related models name in lowercase with _set appended to it. You can chose to set the related name yourself like so if you want:
product = models.ForeignKey(Product, related_name='reviews', on_delete=models.CASCADE, null=True)
Anyway if you insist on modifying the view you can simply do this:
class ProductDetailSlugView(ObjectViewedMixin,DetailView):
queryset = Product.objects.all()
context_object_name = "object_list"
template_name = "product_detail.html"
def get_context_data(self, *args ,**kwargs):
context = super(ProductDetailSlugView , self).get_context_data(*args, **kwargs)
context['reviews'] = Review.objects.filter(product=self.object)
cart_obj, new_obj = Cart.objects.new_or_get(self.request)
context['cart'] = cart_obj
# context['comments'] = Comment.objects.all()
return context
And then you can use this:
{% for review in reviews %}
{{ review.text }}
{% endfor %}
I have made a blogger website on Django and I would have a page where the user can see/manage their own posts, so they can edit, update and delete.
I have tried to add the page but it keeps throwing an error saying no reverse match?
I am sure how to solve this problem, is something to do with how I have added the author in the Post model to PostAuthor?
This is my models file
class PostAuthor(models.Model):
user = models.OneToOneField(User, on_delete=models.SET_NULL, null=True)
bio = models.TextField(max_length=400, help_text="Enter your bio details here.")
class Meta:
ordering = ["user", "bio"]
def get_absolute_url(self):
return reverse('post-by-author', args=[str(self.id)])
def __str__(self):
return self.user.username
class Post(models.Model):
title = models.CharField(max_length=200, unique=True)
slug = models.SlugField(max_length=200, unique=True)
author = models.ForeignKey(PostAuthor, on_delete=models.CASCADE, null=True, blank=True)
updated_on = models.DateTimeField(auto_now=True)
content = models.TextField()
created_on = models.DateTimeField(auto_now_add=True)
status = models.IntegerField(choices=STATUS, default=0)
class Meta:
ordering = ['-created_on']
def get_absolute_url(self):
return reverse('post-detail', args=[str(self.id)])
def __str__(self):
return self.title
URLs file
urlpatterns = [
path('', views.IndexPage.as_view(), name='index'),
path('posts/', views.PostList.as_view(), name='all-posts'),
path('blog/<int:pk>', views.PostDetail.as_view(), name='post-detail'),
path('blog/<int:pk>', views.PostListbyAuthorView.as_view(), name='post-by-author'),
path('accounts/', include('django.contrib.auth.urls')),
]
Views file
class PostListbyAuthorView(generic.ListView):
model = Post
template_name = 'blog/post_list_by_author.html'
def get_queryset(self):
id = self.kwargs['pk']
target_author = get_object_or_404(PostAuthor, pk=id)
return Post.objects.filter(author=target_author)
def get_context_data(self, **kwargs):
context = super(PostListbyAuthorView, self).get_context_data(**kwargs)
context['blog'] = get_object_or_404(PostAuthor, pk=self.kwargs['pk'])
return context
class IndexPage(generic.ListView):
queryset = Post.objects.filter(status=1).order_by('-created_on')
template_name = 'blog/index.html'
class PostList(generic.ListView):
queryset = Post.objects.filter(status=1).order_by('-created_on')
template_name = 'blog/all_posts.html'
class PostDetail(generic.DetailView):
model = Post
template_name = 'blog/post_detail.html'
You are not passing the user's ID on your link, try this:
{% url 'post-by-author' pk=user.id %}
Models
attendance_choices = (
('absent', 'Absent'),
('present', 'Present')
)
class Head_of_department(models.Model):
first_name = models.CharField(max_length=200)
last_name = models.CharField(max_length=200)
email = models.CharField(max_length=30)
def __str__(self):
return self.first_name
class Employee(models.Model):
first_name = models.CharField(max_length=200, unique=True)
last_name = models.CharField(max_length=200, unique=True)
head_of_department = models.ForeignKey('Head_of_department', on_delete=models.SET_NULL, blank=True, null=True)
email = models.EmailField(max_length=100)
def __str__(self):
return self.first_name + ' ' + self.last_name
class Attendance(models.Model):
head_of_department = models.ForeignKey('Head_of_department', on_delete=models.SET_NULL, blank=True, null=True)
employee = models.ForeignKey('Employee', on_delete=models.CASCADE, )
attendance = models.CharField(max_length=8, choices=attendance_choices, blank=True)
Views
class Attendancecreate(CreateView):
model = Attendance
fields = ['employee']
success_url = '/dashboard/'
def get_context_data(self,** kwargs):
context = super(Attendancecreate, self).get_context_data(**kwargs)
context['formset'] = AttendanceFormset(queryset=Attendance.objects.none())
context['attendance_form'] = Attendanceform()
email = self.request.user.email
hod = Head_of_department.objects.get(email=email)
context["employees"] = Employee.objects.filter(head_of_department =hod)
return context
def get_initial(self):
email = self.request.user.email
hod = Head_of_department.objects.get(email=email)
initial = super(Attendancecreate , self).get_initial()
initial['employee'] = Employee.objects.filter(head_of_department=hod)
return initial
def post(self, request, *args, **kwargs):
formset = AttendanceFormset(request.POST)
if formset.is_valid():
return self.form_valid(formset)
def form_valid(self, formset):
instances = formset.save(commit=False)
for instance in instances:
instance.head_of_department = get_object_or_404(Head_of_department, email=self.request.user.email)
instance.save()
return HttpResponseRedirect('/dashboard/')
Forms
class Attendanceform(ModelForm):
class Meta:
model = Attendance
fields = ('employee','attendance','head_of_department')
AttendanceFormset = modelformset_factory(Attendance,fields=('attendance',))
Template
{% csrf_token %}
{{ formset.management_form }}
{% for employee in employees %}
{% for form in formset %}
{{employee.first_name}} {{ form }}
{ % endfor %}<br><br>
{% endfor %}
The webapp has a login feature. The headofdepartment can mark the attendance . List of employees are rendered in the template without any issues , I want to mark attendance to the respective employees sorted in ascending order of their first_name .
That is when marking attendance employees will be listed in template, and to the right attendance form will be displayed for all the employees . It is saving only one object and not assigning the initial value for employee
Requirement :
Following dirkgroten I was able to solve the issue, answer allow to render a list employees under the head_of_department(logged in hod) and mark respective attendance .
Models
attendance_choices = (
('absent', 'Absent'),
('present', 'Present')
)
class Head_of_department(models.Model):
first_name = models.CharField(max_length=200)
last_name = models.CharField(max_length=200)
email = models.CharField(max_length=30)
def __str__(self):
return self.first_name
class Employee(models.Model):
first_name = models.CharField(max_length=200, unique=True)
last_name = models.CharField(max_length=200, unique=True)
head_of_department = models.ForeignKey('Head_of_department', on_delete=models.SET_NULL, blank=True, null=True)
email = models.EmailField(max_length=100)
def __str__(self):
return self.first_name + ' ' + self.last_name
class Attendance(models.Model):
head_of_department = models.ForeignKey('Head_of_department', on_delete=models.SET_NULL, blank=True, null=True)
employee = models.ForeignKey('Employee', on_delete=models.CASCADE, )
attendance = models.CharField(max_length=8, choices=attendance_choices, blank=True)
Views
class Attendancecreate(CreateView):
model = Attendance
form_class = Attendanceform
success_url = '/dashboard/'
def get_context_data(self,** kwargs):
context = super(Attendancecreate, self).get_context_data(**kwargs)
context['formset'] = AttendanceFormset(queryset=Attendance.objects.none(), instance=Head_of_department.objects.get(email=self.request.user.email), initial=[{'employee': employee} for employee in self.get_initial()['employee']])
return context
def get_initial(self):
email = self.request.user.email
head_of_department = Head_of_department.objects.get(email=email)
initial = super(Attendancecreate , self).get_initial()
initial['employee'] = Employee.objects.filter(head_of_department=head_of_department)
return initial
def post(self, request, *args, **kwargs,):
formset = AttendanceFormset(request.POST,queryset=Attendance.objects.none(), instance=Head_of_department.objects.get(email=self.request.user.email), initial=[{'employee': employee} for employee in self.get_initial()['employee']])
if formset.is_valid():
return self.form_valid(formset)
def form_valid(self,formset):
instances = formset.save(commit=False)
for instance in instances:
instance.head_of_department = get_object_or_404(Head_of_department, email=self.request.user.email)
instance.save()
return HttpResponseRedirect('/dashboard/')
Forms
class Attendanceform(ModelForm):
class Meta:
model = Attendance
widgets = {'employee' : HiddenInput}
fields = ('employee','attendance','hod')
AttendanceFormset = inlineformset_factory(Head_of_department,Attendance,form=Attendanceform,fields=('attendance','employee'))
Template
{% csrf_token %}
{{ formset.management_form }}
{% for form in formset %}
{{ form.employee.initial }} {{ form.employee}} {{ form.attendance }}
<br><br>
{% endfor %}
I am having a trouble understanding what is wrong inside my code. Please can anybody tell me why the fields in locations = Location.objects.filter(user=add_profile.user) are not displayed in my html page.
models.py
class Location(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
my_location = models.CharField(max_length=120, choices=LOCATION_CHOICES)
update_date = models.DateField(auto_now=True, null=True)
date = models.DateField()
def __str__(self):
return self.my_location
class UserProfile(models.Model):
user = models.OneToOneField(User)
user_base = models.CharField(max_length=120, choices=LOCATION_CHOICES)
user_position = models.CharField(max_length=120)
user_phone = models.CharField(max_length=50)
first_name = models.CharField(max_length=120, null=True)
last_name = models.CharField(max_length=120, null=True)
slug = models.SlugField()
def save(self, *args, **kwargs):
self.slug = slugify(self.user)
super(UserProfile, self).save(*args, **kwargs)
def __unicode__(self):
return self.user.username
views.py
#login_required
def details(request, user_slug):
add_profile = UserProfile.objects.get(slug=user_slug)
locations = Location.objects.filter(user=add_profile.user)
print(locations)
context = {'add_profile': add_profile, locations: "locations"}
return render(request, 'details.html', context)
Though, the print(locations) is printing the requested data inside my cmd.
html code
{% for l in locations %}
<ul>
<li> {{l.my_location}} </li>
</ul>
{% endfor %}
My problem is that I am not having any an error to do know where to look.
Thank you.
Instead of
context = {'add_profile': add_profile, locations: "locations"}
should be
context = {'add_profile': add_profile, 'locations': locations}
Instead of using locations as value for context, you've used it as key and as value just the string "locations".