Django UpdateView not working - python

I am trying to use the UpdateView of django but for some reason it does not work.
(URL.py)
from django.conf.urls import url
from . import views
app_name='profiles'
urlpatterns = [
url(r'^$', views.IndexView.as_view(),name='index'),
url(r'^(?P<pk>[0-9]+)$',views.DetailView.as_view(),name='detail'),
url(r'^task/add/$',views.TaskCreate.as_view(),name='task-add'),
url(r'^task/(?P<pk>[0-9]+)$',views.TaskUpdate.as_view(), name='task-update'),
url(r'^task/(?P<pk>[0-9]+)/delete/$',views.TaskDelete.as_view(), name='task-delete'),]
Below is my Html file in which I am trying to add a "Edit" link which will redirect to the UpdateView.
(Details.PY this already has the second url mapped)
{% extends 'profiles/base.html' %}
{% block body %}
<H3>The total efforts are {{datamain.efforts}} {{datamain.status}} hours.</H3>
Edit
{% endblock %}
Below is the Views.py
class IndexView(generic.ListView):
template_name = 'profiles/index.html'
def get_queryset(self):
return Datamain.objects.all()
class DetailView(generic.DetailView):
model = Datamain
template_name = 'profiles/details.html'
class TaskCreate(CreateView):
model=Datamain
fields=['main_task','date_time','efforts','status']
class TaskUpdate(UpdateView):
model=Datamain
fields=['main_task','date_time','efforts','status']
class TaskDelete(DeleteView):
model=Datamain
success_url = reverse_lazy('profiles:index')
fields=['main_task','date_time','efforts','status']
When I run it and go to the page , it shows error "no reverse match"

You forget to pass url argument pk try this:
Edit

Related

Django UpdateView generating 'GET' request instead of 'POST'

I'm following along a book called Django for Beginners and creating a project which displays newspaper articles. Part of the functionality is being able to edit those articles. I've followed along as closely as I could but I'm still getting an error when hitting the 'Update' button:
My urls.py
from django.urls import path
from .views import (ArticleListView,
ArticleUpdateView,
ArticleDetailView,
ArticleDeleteView)
urlpatterns = [
path('<int:pk>/edit/', ArticleUpdateView.as_view(), name = 'article_edit'),
path('<int:pk>/', ArticleDetailView.as_view(), name = 'article_detail'),
path('<int:pk>/delete/', ArticleDeleteView.as_view(), name = 'article_delete'),
path('', ArticleListView.as_view(), name = 'article_list'),
]
my views.py
from django.shortcuts import render
from django.views.generic import ListView, DetailView
from django.views.generic.edit import UpdateView, DeleteView
from django.urls import reverse_lazy
from .models import Article
# Create your views here.
class ArticleListView(ListView):
model = Article
template_name = 'article_list.html'
class ArticleDetailView(DetailView):
model = Article
template_name = 'article_detail.html'
class ArticleUpdateView(UpdateView):
model = Article
fields = ('title', 'body')
template_name = 'article_edit.html'
class ArticleDeleteView(DeleteView):
model = Article
template_name = 'article_delete.html'
success_url = reverse_lazy('article_list')
My models.py:
from django.db import models
from django.conf import settings
from django.contrib.auth import get_user_model
from django.urls import reverse
# Create your models here.
class Article(models.Model):
title = models.CharField(max_length=225)
body = models.TextField()
date = models.DateTimeField(auto_now_add=True)
author = models.ForeignKey(
get_user_model(),
on_delete=models.CASCADE,
)
def __str__(self):
return self.title
def get_absolute_url(self):
reverse('article_detail', args=[str(self.id)])
My HTML:
<!-- templates/article_edit.html -->
{% extends 'base.html' %}
{% block content %}
<h1>Edit</h1>
<form action="" method="post">{% csrf_token %}
{{ form.as_p }}\
<button class="btn btn-info ml-2" type="submit">Update Article {{article.pk}}</button>
</form>
{% endblock content %}
After hitting the edit button, according to the book the app is supposed to forward me to the 'article_detail' page however that is not happening.
Any assistance would be gratefully received.
Thanks
Andy
In the end it was a simple omission of a return statement in the get_absolute_url function within models.py.

I'm getting 'AttributeError' whenever I try to edit any entry through forms in Django

Every time I try to edit any entry through a form, it gives Attribute Error.
I have only one model that is BlogPost
models.py
from django.db import models
# Create your models here.
class BlogPost(models.Model):
""" A title and text for a blog entry"""
title = models.CharField(max_length=200)
text = models.TextField()
date_added = models.DateTimeField(auto_now_add=True)
def __str__(self):
""" return a string representation of the model."""
return self.title
This is views file
views.py
from django.shortcuts import render, redirect
from .models import BlogPost
from .forms import BlogPostForm
def edit_post(request, post_id):
""" edit an entry"""
title = BlogPost.objects.get(id=post_id)
post = title.text
if request.method != 'POST':
form = BlogPostForm(instance=post)
else:
form = BlogPostForm(instance=post, data=request.POST)
if form.is_valid():
form.save()
return redirect('blogs:index', post_id=title.id)
context = {'title': title, 'post': post, 'form': form}
return render(request, 'blogs/edit_post.html', context)
This is edit post file
edit_post.html
{extends 'blogs/base.html'}
{% block content %}
<p>Edit Form:</p>
<p>{{ title }}:</p>
<form action="{% url 'blogs:edit_post' title.id %}" method="POST">
{% csrf_token %}
{{ form.as_p }}
<button name="submit">Save changes</button>
</form>
{% endblock content %}
forms.py
from django import forms
from .models import BlogPost
class BlogPostForm(forms.ModelForm):
class Meta:
model = BlogPost
fields = ['title', 'text']
labels = {'title':'Title', 'text': 'Post'}
widgets = {'text': forms.Textarea(attrs={'cols': 80})}
urls.py
# defines urls patterns for the blogs app
from django.urls import path
from . import views
app_name = 'blogs'
urlpatterns = [
# Home page
path('', views.index, name='index'),
# To add new post
path('new_post/', views.new_post, name='new_post'),
# To edit post
path('edit_post/<int:post_id>/', views.edit_post, name='edit_post'),
]
I'm using Django 2.2.6 and python 3.7.4.
I guess there is a problem with my URL patterns or with the paths of the request.
This is the error it generates
TypeError at /edit_post/1/
edit_post() got an unexpected keyword argument 'post_id'
Request Method: GET Request URL: http://localhost:8000/edit_post/1/
Django Version: 2.2.6 Exception Type: TypeError Exception Value:
edit_post() got an unexpected keyword argument 'post_id'
Exception Location:
C:\Users\nouma\Desktop\blog_folder\ll_env\lib\site-packages\django\core\handlers\base.py
in _get_response, line 113 Python Executable:
C:\Users\nouma\Desktop\blog_folder\ll_env\Scripts\python.exe Python
Version: 3.7.4
**
I've got my answer. The problem was that in views file I was giving unnecessary argument.
i-e
return redirect('blogs:index', post_id=title.id)
this second argument was not needed

Django: List and Display Data from DB

I found a code that the urls in django can contain a model, so it can display a db values directly to html, but when i tried it, i got some error in the urls because this code still using patterns, is it possible doing this thing in a newer django?
The Url
from django.views.generic import ListView
from django.conf.urls import patterns, url
urlpatterns = patterns("myapp.views",
url(r'^dreamreals/', ListView.as_view(
template_name = "dreamreal_list.html")),
model = Dreamreal, context_object_name = ”dreamreals_objects” ,)
The HTML
{% extends "main_template.html" %}
{% block content %}
Dreamreals:<p>
{% for dr in object_list %}
{{dr.name}}</p>
{% endfor %}
{% endblock %}
I'm pretty sure all you've entered are kwargs of ListView.as_view() method.
So instead of doing
ListView.as_view(
template_name = "dreamreal_list.html")),
model = Dreamreal, context_object_name = ”dreamreals_objects” ,)
Which is actually syntaxly incorrect, do :
ListView.as_view(
template_name = "dreamreal_list.html",
model = Dreamreal,
context_object_name = ”dreamreals_objects”
)
Second error, you're setting the context_object_name to dreamreals_objects, but in your template you're iterating over object_list.
But this method is not really "pretty" and you should really make a views.py with your views and then the urls.py should only care about making a route.
As pointed in comments, django 2.1+ no longer use urlpatterns but path : https://docs.djangoproject.com/en/2.1/topics/http/urls/#example

How does one pass arguments from the URL to a view before rendering a new page?

I am creating a stock portfolio app. The user has a list of stocks each of which has a link which looks something like 'http://127.0.0.1:8000/search/symbol=TSLA'. What I want to do is pass the stock symbol 'TSLA' to one of my views and simply print that string on the next page (for now).
What I have done so far (did not include it in the code below) is to simply have some method in my SearchPageView called get_symbol and I tried to get the url from there and in my search.html template, I tried accessing that via {{ view.get_symbol }}. But this displays nothing.
My set-up:
views.py:
class SearchPageView(TemplateView):
template_name = 'search.html'
urls.py:
from django.urls import path, re_path
from .views import SearchPageView
urlpatterns = [
path('search/<string>', SearchPageView.as_view(), name='search_stock'),
]
search.html:
{% extends 'base.html' %}
{% block content %}
{% endblock content %}
I know there's nothing above, all i'm asking for is how to pass the string 'TSLA' to my view then to 'search.html' then I can do what I need to do with it. I appreciate any help.
Change your urls.py by this
path('search/<symbol>', SearchPageView.as_view(), name='search_stock'),
In views.py
from django.shortcuts import get_object_or_404
from django.views.generic import ListView
class SearchPageView(ListView):
template_name = 'your_template.html'
def get_queryset(self):
self.publisher = get_object_or_404(YOUR_MODEL_NAME, name=self.kwargs['symbol'])
return YOUR_MODEL_NAME.objects.filter(symbol=self.symbol)
I consider your model field name is symbol.
You can try like this:
from django.shortcuts import render
def page_view(request):
# recheck how to get data you want pass in html from this view
return render(request, 'search.html', {
'symbol': request.DATA.get('symbol'),
})
and in url change to this:
urlpatterns = [
path('search/<string>', page_view, name='search_stock'),
]
and in search.html you will have {{ symbol }} variable from def page_view

Django, Can't get delete button to work

I have a section of my site where an admin can add a widget. However the delete button to delete any current widgets is not working. I have this code implemented else where on my site and it is working.
I copied the same code from the other section of my site where this is being used. The other section of my site which uses this code is a little different in that a post can only be deleted be the user who created it, and the widgets can be delete by any user with the "access_level" field is equal to "admin". However, I am the only admin so it should still work. The page that the widget stuff is displayed on is only accessible if your "access_level" is equal to admin so I don't need to validate whether or not they have the permission before deleting. Please help.
widget_list.html:
{% extends "base.html" %}
{% block content %}
<div class="container">
<div class="content">
<div class="widgets-list">
{% for widget in widget_list %}
<h3>{{ widget.name }}</h3>
<h3>{{ widget.widget_order }}</h3>
<div>
<p>{{ widget.body }}</p>
</div>
{% if user.is_authenticated %}
<a class="auth-user-options" href="{% url 'adminpanel:delete-widget' pk=widget.pk %}">Delete</a>
{% endif %}
{% endfor %}
</div>
</div>
</div>
{% endblock %}
Adminpanel app views.py:
from django.shortcuts import render
from adminpanel.forms import WidgetForm
from adminpanel.models import Widget
from django.utils import timezone
from django.contrib.auth import authenticate,login,logout
from django.http import HttpResponseRedirect, HttpResponse
from django.core.urlresolvers import reverse,reverse_lazy
from django.contrib.auth.decorators import login_required
from django.contrib.auth.mixins import LoginRequiredMixin
from braces.views import SelectRelatedMixin
from django.views.generic import (TemplateView,ListView,
DetailView,CreateView,
UpdateView,DeleteView)
# Create your views here.
class CreateWidgetView(LoginRequiredMixin,CreateView):
login_url = '/login/'
redirect_field_name = 'index.html'
form_class = WidgetForm
model = Widget
def form_valid(self,form):
self.object = form.save(commit=False)
self.object.save()
return super().form_valid(form)
def get_success_url(self):
return reverse('adminpanel:widgets')
class SettingsListView(ListView):
model = Widget
ordering = ['widget_order']
class DeleteWidget(LoginRequiredMixin,SelectRelatedMixin,DeleteView):
model = Widget
select_related = ('Widget',)
success_url = reverse_lazy('adminpanel:widget')
def get_queryset(self):
queryset = super().get_queryset()
return queryset.filter(user_id=self.request.user.id)
def delete(self,*args,**kwargs):
return super().delete(*args,**kwargs)
Project url spy:
from django.conf.urls import url
from django.contrib import admin
from django.conf.urls import include
from accounts import views
from colorsets import views
from colors import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^$',views.home,name='index'),
url(r'^accounts/',include('accounts.urls',namespace='accounts')),
url(r'^colorsets/',include('colorsets.urls',namespace='colorsets')),
url(r'^adminpanel/',include('adminpanel.urls',namespace='adminpanel')),
]
Adminpanel app urls.py:
from django.conf.urls import url
from adminpanel import views
app_name = 'adminpanel'
urlpatterns = [
url(r'^widgets/',views.SettingsListView.as_view(),name='widgets'),
url(r'^new/$',views.CreateWidgetView.as_view(),name='create-widget'),
url(r'^delete/(?P<pk>\d+)/$',views.DeleteWidget.as_view(),name='delete-widget'),
]
EDIT: Here is the error I'm getting I forgot to add it.
FieldError at /adminpanel/delete/10/
Cannot resolve keyword 'user_id' into field. Choices are: body, id, name, widget_order
and the traceback points to this:
/Users/garrettlove/Desktop/colors/adminpanel/views.py in get_queryset
return queryset.filter(user_id=self.request.user.id) ...
▶ Local vars
Adminpanel app models.py (widget model):
from django.db import models
from adminpanel.choices import *
# Create your models here.
class Widget(models.Model):
name = models.CharField(max_length=50)
widget_order = models.IntegerField(blank=False,unique=True)
display_name = models.IntegerField(choices=WIDGET_NAME_CHOICES,default=1)
body = models.TextField(max_length=500)
def __str__(self):
return self.name
As your error is saying:
Cannot resolve keyword 'user_id' into field.
And it points to this line:
return queryset.filter(user_id=self.request.user.id)
It's that your queryset model does not have a user_id field. In your DeleteWidget view you have specified model = Widget
and as you see in your Widget model, you have the following fields: body, id, name, widget_order. There is no user_id field.
You need to change your filtering logic. If you want to have a related User model, you should use ForeignKey relation and then you can filter by the User's id.
In your models.py:
from django.contrib.auth.models import User
class Widget(models.Model):
# ...
user = models.ForeignKey(User, on_delete=models.CASCADE)
And then in your DeleteWidget's get_queryset, you can do the following:
return queryset.filter(user__id=self.request.user.id)
# __________________________^
# Note that there is a double underscore here!
# This is because Django uses double underscore for accessing related models in queries.

Categories

Resources