I want to create a management page where an admin can delete users. I have succesfully made it list created users, but now i'm struggeling with how to create a deleteView to delete the user entirely from my django project.
Views.py
def index(request):
users = User.objects.all()
return render(request, 'EditUser.html',{'userlist':users})
def deletefunction(request,User =None):
object = User.objects.get(id=User)
object.delete()
return render(request,'EditUser.html')
Project urls.py
from edit_user.views import deletefunction
urlpatterns = [
path('admin/', admin.site.urls),
path('management', include('management.urls')),
path('management/create', include('signup.urls')),
path('management/edit', include('edit_user.urls')),
path('^delete/(?P<User>[0-9]+)/$', deletefunction, name='delete_view'),
]
HTML code
<div class="container">
{% for item in userlist %}
<tr>
<td>{{ item.username }}</td>delete
</tr>
{% endfor %}
</div>
As of right now when i'm trying to load my page i'm receiving this exception.
Reverse for 'deletefunction' not found. 'deletefunction' is not a
valid view function or pattern name.
def deletefunction(request, user_id):
object = User.objects.get(id=user_id)
object.delete()
users = User.objects.all()
return render(request,'EditUser.html', {'userlist': users})
and
<div class="container">
{% for item in userlist %}
<tr>
<td>{{ item.username }}</td>delete
</tr>
{% endfor %}
</div>
I think you should delete EditUser in href. Because you url in project urls.py(not EditUser urls ). So django looks EditUser app_name but they cant find.
Also you had not determineted 'User'.And you url name "delete_view" but you send view name.Can you change like this?Maybe work.
<td>{{ item.username }}</td>delete
Related
I'm building an instagram-ish clone in Django. I have the basic functionality working, where a user can post an image, and this is displayed on the main page. I would like to make a 'user page' that only displays posts from a user. For example, example.com/foobar would only display posts from the user 'foobar'.
I believe i have the urls.py and template working correctly, but I can not figure out how to only iterate through items and pull out ones of a specific user. I realize this should be a queryset of some kind, but other than that I'm stumped. Should this be its own class, or could I extend the existing PostList class to pull out a single author's posts?
post_detail.html - gets all the images stored in the database, this works fine.
{% for post in object_list %}
<td><img src="{{ post.image.url }}" width="300"></td>
{% if forloop.counter|modulo:4 %}
</tr><tr>
{% endif %}
{% endfor %}
profile.html - shows all posts from a user (as in example.com/foobar)
<table>
<tr>
{% for post in object_list %}
<td><img src="{{ post.image.url }}" width="300"></td>
{% if forloop.counter|modulo:4 %}
</tr><tr>
{% endif %}
{% endfor %}
</tr>
</table>
urls.py - I believe this works correctly.
urlpatterns = [
path('admin/', admin.site.urls),
path('', PostList.as_view(), name='list'),
path('<str:username>/', Profile.as_view(), name='user_profile'),
views.py:
from posts.models import Post
class PostList(ListView):
ordering = ['-created']
paginate_by = 12
model = Post
class Profile(ListView):
template_name = 'posts/profile.html'
UserName = self.kwargs.get("username")
queryset = PostList.queryset
.filter(author = UserName)
return queryset
models.py:
class Post(models.Model):
image = models.ImageField()
author = models.ForeignKey(User, on_delete=models.CASCADE)
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
You can override get_queryset():
class ProfileView(ListView):
template_name = 'posts/profile.html'
model = Post
def get_queryset(self, **kwargs):
return super().get_queryset(**kwargs).filter(
author__username=self.kwargs['username']
)
Note: In Django, class-based views (CBV) often have a …View suffix, to avoid a clash with the model names.
Therefore you might consider renaming the view class to ProfileView, instead of Profile.
When I render blogpost.html page I can't see any content in my page.
My urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.index, name='Blog_home'),
path('<slug:slug>', views.blogpost, name='blogpost'),
]
my views.py
When I print blogpost function's query I got null value
from django.shortcuts import render
from django.http import HttpResponse
from blog.models import Post
# Create your views here.
def index(request):
post = Post.objects.all()
context = {'post':post}
return render(request, 'blog/bloghome.html', context)
def blogpost(request, post_id):
post = Post.objects.filter(slug=slug)
print(post)
context = {'post':post}
return render(request, 'blog/blogpost.html', context)
Template Name:- blogpost.html
{% extends 'basic.html' %}
{% block title %}Blog{% endblock title %}
{% block body %}
<div class="contaier">
<div class="row">
<div class="col-md-8 py-4">
<h2 class=" blog-post-title">{{post.title}}</h2>
</div>
</div>
</div>
{% endblock body %}
If I write like this my blogpost.html template it works.
{% extends 'basic.html' %}
{% block title %}Blog{% endblock title %}
{% block body %}
<div class="contaier">
<div class="row">
<div class="col-md-8 py-4">
<h2 class=" blog-post-title">Django</h2>
</div>
</div>
</div>
{% endblock body %}
You're passing a queryset as a context. Your post object contains a queryset of Post objects, so you can't retrieve post.title, you need either to pass only one Post object to your template, or loop through all of your objects and then display post.title for each of them.
You probably need the first option, so you need to change several things.
In your urls.py, you defined your blogpost view by blogpost(request, post_id) whereas in your urls.py you defined your url as
path('<slug:slug>', views.blogpost, name='blogpost')
If you want to get an id from your url, you should define it as
path('<int:post_id>', views.blogpost, name='blogpost')
And in your blogpost view, you do
post = Post.objects.filter(slug=slug)
but your slug isn't defined because your named it post_id.
Once again, if you want to retrieve only a post_id, you should use
post = Post.objects.get(pk=post_id)
The problem is that you are not retrieving a post with this:
post = Post.objects.filter(slug=slug)
It's a queryset, which returns zero, one, or possibly >1 objects (the latter if the slugfield isn't specified unique)
Try:
post = Post.objects.get(slug=slug)
or to better handle failure
post = get_object_or_404( Post, slug=slug)
Django template language fails quietly. If something in {{ }} fails, you get a null string substituted, not a runtime error.
In my 'django' project, I need to retrieve / insert data from multiple tables of my (mysql)database. However because of the code I used, I had to use an extra .html page for each table operation. I want to be able to access multiple tables on a single html page. In order to better explain the situation, I write the relevant codes of the project below.
Project/views.py
def home_view(request, *args, **kwargs):
print(args, kwargs)
print(request.user)
return render(request, "home.html", {})
#login_required()
def admin_view(request, *args, **kwargs):
print(args, kwargs)
print(request.user)
return render(request, "adminPage.html", {})
#login_required()
def doctor_view(request):
return render(request, 'doctorPage.html', {'doctors': doctor_view()})
appointments/views.py
from django.views.generic import DetailView, ListView
class list_of_appointments(ListView):
model = Appointment
template_name = 'appointments/appointment_list.html'
class list_of_patients(ListView):
model = Patient
template_name = 'appointments/patient_list.html'
appointments/urls.py
urlpatterns=[
url(r'^appointment_list/$', list_of_appointments.as_view(), name='list1'),
url(r'^patient_list/$', list_of_patients.as_view(), name='list2')
]
So, in order to access the operations related to the tables, I have to use the following url code.
<a href={% url 'appointments:list2' %}>
Therefore, I can create a second html file and extract the data I want to extract from the database with this method.
{% for appointment in object_list %}
<tr>
<td>{{ appointment.patient.name }}</td>
<td>{{ appointment.doctor.name }}</td>
<td>{{ appointment.Date }}</td>
<td>{{ appointment.time }}</td>
<td>{{ appointment.province }}</td>
<td><a href="#">
<button type="button" class="btn btn-default"><span class="glyphicon glyphicon-pencil"
aria-hidden="true"></span>Edit
</button>
</a></td>
</tr>
{% endfor %}
But I want to do this database interaction on an existing html link (eg adminPage) without going to another link. Nowhere could I find out how to do this, can you help me? Thank you all!
If you want pass more than one model to ListView, you can override get_context_data method of MultipleObjectTemplateResponseMixin. But be carefull, it should be a QuerySet object. The example look like this:
views.py
from django.views.generic.list import ListView
from .models import FirstModel, SecondModel, ThirdModel
class MyListView(ListView):
template_name = 'my_app/what-ever.html'
model = Article
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['my_first_model'] = FirstModel.objects.all()
context['my_second_model'] = SecondModel.objects.all()
context['my_third_model'] = ThirdModel.objects.all()
return context
what-ever.html
{% for object in my_first_model %}
<h1>{{ object.title }}</h1>
<p>{{ object.pk }}</p>
{% endfor %}
You can find more information here.
I have an application which requests data based on certain parameters. I use two functions to handle the requests and then create two objects from the responses. I am able to iterate through each object individually and display the data of a particular object on my webpage, but when I try to use both functions simultaneously, only one function iterates through the object. It is my understanding that this issue has something to do with URL patterns, but I am not as to what the best approach would be. Below you will find my urlpatterns, my functions, and the HTML I use to access the view.
urls.py
urlpatterns = [
path('', views.customer, name='customer'),
path('', views.information, name='information'),
]
views.py
def customer(request):
for i, contact in enumerate(contactObj):
try:
contacts = contactObj
context = {'contacts': contacts}
except KeyError:
print()
return render(request, 'uccx/home.html', context)
def information(request):
for i, ticket in enumerate(ticketObj):
try:
tickets = ticketObj
context = {'tickets': tickets}
except KeyError:
print()
return render(request, 'uccx/home.html', context)
home.html
<tbody>
{% for ticket in tickets %}
<tr class="{% cycle 'row1' 'row2'">
<td> {{ ticket.id }} </td>
<td> {{ ticket.company.name }} </td>
<td> {{ ticket.summary }} </td>
</tr>
{% endfor %}
</tbody>
Your URL patterns should be different for every view. otherwise, it will always call the view which is defined above either you call it by customer or information
So your URL patterns should be
urlpatterns = [
path('customer/', views.customer, name='customer'),
path('information/', views.information, name='information'),
]
UPDATE
You don't have to create separate views for fetching objects from different tables to
show in a webpage
Create a single view and send as many objects in context dictionary.
def table_content(request):
...
# fetch objects here from model
contacts = Contact.objects.all()
tickets = Ticket.objects.all()
# set objects to context dictionary
context = {'contacts': contacts, 'tickets' : tickets}
return render(request, 'uccx/home.html', context)
Now in your template, you can easily loop over tickets and contacts
{% for ticket in tickets %}
<tr>
<td> {{ ticket.id }} </td>
...
</tr>
{% endfor %}
{% for contact in contacts %}
<tr>
<td> {{ contact.id }} </td>
...
</tr>
{% endfor %}
I hope someone can give me a little help on how to do the following with Django (excuse me if I don't explain everything correct, still new to Django and don't know about a lot of things) :
I have a table of Movies, those Movies have a "Description" Datafield, where when they click on it a form opens up with the current description of the movie. If they double click on this description they are allowed to change it and then save the value. I've made a small gif to visualize the idea:
At least thats the basic Idea behind this, so far I've managed to make most of the things run, but sadly not the Django part where the "new" data from the user is send to the Databank and replaces the old data of the Description.
So could someone explain to me how I can make that work? I know that I'd probably have to write a function to my views.py and then create a new url pattern, but I just can't figure out how exactly. So any help is welcome! Below is my code (I hope I've included every file you guys need):
views.py
from django.shortcuts import get_object_or_404, render
from django.http import HttpResponseRedirect
from django.urls import reverse
from django.views import generic
from django.views.generic.list import ListView
from .models import *
class AllMovies(generic.ListView):
model = Movie
template_name = "consilium/index.html"
context_object_name = "latest_movie_list"
class MovieDetails(generic.DetailView):
model = Movie
template_name = "consilium/detail.html"
urls.py
from django.conf.urls import url
from . import views
from .models import *
from django.views.generic.list import ListView
app_name = "consilium"
urlpatterns = [
url(r'^$', views.AllMovies.as_view(), name="index"),
url(r'^(?P<slug>[\w_0-9]+)/$', views.MovieDetails.as_view(), name='detail'),
]
models.py
from django.db import models
from decimal import Decimal
from django import forms
from django.contrib import admin
class Movie(models.Model):
// removed the other models for better overview
description = models.TextField('Movie Description')
def __str__(self):
return self.title
index.html
{% extends "consilium/base.html" %}
{% block body %}
<table class="table">
<thead>
<tr>
<th></th>
<th colspan="2">My Movielist</th>
<th>
</tr>
<tr>
<th></th>
<th>TITLE</th>
<th>GENRE</th>
<th>RELEASE DATE</th>
<th>DIRECTOR</th>
<th>DESCRIPTION</th>
<th>RUNTIME</th>
<th>STATUS</th>
<th>IMDB</th>
</tr>
</thead>
<tbody>
{% if latest_movie_list %}
{% for movie in latest_movie_list %}
<tr>
<td></td>
<td>
<a href="{% url 'consilium:detail' movie.slug %}" data-toggle="popover" data-placement="left" data-content='<img class="title-image" src="{{movie.image.url}}"/>'>{{ movie.title }}</a>
</td>
<td>{{ movie.get_genre_display}}</td>
<td>{{ movie.date}}</td>
<td>{{ movie.director}}</td>
<td id="icn-change" data-toggle="collapse" data-target=".demo{{ forloop.counter }}">
Description <i class="fa fa-caret-right"></i>
</td>
<td>{{ movie.runtime}} min</td>
<td>{{ movie.get_status_display}}</td>
<td>{{ movie.imdb}}</td>
</tr>
<tr>
<td></td>
<td class="hiddenRow" colspan="8">
<div class="container collapse demo{{ forloop.counter }}">
<div class="row justify-content-center">
<div class="col">
<form method="post" id="usrform">{% csrf_token %}
<textarea id="text" class ="form-control" readonly="true" onkeydown="expandtext(this)" ondblclick="this.readOnly='';">{{movie.description}}</textarea>
</form>
</div>
</div>
<div class="row justify-content-center">
<div class="col align-self-start">Double Click to Edit</div>
<div class="col align-self-end">
<input type="submit" id="set" class="pull-right"/>
</div>
</div>
</div>
</td>
</tr>
{% endfor %}
{% else %}
<tr>
<td>No Movies are available.</td>
</tr>
{% endif %}
</tbody>
</table>
{% endblock %}
script.js
// removed all other code for overview
// replace description text with user input
$('#set').click(function() {
var test = $('#text').val();
localStorage.setItem("test", test);
});
$('#text').text(localStorage.getItem("test"));
I hope I didn't miss anything, thanks for everyone who can help me!
I worked on a similar project, and here is what I did.
from django.forms.models import model_to_dict
#login_required
def edit_profile(request):
profile, created = ClientProfile.objects.get_or_create(user_id=request.user.id)
if request.method == 'POST':
form = ProfileSubmissionForm(request.POST, instance=profile)
if form.is_valid():
form.save()
return HttpResponseRedirect(reverse('jobs:list'))
else:
profile_dict = model_to_dict(profile)
form = ProfileSubmissionForm(profile_dict)
return render(request, 'jobs/profile.html', {'form': form})
Essentially, the model_to_dict renders the values stored in the database in the form. The instance=profile makes sure I'm updating the form and not creating a new object.
Figured it out thanks to the great help of the pythondev slack community!
views.py: getting the description field of my Movie Model
class MovieUpdateForm(forms.ModelForm):
class Meta:
model = Movie
fields = ['description']
reverse_lazy is important, so that when I click on my button it won't redirect me to consilium(my appname)/2/update and stays on the index site where I have my table
class MovieUpdateView(UpdateView):
model = Movie
form_class = MovieUpdateForm
success_url = reverse_lazy('consilium:index')
urls.py:
url(r'^(?P<pk>[0-9]+)/update/$', views.MovieUpdateView.as_view(), name='movie_update'),
here it was important to put this before my slug url pattern I had in my urls.py, otherwise it didn't work:
url(r'^(?P<slug>[\w_0-9]+)/$', views.MovieDetails.as_view(), name='detail'),
My form in my html: using pk=movie.pk so it will grab the correct movie and giving my textarea the name of "description" so my method knows where the data is coming from
<form action="{% url 'consilium:movie_update' pk=movie.pk %}" method="post" id="usrform">{% csrf_token %}
<textarea id="text" class ="form-control" name="description" readonly="true" onkeydown="expandtext(this)" ondblclick="this.readOnly='';">{{movie.description}}</textarea>
<input type="submit" id="set" class="pull-right"/>
</form>