redirecting with primary key from views.py - django

I have a view
(user_list.html)
{% extends "base.html" %}
{% load static %}
{% block content %}
<div class="list_main">
<div class="container">
{% for user in user_list %}
<ul>
<li><a href="{% url 'myapp:detail' pk=user.pk %}">
<div class="jumbotron">
<h4 class="list_content">{{user.name}}</h4>
</div>
</a></li>
</ul>
{% endfor %}
<div class="bttn">
<p><a type="button" class="btn btn-primary" href="{% url 'myapp:user' %}">Add</a></p>
</div>
</div>
</div>
{% endblock %}
Here with the help of
<p><a type="button" class="btn btn-primary" href="{% url 'myapp:user' %}">Add</a></p>
I am calling (views.py --> UserView)
def UserView(request):
response = requests.get('https://randomuser.me/api')
data = response.json()
title = data['results'][0]['name']['title']
first = data['results'][0]['name']['first']
last = data['results'][0]['name']['last']
final_name = " ".join([first,last])
#############################################
final_name = ". ".join([title, final_name]) #Final name of the user
#############################################
agee = data['results'][0]['dob']['age'] # age of the user
user = UserData.objects.create( name = final_name, age= agee, gender = gender)
user.save()
return redirect('detail', pk=user.pk) #This is not working
what I want to do is whenever the button from template (user_list.html) is clicked.
I want to enter this function in my views.py file perform the operations and redirect to
(path('detail/<int:pk>/', views.UserDetailView.as_view(), name='detail'),)
My views.UserDetailView
class UserDetailView(DetailView):
model = UserData
context_object_name = 'user_detail'
template_name = 'user_detail.html'
As shown in the code in( UserView(request) ), I have tried "return redirect('detail', pk=user.pk) "
this does not work.
Also please tell me if there is more neat and efficient way available to perform operations present in
( UserView(request) ) when button is clicked in ( user_list.html ) and then redirect from "UserView" to ((path('detail//', views.UserDetailView.as_view(), name='detail'),))

You missed app name myapp when using redirect:
return redirect('myapp:detail', pk=user.pk)

Related

How to add data to Django's database by the click of a button using JS and AJAX

I'm trying to add data that I rendered on a page from an API endpoint, to my database when I click "Add to my records" button, as can be seen in the image below, and I'm only trying to store "Date and Country" into the database (my model table has only date and country)
enter image description here
I've seen many resources talking about how JS and AJAX are useful in this case but I'm lost with logic of it all. Is there any way someone could explain how it's supposed to be done.
models.py
from django.db import models
class CountryData(models.Model):
country = models.CharField(max_length=100)
date = models.DateTimeField()
def __str__(self):
return self.country
views.py
def all_countries(request):
first_response = requests.get("https://api.covid19api.com/summary").json()
results = len(first_response["Countries"])
my_new_list = []
data_list = []
for i in range(0, results):
my_new_list.append(first_response["Countries"][i])
# print(my_new_list)
if request.method == "POST":
if request.POST.get("country") and request.POST.get("date"):
added_record = CountryData()
added_record.country = request.POST.get("country")
# 2022-12-19T08:53:48.179Z
added_record.date = datetime.datetime.strptime(
request.POST.get("date"), "%Y-%m-%dT%I:%M:%S.%fZ"
)
added_record.save()
return render(request, "allcountries.html")
else:
return render(request, "allcountries.html", )
context = {"my_new_list": my_new_list}
return render(request, "allcountries.html", context)
urls.py
from django.urls import path, include
from .views import home, all_countries
urlpatterns = [
path("", home, name="home"),
path("allcountries", all_countries, name="all_countries")
]
allcountries.html
{% extends '_base.html' %}
{% block page_title %} Covid19 Statistics For All Countries {% endblock %}
{% block content %}
<h3 class="text-center">Covid19 Statistics For All Countries </h3>
{% for object in my_new_list %}
<div class="row justify-content-center">
<div class="col-sm-10 d-flex justify-content-center">
<div class="card text-dark text-center" style="width: 20rem;">
<div class="card-block card-body">
<form method="POST" action="">
{% csrf_token %}
<h5 class="card-header" name="country">Country: {{object.Country}}, {{object.CountryCode}}</h5>
<br>
<p class="card-text">Total Confirmed Cases: {{object.TotalConfirmed}} </p>
<p class="card-text">Total Deaths Cases: {{object.TotalDeaths}} </p>
<p class="card-text">Total Recovered Cases: {{object.TotalRecovered}} </p>
<p class="card-text" name="date">Date: {{object.Date}}</p>
<button class="btn btn-success" type="submit">ADD TO MY RECORDS </button>
</form>
</div>
</div>
<br>
</div>
</div>
{% endfor %}
{% endblock %}
You can use the following ajax snippet to send data in the backend:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.1/jquery.min.js"></script>
<script>
$.ajax({
type: 'POST',
url: 'url', #leave blank if URL is same as the current one
data: {
'country': 'county_name',
'date': 'date_value',
},
success: function(response) {
# depending upon the response from the server you can make an alert here.
},
error: function(response){
# If some error occurred on the backend you can show error message from here
}
});
</script>

i cant specify a user to access my post in django

its a bit tricky for i tried solving it but cant,i am using class based views with customuser model, i have a blog post with multiple user i want to make it in a way only the main authour of a post should be allowed to delete or update post but i dont seems to know what to do or how to set it,here is my code kindly take a glance and release me from debugging,instead i get what i want wont get nothing and inatead i get something every author has the right to delete each other's post plus this is how i want it to look like when the user view its blog_detail but for non user it should be blank [![enter image description here][1]][1]
views.py
class BlogUpdateView(LoginRequiredMixin, UserPassesTestMixin, UpdateView):
model = Blog
fields = ['title', 'categories', 'overview', 'thumbnail', 'summary']
def form_valid(self, form):
form.instance.user = Doctor.objects.get(user=self.request.user)
return super().form_valid(form)
def test_func(self):
blog = Doctor.objects.get(user=self.request.user)
if self.request.user == blog.user:
return True
return False
class BlogDeleteView(LoginRequiredMixin, UserPassesTestMixin, DeleteView):
model = Blog
success_url = reverse_lazy('blog')
def test_func(self):
blog = Doctor.objects.get(user=self.request.user)
if self.request.user == blog.user:
return True
return False
blog_detail.html
{% extends "pages/base.html" %}
{% load static %}
{% block title %}Jazeera Blog{% endblock title %}
{% block meta %} the best medical-service website in Abuja {% endblock meta %}
{% block content %}
<br><p></p>
<section class="ftco-section bg-light" id="blog-section">
<div class="container">
<div class="row justify-content-center mb-5 pb-5">
<div class="col-md-10 heading-section text-center ftco-animate">
<h2 class="mb-4">Gets Every Single Updates Here</h2>
<p>Far far away, behind the word mountains, far from the countries Vokalia and Consonantia</p>
</div>
</div>
<div class="container">
<div class="row justify-content-center mb-5 pb-5">
<div class="col-lg-8 ftco-animate">
<h2 class="text-center">{{ object.title }}</h2>
<div class="meta mb-3 text-center">
<div><h6><span><a href = "">written By {{ object.user }}</span><small class="date"><i class="icon-clock"></i> {{ object.timestamp|timesince }} ago</small><a/></h6>
</div>
</div>
<div><small class="icon-eye text-danger">{{ object.view_count }}</small></div>
<div class="meta mb-3 text-center">
<h5>{% for cat in object.categories.all %}<span class="btn btn-dark">{{ cat }}</span> {% endfor %}</h5>
</div>
<p class="text-center">{{ object.overview }}</p>
{% if object.created_by == user %}
<a class="btn btn-secondary btn-sm mt mb-2" href="{% url 'blog-update' blog.id %}">Update</a>
<a class="btn btn-danger btn-sm mt mb-2" href="{% url 'blog-delete' blog.id %}">Delete</a>
{% endif %}
</div>
</div>
</div>
</div>
</section>
{% endblock content %}
##urls.py
path('blog/', BlogListView.as_view(), name='blog'),
path('blog/<int:pk>/', BlogDetailView.as_view(), name='blog-detail'),
path('blog/<int:pk>/update/', BlogUpdateView.as_view(), name='blog-update'),
path('blog/new/', BlogCreateView.as_view(), name='blog-create'),
path('blog/<int:pk>/delete/', BlogDeleteView.as_view(), name='blog-delete'),
[1]: https://i.stack.imgur.com/aojDX.jpg
You can restrict the set of Blog objects in the queryset to the ones that are written by the request.user:
class BlogDeleteView(LoginRequiredMixin, DeleteView):
model = Blog
success_url = reverse_lazy('blog')
def get_queryset(self, *args, **kwargs):
return super().get_queryset(*args, **kwargs).filter(
user=self.request.user
)
This will return a HTTP 404 error, if a user aims to remove a Blog object post where the post.user is not the logged in user.
In your views (BlogUpdateView and BlogDeleteView), update test_func to become;
def test_func(self):
blog = Doctor.objects.get(pk=self.kwargs.pk)
return self.request.user == blog.user
If you're testing for one condition in multiple views as you just did, it will be better creating a separate class for the test. Say, IsOwnerMixin where you perform the test and then inherit it in the required view(s).
Additionally, you can change {% if object.user == user %} in your blog_detail.html to become {% if user.is_authenticated and object.user == request.user %}
Good luck!

how do i create a profile page that shows all users post to the user and to other users

am new to Django and am trying to create a blog site where users can sign up and post articles, but my problem is how can I display a user's post on the user's profile page so that when other users reading the post clicks on the author's name it takes them to the post.author's profile page with the post.author's recent post listed and not the request.user's post. here is my code.
here is accounts/views.py
views.py
#login_required()
def user_profile_view(request, username):
post = User.objects.filter(courses__author=username)
context = {'courses': courses}
return render(request, 'accounts/user_profile_view.html', context)
and here is post/models.py
models.py
class Posts(models.Model):
author = models.ForeignKey(User, on_delete=models.CASCADE)
cover = ProcessedImageField(upload_to='post_featured_image',
processors=[ResizeToFill(600, 300)],
format='png',
options={'quality': 80},
blank=True)
slug = models.SlugField()
title = models.CharField(max_length=200)
body = models.TextField()
summary = models.TextField(max_length=200)
here is the template
post_list.html
{% extends 'base.html' %}
{% load static %}
{% block content %}
<div class="col-lg-6">
{% for course in courses_list %}
<div class="central-meta item">
<div class="user-post">
<div class="friend-info">
{% if post.author.profile.avatar %}
<figure>
<img src="{{ post.author.profile.avatar.url }}" alt="">
</figure>
{% else %}
<img src="{% static 'default.ico' %}" alt="">
{% endif %}
<div class="friend-name">
<ins>{{ course.author.get_full_name|title }}</ins>
<span>published: {{ post.published }}</span>
</div>
<div class="post-meta">
{% if course.cover %}
<img src="{{ post.cover.url }}" alt="">
{% endif %}
<div class="friend-name">
<ins>{{ course.title|title }}</ins>
</div>
<div class="description">
<p><span>{{ post.summary|capfirst }}</span></p>
</div>
</div>
</div>
</div>
</div>
{% endfor %}
</div>
{% endblock content %}
here is my accounts/urls.py
urls.py
app_name = 'accounts'
urlpatterns = [
path('accounts/profile/<str:username>/', user_profile_view, name='user_profile'),
]
you should be able do that, easy and via lots of ways.
make a post model like this:
class Post(models.Model):
author = foreign_key(User, related_name="posts", on_delete=models.CASCADE)
title = char_field()
content ........
so with that related name you will be able to reverse from user to its posts too!.
in your template do this:
{{ post.author }}
this link will redirect user to the posts author dashboard if you arrange the urls pattern correctly.
then for sorting authors posts, you have to pass the dashboard_owner to the template and use this name instead of user which normally will refer to the request.user -> user who are visiting the page
{% for post in dash_owner.posts.all %}
<li> <a href="{{ post.get_abslute_url }}" target="_blink">
{{ post.title }} </a> </li>
{% endfor %}
in views.py
def dashboard(request, owner_id=None)
if owner_id:
dash_owner = get_or_404(User, id=owner_id)
elif request.user.is_authenticated:
dash_owner = User.objectd.get(id=request.user.id)
return render(request, 'dashboard.html', {'dash_owner': dash_owner})
in urls.py -> urlpatterns:
path('dashboard/<int:owner_id>/', views.dashboard, name="dashboard")
this is the idea behind that, but for get the better result, you may need to clearly define the get_absolute_url of User model, to give you the url which machts to
'dashboard/<int:id/'
or another way is instead of that, do this:
{{ post.author }}

How to render template after failed form validation?

urls.py:
urlpatterns = [
path('employee/add_employee/', views.add_employee, name='add-employee'),
path('employee/add_employee/add/', views.add_employee_action, name='add-employee-action'),
]
I have add-employee page and some forms to fill there.
views.py:
def add_employee(request):
personal_form = PersonalEmployeeForm()
history_form = EmployeeHistoryForm()
return render(
request,
'sections/add_employee.html',
context={
'personal_form': personal_form,
'history_form': history_form,
}
)
def add_employee_action(request):
if request.method == "POST":
personal_form = PersonalEmployeeForm(request.POST)
history_form = EmployeeHistoryForm(request.POST)
if personal_form.is_valid() and history_form.is_valid():
# here is some logic with models
return redirect('add-employee')
else:
personal_form = PersonalEmployeeForm()
history_form = EmployeeHistoryForm()
return render(
request,
'sections/add_employee.html',
context={
'personal_form': personal_form,
'history_form': history_form,
}
)
template:
<form id="a-submit-form" action="add/" method="POST">
{% csrf_token %}
<div class="column-wrapper">
<div class="column">
<div class="form-wrapper">
{% for field in personal_form.visible_fields %}
{% include "elements/forms/form_line.html" %}
<br>
{% endfor %}
</div>
</div>
<div class="column">
<div class="form-wrapper">
{% for field in history_form.visible_fields %}
{% include "elements/forms/form_line.html" %}
<br>
{% endfor %}
</div>
</div>
</div>
<div class="button-bar-wrapper">
<div class="button_bar">
<a class="a-button positive" id="submit">Добавить</a>
<a class="a-button" href="{% url 'employee' %}">Сотрудники</a>
<a class="a-button" href="{% url 'index' %}">На главуную</a>
</div>
</div>
</form>
Submitting by <a> element is tested and worked well with jQuery script.
The problem is after submitting invalid forms I have a page with blah-blah/employee/add_employee/add/ URL. And if I try to submit forms again I have a page with blah-blah/employee/add_employee/add/add/ URL, which is incorrect. How can I render the page with blah-blah/employee/add_employee/ URL and show all error messages?
This is likely because you have written a relative URL in the <form> tag of the sections/add_employee.html template. The template thus contains something like:
<form method="post" action="add/">
...
</form>
You can use a URL with the {% url … %} template tag [Django-doc]:
<form method="post" action="{% url 'add-employee-action' %}">
...
</form>
Furthermore one usually uses the same path to handle both the GET and the POST request. So in fact you might simply remove the 'add-employee' path.

Reverse for 'user_review_list' not found. 'user_review_list' is not a valid view function or pattern name

Even after going through similar STACKOVERFLOW solutions this doubt was not solved.
I have also been through other resources.
Been engaged in django since 2 days only !! :)
project -> winerama
app ->reviews
my views.py
def review_list(request):
latest_review_list =Review.objects.order_by('-pub_date')[:9]
context ={'latest_review_list': latest_review_list}
return render(request, 'reviews/review_list.html',context)
def wine_list(request):
wine_list =Wine.objects.order_by('-name')
context ={'wine_list':wine_list}
return render(request, 'reviews/wine_list.html',context)
def review_detail(request , review_id):
review = get_object_or_404(Review , pk = review_id)
context = {'review':review}
return render(request,'reviews/review_detail.html',context)
def wine_detail(request , review_id):
wine = get_object_or_404(Wine, pk = wine_id)
context = {'wine':wine}
return render(request,'reviews/wine_detail.html',context)
def add_review(request,wine_id):
wine = get_object_or_404(Wine , pk = wine_id)
form = ReviewForm(request.POST)
if form.is_valid():
rating = form.cleaned_data['rating']
comment = form.cleaned_data['comment']
user_name=form.cleaned_data['user_name']
review =Review()
review.wine = wine
review.user_name = user_name
review.user_name = user_name
review.rating =rating
review.comment = comment
review.pub_date = datetime.datetime.now()
review.save()
return HttpRespponseRedirect(reverse('reviews:wine_detail',args = (wine.id,)))
return render(request,'reviews/wine_detail.html',{'wine':wine,'form':form})`
reviews/urls.py
urlpatterns = [
# ex: /
url(r'^$', views.review_list, name='review_list'),
# ex: /review/5/
url(r'^review/(?P<review_id>[0-9]+)/$', views.review_detail, name='review_detail'),
# ex: /wine/
url(r'^wine$', views.wine_list, name='wine_list'),
# ex: /wine/5/
url(r'^wine/(?P<wine_id>[0-9]+)/$', views.wine_detail, name='wine_detail'),
url(r'^wine/(?P<wine_id>[0-9]+)/add_review/$', views.add_review, name='add_review'),
]
reviews/templates/reviews/base.html
{% block bootstrap3_content %}
<div class="container">
<nav class="navbar navbar-default">
<div class="navbar-header">
<a class="navbar-brand" href="{% url 'review_list' %}">Winerama</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li>Wine list</li>
<li>Home</li>
</ul>
</div>
</nav>
<h1>{% block title %}(no title){% endblock %}</h1>
{% bootstrap_messages %}
{% block content %}(no content){% endblock %}
</div>
{% endblock %}
THANKS IN ADVANCE.
PLEASE HELP ME FOR THE SAME.
The error is self explanatory:
Somewhere in your template html you have written
{% url 'user_review_list' %}
That means you are calling user_review_list function, but it is not defined in views. Instead you have defined review_list function.