For whatever reason when I give a name="..." - argument to a URL pattern and I want to refer to it by using the name it does not seem to work.
That's my 'webapp/urls.py' file:
from django.urls import path
from .views import PostListView, PostDetailView, PostCreateView
from .import views
app_name = 'webapp'
urlpatterns = [
path("", PostListView.as_view(), name="webapphome"),
path("post/<int:pk>/", PostDetailView.as_view(), name="postdetail"),
path('post/new/', PostCreateView.as_view(), name="postcreate"),
path("about/", views.About, name="webappabout"),
]
And that's my 'webapp/views.py' file:
from django.shortcuts import render
from django.views import generic
from django.views.generic import ListView, DetailView, CreateView
from .models import Post
def Home(request):
context = {
'posts': Post.objects.all() }
return render(request, "webapp/home.html", context)
class PostListView(ListView):
model = Post
template_name = 'webapp/home.html'
context_object_name = 'posts'
ordering = ['-date']
class PostDetailView(DetailView):
model = Post
template_name = 'webapp/detail.html'
class PostCreateView(CreateView):
model = Post
fields = ['title', 'content']
template_name = 'webapp/postform.html'
def form_valid(self, form):
form.instance.author = self.request.user
return super().form_valid(form)
def About(request):
return render(request, "webapp/about.html", {'title': 'About'})
And that's my 'webapp/models.py' file:
from django.db import models
from django.utils import timezone
from django.contrib.auth.models import User
from django.urls import reverse
class Post(models.Model):
title = models.CharField(max_length=50)
content = models.TextField(max_length=300)
date = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse("postdetail", kwargs={'pk': self.pk})
As you can see, I'm using the name 'postdetail' I've given to the URL path from PostDetailView but however I receive an Error like this when I create a new Post:
NoReverseMatch at /post/new/
Reverse for 'postdetail' not found. 'postdetail' is not a valid view function or pattern name.
Request Method: POST
Exception Type: NoReverseMatch
I'd suggest you read the Namespace section in Django Documentation, here
The issue is due to you having an app_name = 'webapp' but not using it with postdetail
The objective of app_name is to ensure you know where to redirect if you have two url in different apps with same names.
change
return reverse("postdetail", kwargs={'pk': self.pk})
to
return reverse("webapp:postdetail", kwargs={'pk': self.pk})
Related
I am the newbie of writing programming, now I am learning django.
I have a problem for URL redirection. I create the model and it does work at admin site.
Also I set the PK for each article, that successfully generate the URL by PK.
However when I post the message form the front-end, after posting it appear the error message suppose it should be redirect to the page of DetailViewand
I have imported the reverse function in my model, but it seem not working.
My python version : 3.7.6 and django version : 3.0.0
ImproperlyConfigured at /add/
No URL to redirect to. Either provide a url or define a get_absolute_url method on the Model.
My View
from django.shortcuts import render
from django.views.generic import ListView, DetailView
from django.views.generic.edit import CreateView
from .models import Page
class PageListView(ListView):
model = Page
template_name='home.html'
context_object_name = 'all_post_list'
class PageDetailView(DetailView):
model = Page
template_name='post.html'
class PageCreateView(CreateView):
model = Page
template_name='post_new.html'
fields = ['title', 'author', 'body', 'body2']
Model
from django.urls import reverse
from django.db import models
from ckeditor.fields import RichTextField
class Page(models.Model):
title = models.CharField(max_length=50)
author = models.ForeignKey(
'auth.User',
on_delete=models.CASCADE,
)
body = RichTextField()
body2 = models.TextField()
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('post', args=[str(self.id)])
URL
from django.urls import path
from .views import PageListView, PageDetailView, PageCreateView
urlpatterns = [
path('add/', PageCreateView.as_view(), name='post_new'),
path('', PageListView.as_view(), name='home'),
path('blog/<int:pk>/', PageDetailView.as_view(), name='post'),
]
Thanks for helping. :)
I think your indentation is the problem here. Fix it by:
class Page(models.Model):
title = models.CharField(max_length=50)
author = models.ForeignKey(
'auth.User',
on_delete=models.CASCADE,
)
body = RichTextField()
body2 = models.TextField()
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('post', args=[self.id])
Why am I getting an error when trying to run my server to access the database to see if my code works? While in my projects folder in Terminal, I ran sudo python manage.py runserver to try to run the server but it doesn't work because of the aforementioned error. I've looked around SO but can't find one directly related to my problem.
I'm getting my if() statement is the problem.
The error I'm getting says:
RuntimeError: maximum recursion depth exceeded while calling a Python object
Here's my views.py file:
from .models import Album
from django.shortcuts import render, redirect
from django.contrib.auth import authenticate, login
from django.core.urlresolvers import reverse_lazy
from django.views import generic
from django.views.generic import View
from django.views.generic.edit import CreateView, UpdateView, DeleteView
from .forms import UserForm
class IndexView(generic.ListView):
template_name = 'music/index.html'
context_object_name = 'all_albums'
def get_queryset(self):
return Album.objects.all()
class DetailView(generic.DeleteView):
model = Album
template_name = 'music/detail.html'
class AlbumCreate(CreateView):
model = Album
fields = ['artist', 'album_title', 'genre', 'album_logo']
class AlbumUpdate(UpdateView):
model = Album
fields = ['artist', 'album_title', 'genre', 'album_logo']
class AlbumDelete(DeleteView):
model = Album
success_url = reverse_lazy('music:index')
class UserFormView(View):
form_class = UserForm
template_name = 'music/registration_form'
# display blank form
def get(self, request):
form = self.form_class(None)
return render(request, self.template_name, {'form': form})
def post(self):
form = self.form_class(request.POST)
if form.is_valid():
user = form.save(commit=False)
#cleaned normalized data
username = form.cleaned_data['username']
password = form.cleaned_data['password']
user.set_password(password)
user.save()
Tail of error:
File "/Library/Python/2.7/site-packages/Django-1.11.2-py2.7.egg/django/urls/resolvers.py", line 255, in check
warnings.extend(check_resolver(pattern))
File "/Library/Python/2.7/site-packages/Django-1.11.2-py2.7.egg/django/core/checks/urls.py", line 26, in check_resolver
return check_method()
File "/Library/Python/2.7/site-packages/Django-1.11.2-py2.7.egg/django/urls/resolvers.py", line 172, in check
warnings = self._check_pattern_startswith_slash()
File "/Library/Python/2.7/site-packages/Django-1.11.2-py2.7.egg/django/urls/resolvers.py", line 140, in _check_pattern_startswith_slash
regex_pattern = self.regex.pattern
Here's my forms.py file:
from django.contrib.auth.models import User
from django import forms
class UserForm(forms.ModelForm): # UserForm inherits from forms.
passwords = forms.CharField(widget=forms.PasswordInput)
class Meta: # Information about your class.
model = User # whenevr a creates sign up to your site it's gonna go in same table
fields = ['username', 'email', 'password']
Here's my urls.py file:
from django.conf.urls import include, url
from django.contrib import admin
from django.conf import settings
from django.conf.urls.static import static
app_name = 'music'
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^music/', include('music.urls'))
]
if settings.DEBUG:
urlpatterns += static(settings.STATIC_URL, document_root = settings.STATIC_ROOT)
urlpatterns += static(settings.STATIC_URL, document_root=settings.MEDIA_ROOT)
You didn't pass request into your post method, It should be,
class UserFormView(View):
form_class = UserForm
template_name = 'music/registration_form.html'
def post(self, request, *args, **kwargs):
# blaah
Also, missed the extension of your template.
I think you should use FormView for this and don't need to override post or get method in your View, Because you will get form object in template if user assign form_class in View.You have to override form_valid() method for your custom operations
class UserFormView(FormView):
form_class = UserForm
template_name = 'music/registration_form'
def form_valid(self, form)
user = form.save(commit=False)
username = form.cleaned_data['username']
password = form.cleaned_data['password']
user.set_password(password)
user.save()
I am trying to view a user profile for my website with the Detail CBV. Below is the code for views.py, urls.py, models.py and profile.html.
A user exists with the username "brian_weber", but for some reason when I navigate to this link: http://0.0.0.0:8000/accounts/profile/brian_weber the page is not found. My app is called "accounts".
If someone could point me in the right direction to get the view to show up with the url, that would be greatly appreciated! I have searched around Stack Overflow, but nothing has worked that I tried.
Thanks in advance,
Brian
views.py
from django.shortcuts import render
from django.shortcuts import get_object_or_404
from django.contrib.auth import login, logout, authenticate
from django.http import HttpResponseRedirect
from django.contrib.auth.forms import AuthenticationForm
from django.core.urlresolvers import reverse, reverse_lazy
from django.views import generic
from braces.views import LoginRequiredMixin
from django.contrib.messages.views import SuccessMessageMixin
from . import forms
from . import models
class LoginView(generic.FormView):
form_class = AuthenticationForm
success_url = reverse_lazy('home')
template_name = "accounts/login.html"
def get_form(self, form_class=None):
if form_class is None:
form_class = self.get_form_class()
return form_class(self.request, **self.get_form_kwargs())
def form_valid(self, form):
login(self.request, form.get_user())
return super().form_valid(form)
def logout_view(request):
logout(request)
return HttpResponseRedirect(reverse('home'))
class SignUp(SuccessMessageMixin, generic.CreateView):
form_class = forms.UserCreateForm
success_url = reverse_lazy("login")
template_name = "accounts/signup.html"
success_message = "Your profile has been successfully created. Please log into your account."
class UserProfile(LoginRequiredMixin, generic.DetailView):
model = models.UserProfile
template_name = "profile.html"
class UserProfileUpdate(LoginRequiredMixin, generic.UpdateView):
model = models.UserProfile
urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^logout/$', views.logout_view, name="logout"),
url(r'^signup/$', views.SignUp.as_view(), name="signup"),
url(r'^profile/(?P<username>[a-zA-Z0-9]+)$',
views.UserProfile.as_view(),
name="profile"),
url(r'^profile/update/(?P<username>[a-zA-Z0-9]+)$',
views.UserProfileUpdate.as_view(),
name="update_profile"),
]
models.py
class UserProfile(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL)
company = models.CharField(max_length=40, null=True)
position = models.CharField(max_length=40, null=True)
bio = models.CharField(max_length=140, blank=True, default="")
avatar = models.ImageField(blank=True, null=True, upload_to="avatars",
height_field=None, width_field=None)
def create_user_profile(sender, instance, created, **kwargs):
if created:
UserProfile.objects.create(user=instance)
post_save.connect(create_user_profile, sender=User)
Your mistake is very small, the regular expression provided in url for profile, (?P<username>[a-zA-Z0-9]+) does not match brian_weber because of the _.
You can simply update the regex to match _ too.
username_regex = r'[a-zA-Z0-9_]+'
urlpatterns = [
url(r'^logout/$', views.logout_view, name="logout"),
url(r'^signup/$', views.SignUp.as_view(), name="signup"),
url(r'^profile/(?P<username>{username})$'.format(username=username_regex),
views.UserProfile.as_view(),
name="profile"),
url(r'^profile/update/(?P<username>{username})$'.format(username=username_regex),
views.UserProfileUpdate.as_view(),
name="update_profile"),
]
my models.py file looks like this
from django.db import models
from django.template.defaultfilters import slugify
class Entertainmentblog(models.Model):
slug = models.SlugField(max_length=100)
body = models.TextField()
posted = models.DateTimeField('date published')
img_url0 = models.CharField(max_length=100)
img_alt0 = models.CharField(max_length=100)
title1 = models.CharField(max_length=100)
title2 = models.CharField(max_length=100)
def save(self):
super(Entertainmentblog, self).save()
self.slug = '%i-%s' % ( self.id, slugify(self.slug) )
super(Entertainmentblog, self).save()
And my app urls.py file looks like this
from django.conf.urls import patterns, url
from entertainment import views
urlpatterns = patterns('',
url(r'^$', views.ListView.as_view(), name='index'),
url(r'^(?P<slug>[^\.]+),(?P<id>\d+)/$', views.DetailView.as_view(), name='article'),
)
But this gives an error.
Exception Value: Reverse for 'article' with arguments '(u'what-is-happening',)' and keyword arguments '{}' not found. 1 pattern(s) tried: [u'entertainment/(?P[^\.]+),(?P\d+)/$']
My view.py file
from django.shortcuts import get_object_or_404, render
from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse
from django.views import generic
from entertainment.models import Entertainmentblog
class ListView(generic.ListView, slug, id):
template_name = 'entertainment/index.html'
context_object_name = 'latest_article_list'
def get_queryset(self):
return Entertainmentblog.objects.order_by('-posted')[:25]
class DetailView(generic.DetailView):
model = Entertainmentblog
template_name = 'entertainment/article.html'
How do I correct this?
Oh, there is serious problems with your views:
First:
class ListView(generic.ListView, slug, id)
should be
class ListView(generic.ListView)
see python inheritance.
Second:
slug and id must be class members of your view so you can redefine you view like this:
class ListView(generic.ListView):
template_name = 'entertainment/index.html'
context_object_name = 'latest_article_list'
slug = None
id = None
def get_queryset(self):
return Entertainmentblog.objects.order_by('-posted')[:25]
Third:
Youre naming a derivate class as its parent. I don't know the implications of doing this, but surely, isn't a good practice.
Finally:
The error you're getting is becouse the view returned by views.DetailView.as_view() (remember DetailView is your derived class) don't receives the arguments you are passing through url. Check your url, I can see in the error that is complaining about and argument (u'what-is-happening',) but there is no id. It should be something like, for example, (u'what-is-happening', '4')
I have a problam in Django. I'm a amature Django developer. I can't show my "Category" data in Template. here is my code :
models.py
from django.db import models
from taggit.managers import TaggableManager
class Category(models.Model):
title = models.CharField(max_length=40)
def __unicode__(self):
return self.title
class Post (models.Model):
title = models.CharField(max_length=150)
body = models.TextField()
date = models.DateTimeField()
tags = TaggableManager ()
cats = models.ManyToManyField(Category)
def __unicode__ (self):
return self.title
views.py
from django.shortcuts import render
from django.template.loader import get_template
from django.template import Context
from django.http import HttpResponse
from blog.models import Category
render(request, 'index.html', args)
def cats(request):
t = get_template('category.html')
for i in Category.object.get :
html = t.render(Context({'cat': i}))
return HttpResponse(html)
urls.py
from django.conf.urls import include, url, patterns
from django.views.generic import ListView, DetailView
from blog.models import Post, Category
urlpatterns = patterns('blog.views',
url(r'^$',ListView.as_view(
queryset = Post.objects.all().order_by("-date")[:2],
template_name="index.html")),
url(r'^(?P<pk>\d+)$',DetailView.as_view(
model = Post,
template_name="post.html")),
url(r'^(?P<pk>\d+)$','cats'),
)
A part of template "post.html"
#some html code here
{% include "category.html" %}
#another some html code here
This is my category.html
<li>{{cat}}</li>
Thank you.
Your way of writing code is not quite correct. Views are meant for backend codes, urls.py is meant only for url specifications not for writing queries.
views.py
from blog.models import Category
from blog.models import Post
def cats(request):
queryset = Post.objects.all().order_by("-date")[:2]
return render_to_response('category.html',{'queryset': queryset},
context_instance=RequestContext(request))
add this in urls.py
url(r'^cats', 'blog.views.cats', name='cats')
In category.html you can access any field of the object that is passed from views.py (here queryset )
<li>{{querset.title}}</li>