I need to make a view counter [duplicate] - python

This question already has answers here:
Hit counter for pages in Django
(3 answers)
Closed 3 years ago.
I have several articles, and when viewing them, it is necessary to calculate the number of these views for each article. And show how many views on the article
enter image description here
For example, I wanted to do this by clicking on the link so that it was added to "view = models.Integerfiels" 1
my models.py
from django.db import models
from taggit.managers import TaggableManager
class Articles(models.Model):
title = models.CharField(max_length= 200)
post = models.TextField()
date = models.DateTimeField()
img = models.ImageField(upload_to='', default="default_value")
tags = TaggableManager()
article_like = models.IntegerField(default='0')
article_dislike = models.IntegerField(default='0')
view = models.IntegerField(default='0')
font_size = models.IntegerField()
def __str__(self):
return self.title
views.py
class ArticleIndex(ListView):
model = Articles
template_name = 'news/posts.html'
class ArticleDetail(DetailView):
model = Articles
template_name = 'news/post.html'
urls.py
urlpatterns=[
path('', ArticleIndex.as_view(), name='articles_list'),
path('<int:pk>/', ArticleDetail.as_view(), name='article_detail'),
]+ static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

What i advise you to do here is to create your own view like that
from django.db.models import F
def ArticleDetailView(request, pk)
Articles.objects.filter(pk=pk).update(view=F('view') + 1)
article_details = Articles.objects.filter(pk=pk).first()
return render(request, 'the_path_to_your_detail_template.html', {'article_details': article_details})
In yout url.py you do like this :
path('your_url/<int:pk>/', views.ArticleDetailView, name='article_detail'),
In your forloop template where there all the article you just need to add the pk to the href of the anchor tag like this :
{{ article }}

Related

Page not found [404] in Django

I am trying to get all the post, posted in the same category. So my url looking like this, '..../category/Sports' where sports is a category. But if I enter this url, I got page, not found. I have also a html file called category. I also made makemigrations and migrate a several times
My views.py file:
from .models import Post, Category
..............
def CatView(request, cats):
posts = Post.objects.filter(category=cats)
return render(request,'category.html',{"cats":cats, 'posts':posts})
urls.py file:
from django.urls import path
from .views import *
urlpatterns = [
path('',HomeView.as_view(), name='home'),
path('article/<int:pk>', ArticleDetailView.as_view(), name='article_detail'),
path('add-post/', Addblogview.as_view(), name='add_post'),
path('add-category/', AddCategoryview.as_view(), name='add_category'),
path('article/edit/<int:pk>', UpdatethePost.as_view(), name='add_task'),
path('article/delete/<int:pk>', DeleteThePost.as_view(), name='delete_task'),
path('category/<int:cats>', CatView, name='category'),
]
If I change <str:cats> I ended up with ValueError Field 'id' expected a number but got 'Sports'
My models.py file:
from django.db import models
from django.contrib.auth.models import User
from django.urls import reverse
from datetime import datetime, date
class Category(models.Model):
name = models.CharField(max_length=255, default='uncategorized')
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('article_detail',args=str(self.id))
class Post(models.Model):
title = models.CharField(max_length=255)
title_tag=models.CharField(max_length=255)
author = models.ForeignKey(User,on_delete=models.CASCADE)
body = models.TextField()
post_date = models.DateField(auto_now_add= True)
category = models.ForeignKey(Category,on_delete=models.CASCADE)
def __str__(self):
return self.title + "|" + str(self.author)
def get_absolute_url(self):
return reverse('article_detail',args=str(self.id))
My category.html:
{{cats}}
You haven't set a primary key for Category, so the primary key becomes the numeric ID of the row, and the ForeignKey in Post needs to match that. You really want to set primary_key=True when you create the name field in Category.
Maybe you should just add a slash to the end of your URL in urls.py and try again? :)

Why am I getting a No Reverse Match Error

HI working on a new site using Django. can't seem to figure this bug out. First the intended site will be structured as;
Home page - Showing different languages with links to countries you can learn those languages in.
Click on a country on home page -> Country page
Country page will list all fo the schools that teach that language in that country.
Click on a school on country page -> School page.
I figured out this line of code in the Country page is causing the issue, but I don't know how to fix it
<a href="{% url 'schools' schools.id %}">
<div class="left"><h4>Test Link</h4></div>
</a>
This is the error I get in the browser
NoReverseMatch at /5/ Reverse for 'schools' with arguments '('',)' not found. 1 pattern(s) tried: ['(?P<country_id>[0-9]+)/(?P<schools_id>[0-9]+)/$']
Code from the project:
Models.py
from django.db import models
class Languages(models.Model):
language = models.CharField(max_length=100, blank=True, null=True)
country = models.ManyToManyField('Country', blank=True)
image = models.CharField(max_length=100, blank=True)
def __str__(self):
return self.language
class Country(models.Model):
country_name = models.CharField(max_length=50)
country_image = models.CharField(max_length=100, blank=True)
country_city = models.ManyToManyField('City', blank=True)
def __str__(self):
return self.country_name
class City(models.Model):
city_name = models.CharField(max_length=50)
city_image = models.CharField(max_length=1000, blank=True)
city_schools_in = models.ManyToManyField('Schools', blank=True)
def __str__(self):
return self.city_name
class Schools(models.Model):
school_name = models.CharField(max_length=100)
school_image = models.CharField(max_length=1000, blank=True)
school_country = models.ManyToManyField('Country', blank=True)
school_city = models.ManyToManyField('City', blank=True)
school_description = models.TextField()
school_accreditations = models.ManyToManyField('Accreditations', blank=True)
school_lpw = models.IntegerField()
school_cs = models.IntegerField()
school_course = models.ManyToManyField('CoursePrices', blank=True)
def __str__(self):
return self.school_name
class Accreditations(models.Model):
accreditation_name = models.CharField(max_length=50)
def __str__(self):
return self.accreditation_name
class CoursePrices(models.Model):
course_title = models.CharField(max_length=50, blank=True)
lessons_per_week = models.IntegerField()
class_size = models.IntegerField()
weekly_price = models.IntegerField()
language_level = models.CharField(max_length=50, blank=True)
def __str__(self):
return self.course_title
Views.py
from django.shortcuts import render
from django.http import Http404
from .models import Schools, CoursePrices, Languages, Country, City
def home(request):
languages = Languages.objects.all()
return render(request, 'home.html', {
'languages': languages,
})
def country(request, country_id):
try:
country = Country.objects.get(id=country_id)
except Languages.DoesNotExist:
raise Http404('Language not found')
return render(request, 'country.html', {
'country': country,
})
def schools(request, country_id, schools_id):
try:
schools = Schools.objects.get(id=schools_id)
except Schools.DoesNotExist:
raise Http404('school not found')
return render(request, 'schools.html', {
'schools': schools,
})
urls.py
from django.contrib import admin
from django.urls import path
from schools import views
urlpatterns = [
path('admin/', admin.site.urls),
path('', views.home, name='home'),
path('<int:country_id>/', views.country, name='country'),
path('<int:country_id>/<int:schools_id>/', views.schools, name='schools'),
]
Project structure screenshot
Any help would be greatly appreciated. Also please forgive any mistakes in posting or coding, still very new to coding and stack overflow / life in general :)
Your path named schools requires two arguments, you only passed one, so it failed to match any route.
Your comment on Rafael's answer that it is still not matching the path, even with two arguments provided, is because of the order of the paths in your urls.py file.
Django will go through the list of paths in order, and because a path with the single parameter country_id is found first it tries that but fails because you have a second parameter.
To fix that change the order of your paths
urlpatterns = [
path('admin/', admin.site.urls),
path('', views.home, name='home'),
# next two lines have been swapped.
path('<int:country_id>/<int:schools_id>/', views.schools, name='schools'),
path('<int:country_id>/', views.country, name='country'),
]
The 'schools' url needs two (2) arguments. You only pass one (1). In this case: schools.id
Django only finds a reverse match if you pass the correct amount of arguments. In this case, you should pass a country id AND a school id.
E.g. {% url 'schools' country_id=country.id schools_id=schools.id %} if you also have a country variable.
EDIT: '('',)' in your error message don't really look like integers. Are you sure the template variables exists and are integers?

Search field in Django is not redirecting to detail view

I am adding a search field in my blog so people can put the name of the blog they want to read and a list of items come up and after clicking on any of the list items, it will redirect to the detail view. However, in my case,If I put anything in search, it is not redirecting to a detail view but going to http://127.0.0.1:8000/home/search/2 instead of http://127.0.0.1:8000/home/list/2/.
I have posted my models, views, URLs and template files below.
Is there any reverse method I need to use here to redirect and what changes I need in my template file?
models.py
from django.db import models
class Category(models.Model):
cat_name = models.CharField(max_length = 256, blank = True)
def __str__(self):
return self.cat_name
class Blog(models.Model):
name = models.CharField(max_length = 256, blank = True)
pub_date = models.DateTimeField('date published')
text = models.TextField(blank = True)
category = models.ForeignKey(Category, on_delete=models.CASCADE,
related_name='categories', verbose_name = 'blog_categories')
def __str__(self):
return self.name
views.py
from django.shortcuts import render
from homepage.models import Blog
from django.views.generic import TemplateView, ListView, DetailView
from homepage import models
from django.db.models import Q
class Home(TemplateView):
template_name = 'homepage/index.html'
class BlogListView(ListView):
context_object_name = 'blogs'
model = models.Blog
template_name = 'homepage/blog_list.html'
class BlogDetailView(DetailView):
context_object_name = 'blogs_detail'
model = models.Blog
template_name = 'homepage/blog_detail.html'
def get_queryset(self):
query = self.request.GET.get('q')
return Blog.objects.filter(
Q(name__icontains = query) | Q(name__icontains = query) )
class SearchResultsListView(ListView):
model = Blog
context_object_name = 'blog_list'
template_name = 'homepage/search_result_list.html'
def get_queryset(self):
query = self.request.GET.get('q')
return Blog.objects.filter(
Q(name__icontains = query) | Q(name__icontains = query) )
urls.py
from django.urls import path
from homepage import views
from homepage.views import SearchResultsListView
app_name = 'homepage'
urlpatterns = [
path('', views.Home.as_view(), name = 'index'),
path('list/', views.BlogListView.as_view(), name = 'blog-list'),
path('list/<int:pk>/', views.BlogDetailView.as_view(), name = 'blog-list'),
path('search/', SearchResultsListView.as_view(), name = 'search_result'),
]
index.html
<div class="grid-item-1">
<h1>G</h1>
<input type="button" name="" value="Back to Home" placeholder="">
<form action="{% url 'home:search_result' %}" method = 'get'>
<input type="text" name="q" placeholder="search">
</form>
</div>
search_result_list.html
{% for blog in blog_list %}
<ul>
<li>
{{blog.name}}
{{blog.address}}
here
</li>
</ul>
{% endfor %}
the URL redirects to http://127.0.0.1:8000/home/search/2 and its a 404 page.
how can I redirect it to the detail view page http://127.0.0.1:8000/home/list/1/ and see the detail of the list pulled by search result.
The reason this happens is because {{ blog.id }} just contains a number, for example 2. It will be appended to the URL. You can fix this by prepending the URL with a slash (/) and write list with:
{{blog.name}}
{{blog.address}}
here
But it is likely better to make use of the {% url … %} template tag [Django-doc]:
{{blog.name}}
{{blog.address}}
here
In your BlogDetailView, there is no q parameter, so you can remove the get_queryset:
class BlogDetailView(DetailView):
context_object_name = 'blogs_detail'
model = models.Blog
template_name = 'homepage/blog_detail.html'
# no get_queryset
Furthermore perhaps you should consider renaming the DetailView from blog-list, to blog-detail, or something similar.

Django: How can I access and display details about the single "child" in the one-to-many relationship?

I have two models - the Company and Department. The Company can have many Departments - this is all connected with Foreign Key and works as expected. I have URLs and templates/views nicely setup and I can add the Company and then I can add Depratments to it. I am also able to access and create new Departments and assign them to the Company.
To see, say 5 last companies and last 5 Departments I have in the system I use this:
class IndexView(generic.ListView):
model = Company
template_name = 'company/index.html'
context_object_name = 'latest_company_list'
def get_queryset(self):
"""Return the last five created companies."""
return Company.objects.order_by('company_name')[:5]
class DeptIndexView(generic.ListView):
model = Department
template_name = 'department/index.html'
context_object_name = 'latest_department_list'
def get_queryset(self):
"""Return the last five created companies."""
return Department.objects.order_by('dept_name')[:5]
And here are the models from models.py
class Company(models.Model):
company_name = models.CharField(max_length=200)
company_dba = models.CharField(max_length=200)
class Meta:
verbose_name_plural = "companies"
def __str__(self):
return self.company_name
# on submit click on the company entry page, it redirects to the url below.
def get_absolute_url(self):
return reverse('company:index')
class Department(models.Model):
company = models.ForeignKey(Company, on_delete=models.CASCADE)
dept_name = models.CharField(max_length=200)
dept_code = models.IntegerField(default=0)
def __str__(self):
return self.dept_name
# on submit click on the department entry page, it redirects to the url below.
def get_absolute_url(self):
return reverse('company:index')
My urls.py file looks like this
app_name = 'company'
urlpatterns = [
# Company management views
path('', views.IndexView.as_view(), name='index'),
path('<int:pk>/', views.DetailView.as_view(), name='detail'),
path('add/', views.CompanyEntry.as_view(), name='add'),
path('update/<int:pk>/', views.CompanyUpdate.as_view(), name='update'),
path('delete/<int:pk>/', views.CompanyDelete.as_view(), name='delete'),
#Department management views
path('<int:pk>/department/', views.DeptIndexView.as_view(), name='dept_index'),
path('<int:pk>/department/add/', views.DeptEntry.as_view(), name='dept_add'),
path('<int:pk>/department/<int:fk>/', views.DeptDetailView, name='dept_detail'),
]
The issue here is that I don't know how to configure URL/path so that I can access details about one single Department.
I am trying to get something like http://127.0.0.1:8000/company/1/department/2/ where 2 is the id of the Department model.
And that last line in the code above doesn't seem to be working.
Instead, I am getting this as an error:
TypeError at /company/1/department/2/
init() takes 1 positional argument but 2 were given
Request Method: GET
Request URL: http://127.0.0.1:8000/company/1/department/2/
Django Version: 2.2.4
Exception Type: TypeError
Exception Value:
init() takes 1 positional argument but 2 were given
Exception Location: /Users/ABC/DjangoHR/lib/python3.7/site-packages/django/core/handlers/base.py in _get_response, line 113
I figured it out - I missed .as_view()
path('<int:pk>/department/<int:fk>/', views.DeptDetailView.as_view(), name='dept_detail'),
Thank you all for help and comments!

Django DetailView + urls with custom parameters

Simplified version of forum app in Django. What I want to do is have an url in the form of forum/forum_slug/thread_slug/. I have no idea how to define and pass the custom forum_slug to urlpatterns.
# models.py
class Forum(models.Model):
title = models.CharField(max_length=60)
slug = models.CharField(max_length=60)
# ...
def threads(self):
_threads = Thread.objects.filter(forum=self)
return _threads
class Thread(models.Model):
title = models.CharField(max_length=60)
slug = models.CharField(max_length=60)
forum = models.ForeignKey(Forum)
# ...
def get_absolute_url(self):
return '/%s/%s' % (self.forum.slug, self.slug)
class Post(models.Model):
title = models.CharField('Title', max_length=60)
thread = models.ForeignKey(Thread)
# ...
# ******************************************************
# views.py
# ******************************************************
class ForumDetail(MetadataMixin, DetailView):
model = Forum
context_object_name = 'forum'
template_name = 'forum/forum.html'
name='forum'
# meta...
class ThreadDetail(MetadataMixin, DetailView):
model = Thread
context_object_name = 'thread'
template_name = 'forum/thread.html'
name = 'thread'
# meta...
# ******************************************************
# urls.py
# ******************************************************
urlpatterns = patterns('',
url(r'^$',
'forum.views.index',
name='index'
),
url(r'^(?P<slug>[a-zA-Z0-9-]+)/?$',
ForumDetail.as_view()),
# here it comes
url(r'^(?P<forum_slug>[a-zA-Z0-9-]+/?P<slug>[a-zA-Z0-9-]+)/?$',
ThreadDetail.as_view()),
)
I assume that you want URL pattern for slugs. Below is the example you can try.
# URL example: /forum/this-is-a-forum-1/this-is-a-thread-1/
url(r'^forum/(?P<forum_slug>[\w-]+)/(?P<thread_slug>[\w-]+)$', ThreadDetail.as_view()),
Hope this helps.
#rayy: Thanks. No, this is not what I was looking for -- I simply do not know how to define forum_slug in it. That's what I was asking for. :-) Well, I figured out kinda more verbose solution but, frankly, I do not like it:
# models.py
from django.core.urlresolvers import reverse
class Thread(models.Model):
#... like before
def get_absolute_url(self):
return reverse('thread_url', (), {'forum_slug': self.forum.slug, 'slug': self.slug})
# urls.py
urlpatterns = patterns('',
# ...
url(r'^(?P<forum_slug>[\w-]+)/(?P<slug>[\w-]+)/$', ThreadDetail.as_view(), name='thread_url'),)
# index.html / forum.html (in a loop)
{{thread.title}}

Categories