views.py
class CommentCreatView(LoginRequiredMixin, CreateView):
model = Comment
fields = ['text']
template_name = 'home/add-comment.html'
success_url = 'homepage'
def form_valid(self,form):
form.instance.user = self.request.user
post = self.get_object()
form.instance.post = post
return super().form_valid(form)
urls.py
from django.urls import path
from . import views
from django.conf import settings
from django.conf.urls.static import static
from .views import PostCreateView, PostsListView, PostDetailView, CommentCreatView
urlpatterns = [
path('', PostsListView.as_view(), name='homepage'),
path('post/<int:pk>/', PostDetailView.as_view(), name='post-and-comments'),
path('post/<int:pk>/comment', CommentCreatView.as_view(), name='add-comment'),
path('creat', PostCreateView.as_view(), name='creat-post')
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
add-comment.html
{% extends "home/base.html" %}
{% load crispy_forms_tags %}
<!-- allow us to use crispy filter on any of our forms -->
{% block content %}
<div class="content-section">
<form method="POST">
<!--this method post is to protect our form fromcertain attacks -->
{% csrf_token %}
{{form|crispy}}
<button class="btn btn-outline-danger mt-1 mb-1 mr-1 ml-1" type="submit">Add Comment</button>
</div>
</form>
</div>
{% endblock content %}
So I opens it home/post/6/comment , I see the form and when I submit it. I get this error and the comment isnt saved error screenshot
The .get_object(…) [Django-doc] method will try to find a Comment with as primary key the one you specified in the path (here 6). You do not want to find a comment but the Post with that primary key. You thus should rewrite this to:
class CommentCreatView(LoginRequiredMixin, CreateView):
model = Comment
fields = ['text']
template_name = 'home/add-comment.html'
success_url = 'homepage'
def form_valid(self,form):
form.instance.user = self.request.user
form.instance.post_id = self.kwargs['pk']
return super().form_valid(form)
Related
I am having trouble working with models and forms in Django. A little clarification and help will be highly appreciated!
I am really confused because I do not see the form in my html url page. I see everything else but not the form. I assume, I'm missing something.
This is my forms.py
from django import forms
from .models import TwitterContainer
class TwitterUpdateForm(forms.ModelForm):
class Meta:
model = TwitterContainer
fields = ["Twitter_API_key", "Twitter_API_key_secret", "Twitter_API_token", "Twitter_API_token_secret"]
This is my models.py
from django.db import models
from django.contrib.auth.models import User
class TwitterContainer(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
Twitter_API_key = models.fields.CharField(max_length=100)
Twitter_API_key_secret = models.fields.CharField(max_length=100)
Twitter_API_token = models.fields.CharField(max_length=100)
Twitter_API_token_secret = models.fields.CharField(max_length=100)
def __str__(self):
return f'{self.user.username} Twitter Container'
This is my views.py
from django.shortcuts import render, redirect
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from .forms import TwitterUpdateForm
#login_required
def twitter(request):
tw = TwitterUpdateForm(request.POST, instance=request.user)
if tw.is_valid():
tw.save()
messages.success(request, f'NICE!')
return redirect ('home')
else:
tw = TwitterUpdateForm(request.POST, instance=request.user)
context = {'tw': tw}
return render(request, 'twitter_container/twitter_container.html', context=context)
And last but not least, this is my html file.
{% extends 'home/base.html' %}
{% load crispy_forms_tags %}
{% block content %}
<div class="content-section">
</div>
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
<fieldset="form-group">
<legend class="border-bottom mb-4">Profile Information</legend>
{{ u_form|crispy }}
{{ p_form|crispy }}
</fieldset>
<div class="form-group">
<button class="btn btn-outline-info" type="submit">Update</button>
</div>
</form>
</div>
{% endblock content %}
Oh, and my urls.py as well.
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('home.urls')),
path('register/', user_views.register, name='register'),
path('login/', auth_views.LoginView.as_view(template_name='users/login.html'), name='login'),
path('logout/', auth_views.LogoutView.as_view(template_name='users/logout.html'), name='logout'),
path('profile/', user_views.profile, name='profile'),
path('twitter/', twitter_views.twitter, name='twitter'),
]
The issue, I'm facing is that I'm unable to display the form fields from the model to the html. I want to be able to import information into the fields and update it to the database.
Please, do not judge me hard, I am completely newbie.
Thanks in advance.
First of all, you need to add action attribute in your form tag to call the view function when form gets submitted.
It should be like this:
<form method="POST" action ="{% url 'twitter' %}" enctype="multipart/form-data">
Second thing that i found wrong in your html code is, why did you use u_form and p_form as a context variable? it should be 'tw' as per your view.
Try it out with above changes, it might help you out with your requirements.
I'm using Django 3.0.8
in Python version 3.8.2
I'm getting an FieldError at /post/new/
Exception Type: FieldError
Exception Value: Unknown field(s) (content) specified for Post
PostCreateView is a class-based view in my views.py of under the blog app of my current project
My blog/views.py is here:-
from django.shortcuts import render
from .models import Post
from django.views.generic import (
ListView,
DetailView,
CreateView,
)
# Create your views here.
def home(request):
context = {
'posts': Post.objects.all()
}
return render(request, 'blog/home.htm', context)
def about(request):
return render(request, 'blog/about.htm', {'title': 'About'})
# return HttpResponse('<h1> Blog - About page that we want you to see </h1>')
def order(request):
return render(request, 'blog/order.htm')
class PostListView(ListView):
model = Post
template_name = 'blog/home.htm' # <app>/<model>_<viewtype>.html
context_object_name = 'posts'
ordering = ['-date_posted']
class PostDetailView(DetailView):
model = Post
class PostCreateView(CreateView):
model = Post
fields = ['title', 'content']
My blog/urls.py is here:
from django.urls import path
from . import views
from .views import (
PostListView,
PostDetailView,
PostCreateView
)
urlpatterns = [
path('about/', views.about, name='blog-about'),
path('order/', views.order, name='blog-order'),
path('', PostListView.as_view(), name='blog-home' ),
path('post/<int:pk>/', PostDetailView.as_view(), name='post-detail' ),
path('post/new/', PostCreateView.as_view(), name='post-create' ),
]
My blog/templates/blog/post_form.html is here:-
{% extends "blog/base.htm" %}
{% load crispy_forms_tags %}
{% block content %}
<div class="context-section">
<form method="POST">
{% csrf_token %} <!-- for security perpose -->
<fieldset class="form-group">
<legend class="boder-bottom mb-4">Blog Post</legend>
{{ form|crispy }}
</fieldset>
<div class="form-group">
<button class="btn btn-outline-info" type="submit">Post</button>
</div>
</form>
</div>
{% endblock content %}
What wrong is with the code, Please help!!!
I am new to Django and I am completely lost-in here?
I will be very much thankful for your suggestions!!
Thanks and Wellcome
I am creating a blog post with a specific primary key (pk). My other function requires to have the pk as an input (please check the views.py). I am trying to get the post id by getting it as an object id, although it indicated that object has no attribute 'id'.
Any ideas how to get pk as a variable?
Thanks,
Ted
#The template
{% extends "Blog/base.html" %}
{% load crispy_forms_tags %}
{% block content%}
<div class="content-section">
<form method = "POST">
{% csrf_token %}
<fieldset class="form-group">
<legend class="border-bottom mb-4"> Blog Post </legend>
{{ form|crispy }}
</fieldset>
<div class="form-group">
<button class="btn btn-outline-info" type="submit">Post</button>
</div>
</form>
</div>
{% endblock content%}
#urls.py
from django.urls import path
from .views import PostListView, PostDetailView, PostCreateView, PostUpdateView, PostDeleteView
from . import views
urlpatterns = [
path('post/<int:pk>/', PostDetailView.as_view(), name='post-detail'),
path('post/new', PostCreateView.as_view(), name='post-create'),
]
#views.py
from django.shortcuts import render
from django.views.generic import (
ListView,
DetailView,
CreateView,
UpdateView,
DeleteView
)
from .models import Post
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
from .latex import tex
from django.http import FileResponse, Http404
from django.urls import reverse
class PostCreateView(LoginRequiredMixin, CreateView):
model = Post
fields = ['first_name', 'last_name', 'titles' ,'title', 'content', 'billing']
def form_valid(self, form):
form.instance.author = self.request.user # Use this to get the information from the form.
pk = self.object.id
self.external(pk)
return super().form_valid(form),
#Error which I am getting
'NoneType' object has no attribute 'id'
You can obtain the object through the instance wrapped in the form. But as long as the object is not saved, it has no primary key.
class PostCreateView(LoginRequiredMixin, CreateView):
model = Post
fields = ['first_name', 'last_name', 'titles' ,'title', 'content', 'billing']
def form_valid(self, form):
form.instance.author = self.request.user
response = super().form_valid(form)
pk = form.instance.pk
self.external(pk)
return response
What I would like to have is an admin panel that I create where only users with permissions set to "admin" in the UserLevel model can edit certain aspects of the website. However, while I think I have everything coded out properly it isn't working. The way I'm trying to implement this already work on the main content section of my site. My best guess is that since I'm trying to cross-use views between apps something got mixed up, although that may be wrong. Also please keep in mind that while I definitely started with clean code which emulated the code from the working parts of the site this code may not so clean because I have been playing around with it so much that I'm just flat out confused... so any help would be much appreciated.
To be clear, there's no error with the site which is why I think the code is written correctly. However, I made a test widget which is not displaying on the home page at all (it's supposed to), nor will it display on the admin panel page I setup (which is supposed to display any widgets there may be), and I can't get the form for adding a new widget to display on the admin panel page either (it gives me a button to go to another page that has the form on it).
Project urls.py:
"""colors URL Configuration
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/1.11/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: url(r'^$', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.conf.urls import url, include
2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls'))
"""
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
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^$',views.PostListView.as_view(),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'^settings/',views.SettingsListView.as_view(),name='settings'),
url(r'^new/$',views.CreateWidgetView.as_view(),name='create-widget'),
url(r'^delete/$',views.DeleteWidget.as_view(),name='delete-widgets'),
]
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)
class SettingsListView(ListView):
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_query(self):
return Widget.object.filter(order_by('widget_order'))
class DeleteWidget(LoginRequiredMixin,SelectRelatedMixin,DeleteView):
model = Widget
select_related = ('Widget',)
success_url = reverse_lazy('settings')
def get_queryset(self):
queryset = super().get_query()
return queryset.filter(user_id=self.request.user.id)
def delete(self):
return super().delete(*args,**kwargs)
Colorsets app views.py (Where I started mixing things):
from django.shortcuts import render
from colorsets.forms import ColorForm
from colorsets import models
from colorsets.models import ColorSet
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.
#def index(request):
# return render(request,'index.html')
class PostListView(ListView):
model = ColorSet
model = Widget
def get_queryset(self):
return ColorSet.objects.filter(published_date__lte=timezone.now()).order_by('-published_date')
return Widget.objects.filter(order_by('widget_order'))
class CreateColorSetView(LoginRequiredMixin,CreateView):
login_url = '/login/'
redirect_field_name = 'index.html'
form_class = ColorForm
model = ColorSet
def form_valid(self,form):
self.object = form.save(commit=False)
self.object.user = self.request.user
self.object.save()
return super().form_valid(form)
class DeletePost(LoginRequiredMixin,SelectRelatedMixin,DeleteView):
model = models.ColorSet
select_related = ('user',)
success_url = reverse_lazy('index')
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)
Adminpanel app models.py:
from django.db import models
# Create your models here.
class Widget(models.Model):
name = models.CharField(max_length=50)
widget_order = models.IntegerField(default=0)
body = models.TextField(max_length=500)
def __str__(self):
return self.name
widget_list.html:
{% extends "base.html" %}
{% block content %}
<div class="container">
<div class="content">
{% for widget in widget_list %}
<p>{{ widget.body }}</p>
{% endfor %}
</div>
</div>
{% endblock %}
_post.html:
<div class="post media">
<div class="media-body">
<strong>{{ colorset.user.username }}</strong>
<div class="media-footer">
{% if user.is_authenticated and UserLevels.access_level == 'admin' %}
<a href="{% url 'colorsets:delete' pk=colorset.pk %}" title="delete" class="btn btn-simple">
Delete
</a>
{% endif %}
</div>
</div>
</div>
widget_form.html:
{% block content %}
<div class="colorset-base">
<h2>Create new widget</h2>
<form id="postForm" action="{% url 'adminpanel:create-widget' %}" method="POST">
{% csrf_token %}
{{ form }}
<button type="submit" class="submit btn btn-primary btn-large">Add Widget</button>
</form>
</div>
{% endblock %}
settings.html:
{% extends "base.html" %}
{% block content %}
<div class="container">
<h2>Settings:</h2>
</div>
{% endblock %}
widget_confirm_delete.html:
{% extends 'base.html' %}
{% block content %}
<h3>Are you sure you want to delete this widget?</h3>
<div class="posts">
{% include "adminpanel/_post.html" with post=object hide_delete=True %}
</div>
<form method="POST">
{% csrf_token %}
<input type="submit" value="Confirm Delete" class="btn btn-danger btn-large" />
<a class="btn btn-simple btn-large" href="{% url 'adminpanel/settings'%}">Cancel</a>
</form>
{% endblock %}
I know not everything is being used by things but this is everything I have.
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 guessing 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.html'
# 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()
Here's the 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)
Here's my album_form.html file:
{% extends 'music/base.html' %}
{% block title %}Add a New Album{% endblock %}
{% block album_active %}active{% endblock %}
{% block body %}
<div class="container-fluid">
<div class="row">
<div class="col-sm-12 col-md-7">
<div class="panel panel-default">
<div class="panel-body">
<form class="horizontal" action="" method="post" enctype="multipart/form-data">
{% csrf_token %}
{% include 'music/form-template.html' %}
<div class="form-group">
<div class="col-sum-offset-2 col-sm-10">
<button type="submit" class="btn btn-success">Submit</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
Here's my index.html file:
{# loads path to static file #}
{% extends 'music/base.html' %}
{% block body %}
<ul>
{% for album in all_albums %}
<li>{{ album.album_title }}</li>
{% endfor %}
</ul>
{% endblock %}
I suspect you have a recursive reference from your include in music.urls to urls.py since the error that django throws is specific to URL resolver.
Your if statement has no error. 'music:index' refers to namespaced url names and still need named url statements in urls.py. Since in simple projects, there is only one application, the namespace is redundant. So in most cases, 'index' should be used instead, just like what I have show below.
In your urls.py, there is a include to music.urls, and it seems to be recursive reference to itself. 'music.urls' refers to the file urls.py in music directory.
If you do not have a valid python object for 'music.urls', then your include statement is wrong.
I do not use include urls in my project, so there will need to be a statement for each view defined in views.py. To test whether your server starts correctly, I would try the following urlpatterns. Don't forget to import IndexView and DetailView. Add more url statements for you other views after testing out 1 or 2 first.
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^music/index/$', IndexView.as_view() , name='Index'),
url(r'^music/detail/(?P<pk>[0-9]+)/$', DetailView.as_view() , name='Detail'),
]
I use named url, and the statement in index.html should be written as follows:
{{ album.album_title }}
The namespace 'music:' is omitted since it is implicit and will look simpler. You should leave it out for simple applications as it may be confusing for beginners.