ImageField Form doesn't work in django - python

I know that there's a lot of similar questions to mine on stackoverflow but none of them fixed my problem.
I have a form with an imagefield which doesn't work as it should redirect to the index page when it succeeds but it doesn't. I can create a payment with that image from the admin panel but the form doesn't work.
models.py
class Payment(models.Model):
Address = models.CharField(max_length=255)
Payment_ID = models.ImageField(upload_to='payproof')
Status = models.CharField(max_length=5, default="X")
Review_result = models.CharField(max_length=255, default="Not yet reviewed")
created = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ['-created']
def __unicode__(self):
return u'%s'% self.Status
def __str__(self):
return self.Status
views.py
def new_payment(request):
template ='payment.html'
form = PayForm(request.POST or None)
if form.is_valid():
form.save()
return redirect('index')
else:
form = PayForm()
context = {
'form' : form,
}
return render(request, template, context)
forms.py
class PayForm(forms.ModelForm):
Payment_ID = forms.ImageField()
class Meta:
model = Payment
fields = ['Address',
'Payment_ID']

So the problem was simple i was doing request.POST but the img is a file so all what i should of done was add request.FILES
form = PayForm(request.POST, request.FILES or None)

Related

Django: Why does my validation error not show? The title is a unique field that is checked under clean_title, but it just redirects to the profile?

So my form redirects to my profile page, and the form is saved if has a unique title, however this validation error is not raised on testing.
Essentially my slug field is a primary key of sorts, with it being generated from the title in views.py. I know its not the best solution to a primary key, but I thought an easy way to make it unique was to ensure the title was too on form submission.
I've tried the old generate a unique slug, but that dosent seem to work either.
Forms.py
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = ["title", "content", "featured_image", "excerpt", "status"]
def clean_title(self):
title = self.cleaned_data['title']
if Post.objects.filter(title=title).exists():
raise forms.ValidationError("Title already exists")
return title
Views.py
class CreatePost(View):
def get(self, request):
return render(request, 'create_post.html', {
'post_form': PostForm,
})
def post(self, request):
form = PostForm(request.POST)
if form.is_valid():
post = form.save(commit=False)
post.author = request.user
post.slug = slugify(post.title)
post.save()
return HttpResponseRedirect(reverse('profile', args=[request.user]))
The Post Model from models.py
class Post(models.Model):
title = models.CharField(max_length=200, unique=True)
slug = models.SlugField(max_length=200, unique=True)
author = models.ForeignKey(
User, on_delete=models.CASCADE, related_name="blog_posts"
)
featured_image = CloudinaryField('image', default='placeholder')
excerpt = models.TextField(blank=True)
updated_on = models.DateTimeField(auto_now=True)
content = models.TextField()
created_on = models.DateTimeField(auto_now_add=True)
status = models.IntegerField(choices=STATUS, default=0)
likes = models.ManyToManyField(
User, related_name='blogpost_like', blank=True)
class Meta:
ordering = ["-created_on"]
def __str__(self):
return self.title
def number_of_likes(self):
return self.likes.count()
please be nice im not a pro dev... yet :)
of course. You have always redirect:
def post(self, request):
...
if form.is_valid():
...
return HttpResponseRedirect(reverse('profile', args=[request.user]))
in your case it should be:
def post(self, request):
...
if form.is_valid():
...
return HttpResponseRedirect(reverse('profile', args=[request.user]))
return render(request, 'create_post.html', {'post_form': form})
At first, you have an error on get(). In context you send class PostFrom and not the instance of this class. Right now it works, the template create empty instance of class PostForm, but the logic is wrong.
My opinion, try to use GCBV in your case CreateView. It is easier and you can not do stupid errors: the CreateView do it for you. :)
Read more here:
https://docs.djangoproject.com/en/4.0/ref/class-based-views/generic-editing/#django.views.generic.edit.CreateView

Django TypeError: Field 'id' expected a number but got <homeworkForm bound=True, valid=Unknown, fields=(title;descripiton;due)>

I have been trying to allow staff users to post homework to a database however I keep running into the issue above. I've tried setting data['id'] = 0/'' as well as dropped the table and makemigrations/migrate.
models.py
from django.db import models
from teachers.models import Teacher
class Homework(models.Model):
title = models.CharField(max_length=100)
descripiton = models.CharField(max_length=500)
due = models.DateField()
teacher = models.OneToOneField(
Teacher, null=True, blank=True, on_delete=models.CASCADE)
def __str__(self):
return self.title
form.py
from django import forms
class DateInput(forms.DateInput):
input_type = 'date'
class HomeworkForm(forms.Form):
title = forms.CharField(label='Title', max_length=100)
descripiton = forms.CharField(label='Descripiton', max_length=500)
due = forms.DateField(label='Due', widget=DateInput)
views.py
def homework(request):
if request.user.is_authenticated & request.user.is_staff:
if request.method == 'POST':
data = request.POST.copy()
data['teacher'] = request.user.username
request.POST = data
print(request.POST)
form = HomeworkForm(request.POST)
if form.is_valid():
post = Homework(form)
post.save()
messages.info(request, 'Form sent')
print('worked')
return render(request, 'index/index.html')
else:
print('error in form')
form = HomeworkForm()
return render(request, 'dashboard/setHomework.html', {'form': form})
else:
form = HomeworkForm()
return render(request, 'dashboard/setHomework.html', {'form': form})
else:
return redirect('index')
Did you try data['teacher'] = request.user instead of data['teacher'] = request.user.username ?
You do not need to use request.POST.copy(), request.POST is already a dictionary.
I appreciate the answers. I managed to fix the issue by converting the form to a model form as that form model works better for the situation as the model fields are mapped directly to the inputs.
new forms.py
from homework.models import Homework
from django import forms
class HomeworkForm(forms.ModelForm):
class Meta:
model = Homework
fields = ['title', 'description', 'due']
widgets = {
'due': forms.DateInput(format=('%m/%d/%Y'), attrs={'label': 'due date', 'type': 'date'}),
}

How can i set permission on url

I am new on Django,
I have implemented a valid form and now I want to set permission on URL.
When a form is submitted, then it redirects me to this URL
http://127.0.0.1:8000/success/
Without submitting a form I can manually type the name of the URL http://127.0.0.1:8000/success/ and it will take me to the same page.
How can I set permission on "success" url, so that user can not manually view the page unless the form is valid and submitted?
Do I need a decorator for this?
Model:
class Profile(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL,on_delete=models.CASCADE,blank=True,null=True)
profile_pic = models.ImageField(upload_to='ProfilePicture/', default="ProfilePicture/avatar.png", blank=True)
phone = models.IntegerField(default='0', blank=True)
email = models.EmailField(blank=True)
date_of_birth = models.CharField(max_length=50, blank=True)
address = models.TextField(blank=True)
date = models.DateTimeField(auto_now_add=True)
class Meta:
verbose_name = 'Profile'
verbose_name_plural = 'Profiles'
ordering = ['-date']
'''Method to filter database results'''
def __str__(self):
return self.user.username
class CotCode(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
cot_code = models.IntegerField(default='0', blank=True)
date = models.DateTimeField(auto_now_add=True)
class Meta:
verbose_name = 'CotCode'
verbose_name_plural = 'CotCode'
ordering = ['-date']
def __str__(self):
return self.user.username
Url:
path('cot/', TransferCOTView, name='transfer_cot'),
path('success/', SuccessfulView, name='successful_trans'),
Views:
#login_required
def TransferCOTView(request):
form = CotCodeForm(request.POST)
if request.method == "POST":
if form.is_valid():
cot_code = form.cleaned_data.get('cot_code')
try:
match = CotCode.objects.get(cot_code=cot_code)
return redirect('site:successful_trans')
except CotCode.DoesNotExist:
messages.info(request, "Wrong code")
else:
form = CotCodeForm()
context = {
'form':form,
}
return render(request, 'transfer_cotcode.html', context)
#login_required
def SuccessfulView(request):
return render(request, 'successful_transfer.html')
A simple option would be to set a session variable informing that the form was posted and valid and check it before displaying the success page. See session examples here https://docs.djangoproject.com/en/3.1/topics/http/sessions/#examples
e.g.
def formview(request):
# process form
request.session["form_filled"] = True
# redirect to success
def success(request):
if not request.session.get("form-filled"):
raise Http404("Form not filled")
del request.session["form_filled"] # success view visible once after form is filled
# return view template
You can also check if the user has COT code filled in the success view.
def SuccessfulView(request):
cot_code_exists = CotCode.objects.filter(user=request.user).count()
if not cot_code_exists:
raise Http404("Cot code does not exist for user")
return render(request, 'successful_transfer.html')

django unable to saved forms in database

I'm learning django and I'm trying to save the form using POST method and found its working fine, I'M not able to see the saved message in database(form is not submitted)
Models.py
class Post(models.Model):
title = models.CharField(max_length=200)
description = models.TextField(max_length=10000)
pub_date = models.DateTimeField(auto_now_add=True)
slug = models.SlugField(max_length=200, unique=True)
def __unicode__(self):
return self.title
def description_as_list(self):
return self.description.split('\n')
class Comment(models.Model):
title = models.ForeignKey(Post)
comments = models.CharField(max_length=200)
def __unicode__(self):
return '%s' % (self.title)
Forms.py
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = ('title', 'description')
editPostedForm = modelformset_factory(Post, PostForm)
class CommentForm(forms.ModelForm):
class Meta:
model = Comment
fields = ('comments',)
exclude = ('title',)
Views.py
def detail(request, id):
posts = Post.objects.get(id=id)
comments = posts.comment_set.all()
forms = CommentForm
if request.method == 'POST':
form = CommentForm(request.POST, instance=posts)
print form
if form.is_valid():
form.save(commit=False)
form.save()
else:
print form.errors
else:
form = PostForm()
return render(request, "detail_post.html", {'forms':forms,'posts': posts,'comments':comments})
Why is the post message is not being saved. I got status code 200 in console, also i get the entered data, but the form is not being saved...Any help is much appreciated
I think the problem is that your form excludes title field, but it's required according to Comment definition. You need to give the title to comment instance then save it:
def detail(request, id):
posts = Post.objects.get(id=id)
comments = posts.comment_set.all()
forms = CommentForm
if request.method == 'POST':
form = CommentForm(request.POST,instance=posts)
print form
if form.is_valid():
# create a comment instance in memory first
comment = form.save(commit=False)
# fill out the title field
comment.title = posts
comment.save()
else:
print form.errors
else:
form = PostForm()
return render(request, "detail_post.html", {'forms':forms,'posts': posts,'comments':comments})
Also, I don't know why you use plural form for one instance, like posts should be post because you use objects.get(), make your code more readable would save some confusion for other people.

How to get value from Django authentication forms and use that value as input to another form?

I have a form used to create new posts in a blog, and one of the fields in that form is the owner, which means who is posting it, but that should be taken from login view when user provides his/her login information I don't want the user selecting who is the owner from a list, it should be automatically populated and fixed with his username. I tried different ways, fixing the value on my forms.py but didn't work, it doesn't recognizes the variable. This is my forms.py:
class UserForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput())
class Meta:
model = User
fields = ('username', 'email', 'password')
class UserProfileForm(forms.ModelForm):
class Meta:
model = UserProfile
fields = ('website', 'picture')
class CreatePostForm(forms.ModelForm):
class Meta:
model = Post
fields = ('title', 'body','datposted', 'category','owner')
Here is what I have on models:
class Post(models.Model):
title = models.CharField(max_length=100)
body = models.TextField()
datposted = models.DateTimeField('date posted')
category = models.ForeignKey('Category')
owner = models.ForeignKey('UserProfile')
def __str__(self):
return '%s' % self.title
This is my view:
def create_post(request):
if request.method == 'POST':
form = CreatePostForm(request.POST)
if form.is_valid():
post = form.save(commit=False)
post.datposted = datetime.datetime.now()
#post.owner = request.user()
post.save()
return HttpResponseRedirect('/posts/')
else:
return HttpResponse("Favor. Verifique os campos necessarios")
else:
form = CreatePostForm()
f = {'form' : form}
return render(request,'create_post.html',f)
Could you please help with more details?
I think you just have to remove the 'owner' field from the form and make sure that you handle populating the owner in your view
class CreatePostForm(forms.ModelForm):
class Meta:
model = Post
fields = ('title', 'body','datposted', 'category')
view
def create_post(request):
if request.method == 'POST':
form = CreatePostForm(request.POST)
if form.is_valid():
Posts = form.save(commit=False)
# replace below with however you get user profile
Posts.owner = get_user_profile_from_logged_in_user()
Posts.save()
return HttpResponseRedirect('/posts/')
else:
return HttpResponse("Favor. Verifique os campos necessarios")
else:
form = CreatePostForm()
f = {'form' : form}
return render(request,'create_post.html',f)
This case is covered in django docs:
https://docs.djangoproject.com/en/1.7/topics/forms/modelforms/#the-save-method

Categories