__init__() got an unexpected keyword argument 'user_id' in django - python

i have a form for update view like this:
class editpost(forms.ModelForm):
class Meta:
model = Posts
fields = ['body']
and a view like this:
#login_required
def post_edit(request, user_id, post_id):
if request.user.id == user_id:
post = get_object_or_404(Post, pk=post_id)
if request.method == 'POST':
form = editpost(request.POST, instance=post)
if form.is_valid():
ep = form.save(commit=False)
ep.slug = slugify(form.cleaned_data['body'][:30])
ep.save()
messages.success(request, 'your post edited successfully', 'success')
return redirect('account:dashboard', user_id)
else:
form = EditPostForm(instance=post)
return render(request, 'editpost.html', {'form':form})
else:
return redirect('Posts:index')
and url.py like this:
from django.urls import path
from . import views
app_name = 'Posts'
urlpatterns = [
path('', views.index.as_view(),name='index'),
path('<int:year>/<int:month>/<int:day>/<slug:slug>', views.detailPost,name='detail'),
path('addpost/<int:user_id>', views.addpost,name='addpost'),
path('delpost/<int:user_id>/<int:post_id>', views.delpost,name='delpost'),
path('editpost/<int:user_id>/<int:post_id>', views.editpost,name='editpost'),
]
when i open editpost url i got this error,what should i do to fix it?

The path for editpost should point to your view method: views.post_edit not views.editpost
path('editpost/<int:user_id>/<int:post_id>', views.post_edit, name='editpost'),

Related

How to pass field from submitted form into url in Django?

I am trying to submit a form, save to database and then show the cleaned_data on a new url. In the form I have a field called job_number. I would like to send the cleaned_data over to 127.0.0.1:8000/quotes/job_number
quote/views.py:
#login_required
def quote_view(request):
data_form = QuoteInformationForm()
if request.method == "POST":
data_form = QuoteInformationForm(request.POST)
if data_form.is_valid():
data_form.save(commit=True)
return redirect('quote')
else:
print('Error')
return render(request, "index.html", {'data_form': data_form})
#login_required
def submitted_quote(request):
return render(request, "quote.html")
urls.py:
urlpatterns = [
path('home/', quote_view, name='home'),
path('quote/', submitted_quote, name='quote'),
Currently all this does is open the form at http://127.0.0.1:8000/home/ using index.html. When I submit it will send the info to the database and redirect me to http://127.0.0.1:8000/quotes. This is fine. Now I just need to show the cleaned data on this url and change the url to include the job_number at the end. How can I do this?
you need to change url pattern like this:
urlpatterns = [
path('home/', quote_view, name='home'),
path('quote/<int:job_number>/', submitted_quote, name='quote'),
]
and submitted_quotes():
#login_required
def submitted_quote(request,job_number):
job = # Get Your job
return render(request, "quote.html", {"job":job})
and :
#login_required
def quote_view(request):
data_form = QuoteInformationForm()
if request.method == "POST":
data_form = QuoteInformationForm(request.POST)
if data_form.is_valid():
data_form.save(commit=True)
return redirect('quote{}'.format(data_form.id))
else:
print('Error')
return render(request, "index.html", {'data_form': data_form})

Redirect to function based detail view after submitting form

I created a model named Student. I created a model form. I want to go to detail view not the list view, after submitting model form.
How do i do that ?
model.py
class Student(models.Model):
student_name = models.CharField(max_length=100)
father_name = models.CharField(max_length=100)
forms.py
class AdmissionForm(forms.ModelForm):
class Meta:
model = Student
fields = '__all__'
views.py
def admission_form(request):
form = AdmissionForm()
if request.method == 'POST':
form = AdmissionForm(request.POST, request.FILES)
if form.is_valid():
form.save()
return redirect('student-list') # i want to redirect to detail view
context = {'form':form}
return render(request, 'student/admission_form.html', context)
In this admission form, i want to redirect to detail view of the student not the list view. How can i do that. In this code, i have redirected to list view.
def student_detail(request, id):
stud = Student.objects.get(id=id)
context = {'stud':stud}
return render(request, 'student/student_detail.html', context)
urls.py
urlpatterns = [
path('admission_form/', views.admission_form, name = 'admission-form'),
path('student/', views.student_list, name = 'student-list'),
path('student/<int:id>/', views.student_detail, name = 'student-detail'),
]
form.save() will return an instance of Student model. You can use it's id in redirect like this:
def admission_form(request):
form = AdmissionForm()
if request.method == 'POST':
form = AdmissionForm(request.POST, request.FILES)
if form.is_valid():
instance = form.save()
return redirect('student-detail', id=instance.pk)

Django Converting to CBV + tests

I'm trying to test my app. I went over the documentation, and managed to make the test for my URL's and all views but one.
I'm having trouble converting it to a class view and I'm not really sure what kind of tests should I do here ? The documentation explained how it works, but I don't now where to go from here..
Anyone mind helping me out ?
here is the view that I'm trying to convert and test :
def add_comment_to_article(request, pk):
article = get_object_or_404(Article, pk=pk)
if request.method == "POST":
form = CommentForm(request.POST)
if form.is_valid():
comment = form.save(commit=False)
comment.post = article
comment.save()
return HttpResponseRedirect(reverse('news:article', kwargs={"article_id": article.pk}))
else:
form = CommentForm()
return render(request, 'news/add_comment_to_article.html', {'form': form})
my urls :
app_name = "news"
urlpatterns = [
path('', views.IndexView.as_view(), name='index'),
path('<int:article_id>/', views.article_view, name='article'),
path('articles/', views.ArticlesView.as_view(), name='articles'),
path('search/', include('haystack.urls',)),
path('<int:pk>/comment/', views.CommentCreateView.as_view(), name='add_comment_to_article'),
#path('articles/<int:category_id>', views.CategoryView.as_view(), name="category")
]
my form:
class CommentForm(forms.ModelForm):
class Meta:
model = Comment
fields = ('author', 'text',)
The view is in charge of adding a comment to my Article post.
Thank you !!
So assuming you don't have the post field in your CommentForm, I'd maybe do something like this:
# views.py
from django.views.generic import CreateView
from .models import Comment
class CommentCreateView(CreateView):
model = Comment
form_class = CommentForm
template_name = 'my_template.html'
def form_valid(self, *args, **kwargs):
article = get_object_or_404(Article, pk=kwargs.get('pk'))
comment = form.save(commit=False)
comment.post = article
comment.save()
return HttpResponseRedirect(reverse('news:article', kwargs={'article_id': article.pk}))
# tests.py
from django.tests import TestCase
class CreateCommentViewTestCase(TestCase):
def setUp(self):
# maybe look into factory boy if you haven't already
self.article = Article.objects.create()
def test_get(self):
response = self.client.get(reverse('news:add_comment_to_article', kwargs={'article_id': self.article.pk}))
self.assertEqual(response.status_code, 200)
def test_post(self):
# populate with form data
post_data = {'form_field': 'value'}
original_comment_count = self.article.comment_set.all().count()
response = self.client.post(reverse('news:add_comment_to_article', kwargs={'article_id': self.article.pk}))
new_comment_count = self.article.comment_set.all().count()
self.assertNotEqual(original_comment_count, new_comment_count)
self.assertEqual(response.status_code, 302)
django-webtest is pretty useful for testing CBVs too.

'AnonymousUser' object has no attribute '_meta'

views.py code
from django.shortcuts import render,redirect
from django.http import HttpResponse
from django.contrib.auth.forms import UserCreationForm
from tutorial import views
from accounts.form import Registrationform,EditProfileForm
from django.contrib.auth.forms import UserChangeForm,PasswordChangeForm
from django.contrib.auth.models import User
from django.contrib.auth import update_session_auth_hash
# Create your views here.
def home(request):
numbers=[1,2,3,4,5]
name="jay"
args={'myName':name}
return render(request,'accounts/home.html',args)
def register(request):
if request.method == "POST":
form = Registrationform(request.POST)
if form.is_valid():
form.save()
return redirect('/account')
else:
return HttpResponse('please fill all the fields and make sure new password must be match')
else:
form = Registrationform()
args={'form' : form}
return render(request,'accounts/reg_form.html',args)
def view_profile(request):
args = {'user' : request.user}
return render(request,'accounts/profile.html',args)
def edit_profile(request):
if request.method=="POST":
form = EditProfileForm(request.POST,instance=request.user)
if form.is_valid():
form.save()
return redirect('/account/profile')
else:
form = EditProfileForm(instance=request.user)
args = {'form' : form}
return render(request,'accounts/edit_profile.html',args)
def change_password(request):
if request.method == "POST":
form = PasswordChangeForm(data=request.POST,user=request.user)
if form.is_valid():
form.save()
update_session_auth_hash(request, form.user)
return redirect('/account/profile')
else:
return HttpResponse("password doest not match,go back and try again")
else:
form = PasswordChangeForm(user=request.user)
args = {'form' : form}
return render(request,'accounts/change_password.html',args)
and form.py is
from django import forms
from django.contrib.auth.forms import UserCreationForm,UserChangeForm
from django.contrib.auth.models import User
#from django.forms import RegistrationForm,EditProfileForm
class Registrationform(UserCreationForm):
email = forms.EmailField(required=True)
class Meta:
model = User
fields = (
'username',
'first_name',
'last_name',
'email',
'password1',
'password2',
)
def save(self,commit=True):
user=super(Registrationform,self).save(commit=False)
user.first_name= self.cleaned_data['first_name']
user.last_name=self.cleaned_data['last_name']
user.email=self.cleaned_data['email']
if commit:
user.save()
return user
class EditProfileForm(UserChangeForm):
#template_name = '/something/else'
class Meta:
model = User
fields = (
'email',
'first_name',
'last_name',
'password'
)
and urls.py
#python -m smtpd -n -c DebuggingServer localhost:1025
from django.contrib import admin
from .import views
from django.conf.urls import url,include
from django.contrib.auth.views import login,logout,password_reset,password_reset_done,password_reset_confirm,password_reset_complete
#from django.urls import path
urlpatterns = [
url(r'^$',views.home),
url(r'^login/$',login,{'template_name' : 'accounts/login.html'}),
url(r'^logout/$',logout,{'template_name' : 'accounts/logout.html'}),
url(r'^register/$',views.register,name='register'),
url(r'^profile/$',views.view_profile,name='view_profile'),
url(r'^profile/edit/$',views.edit_profile,name='edit_profile'),
url(r'^change-password/$',views.change_password,name='change_password'),
url(r'^reset-password/$',password_reset,name='reset_password'),
url(r'^reset-password/done/$',password_reset_done,name='password_reset_done'),
url(r'^reset-password/confirm/(?P<uidb64>[0-9A-Za-z]+)-(?P<token>.+)/$',
password_reset_confirm,name='password_reset_confirm' ),
url(r'^reset-password-complete/$',password_reset_complete,name='password_reset_complete'),
]
So when i enter url -" http://127.0.0.1:8000/account/profile/edit/ " its give me error
"'AnonymousUser' object has no attribute '_meta'"
What is the mistake ?what i did wrong here ? and django gives this line error
/usr/local/lib/python2.7/dist-packages/django/utils/functional.py in
inner, line 205.
what should i do to solve this error ?
You are not logged in and trying to modify profile. To prevent such kind of error, add is_authenticated validation to your view. If user is not authenticated, you can redirect him to login page with redirect shortcut function:
def edit_profile(request):
if request.user.is_authenticated:
if request.method=="POST":
form = EditProfileForm(request.POST,instance=request.user)
if form.is_valid():
form.save()
return redirect('/account/profile')
else:
form = EditProfileForm(instance=request.user)
args = {'form' : form}
return render(request,'accounts/edit_profile.html',args)
else:
return redirect('/login/')
It's better to use login_required decorator. It will check whether user logged in or not without coding it explicitly.
from django.contrib.auth.decorators import login_required
#login_required
def edit_profile(request):
if request.method=="POST":
form = EditProfileForm(request.POST,instance=request.user)
if form.is_valid():
form.save()
return redirect('/account/profile')
else:
form = EditProfileForm(instance=request.user)
args = {'form' : form}
return render(request,'accounts/edit_profile.html',args)

Displaying Django Form Results

I have a Django Form (ModelForm) which has a number of fields. When the user presses submit these are then saved to a database. What I am struggling to work out is, how do I then output/render these results in some other HTML page.
Models.py
from django.db import models
# Create your models here.
class Contract(models.Model):
name = models.CharField(max_length=200)
doorNo = models.SlugField(max_length=200)
Address = models.TextField(blank=True)
Forms.py
from django import forms
from contracts.models import Contract
class GenerateContract(forms.ModelForm):
class Meta():
model = Contract
fields = '__all__'
Views.py
from django.shortcuts import render
from contracts.forms import GenerateContract
# Create your views here.
def index(request):
return render(request, 'contracts/index.html')
def contractview(request):
form = GenerateContract()
if request.method == "POST":
form = GenerateContract(request.POST)
if form.is_valid():
form.save(commit=True)
return index(request)
else:
print('ERROR')
return render(request,'contracts/contracts.html',{'form':form})
At the moment, I am returning the 'Index' Home page of the app as a placeholder.
After validation, the form data is found in form.cleaned_data dictionary. So you can pass that back to the template and display it as you see fit.
from django.shortcuts import render
from contracts.forms import GenerateContract
# Create your views here.
def index(request):
return render(request, 'contracts/index.html')
def contractview(request):
form = GenerateContract()
if request.method == "POST":
form = GenerateContract(request.POST)
if form.is_valid():
form.save(commit=True)
return render(request,'contracts/contracts.html',{'form_data': form.cleaned_data})
else:
print('ERROR')
return render(request,'contracts/contracts.html',{'form':form})
If you want to show the form with the saved values, you can render the template with form and fill the instance input . like this:
from django.shortcuts import render
from contracts.forms import GenerateContract
# Create your views here.
def index(request):
return render(request, 'contracts/index.html')
def contractview(request):
form = GenerateContract()
if request.method == "POST":
form = GenerateContract(request.POST)
if form.is_valid():
saved_instance = form.save(commit=True)
return render(request,'contracts/contracts.html',{'form':GenerateContract(instance=saved_instance)})
else:
print('ERROR')
return render(request,'contracts/contracts.html',{'form':form})

Categories