How can i set permission on url - python

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')

Related

Django Error : ValueError at / Field 'ticket_id' expected a number but got 'NS000001'

While Inserting data, I got this error. May be this could be due to change of default primary key. I do not want to enter ticket_id field as I have set default value for that field (default='NS000001')
models.py
class Ticket(models.Model):
ticket_id = models.AutoField(primary_key=True, default='NS000001', editable=False)
server_details = models.CharField(max_length=100)
send_date = models.DateTimeField(default=timezone.now)
license_no = models.CharField(max_length=25)
file = models.FileField(upload_to='documents/%Y/%m/%d/')
def __str__(self):
return self.ticket_id
views.py
def Index(request):
if request.method == "POST":
form = SaveTicket(request.POST,request.FILES or None)
if form.is_valid():
form.save()
print(form)
return redirect('index')
else:
form = SaveTicket()
return render(request, 'index.html')
forms.py
class SaveTicket(forms.ModelForm):
class Meta:
model = Ticket
fields = ['server_details','send_date','license_no','file']
first
you don't need define Autofield yourself.
class Ticket(models.Model):
server_details = models.CharField(max_length=100)
send_date = models.DateTimeField(default=timezone.now)
license_no = models.CharField(max_length=25)
file = models.FileField(upload_to='documents/%Y/%m/%d/')
second
If your Ticket ID is static - you can create a property:
class Ticket(models.Model):
... # any staff here
#property
def ticket_id(self):
return f'NS{(self.pk or 0):06d}'
last
after that you can use it everywhere:
print(ticket.ticket_id)
>>>'NS2134154'

Python Django: "Post.author" must be a "User" instance error

I am trying to assign username to author field in Post model , Django spews out the following error:
"Post.author" must be a "User" instance.
model:
class Post(models.Model):
title = models.CharField(max_length=200)
image = models.ImageField(upload_to='',null=True,blank=True)
image_url = models.CharField(max_length=200,default=None,null=True,blank=True)
date = models.DateTimeField(default=timezone.now)
content = models.TextField()
author = models.ForeignKey(User, null=False, blank=False,on_delete=models.CASCADE)
categories = models.ManyToManyField(Category)
published = models.BooleanField()
def __str__(self):
return self.title
view:
#login_required
def new_post(request):
# Add a new post
if request.method != 'POST':
# No data submitted, create a blank form
form = PostForm()
else:
# Post data submitted, process data
form = PostForm(data=request.POST)
if form.is_valid():
new_post = form.save(commit=False)
new_post.author = request.user.username
new_post.save()
return redirect('elogs:posts')
#Display a blank or invalid form
context = {'form':form}
return render(request,'elogs/new_post.html',context)
form:
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = ['title','content','image','image_url','published']
widgets = {
'title': forms.Textarea(attrs={'placeholder': 'Title..'}),
'content': forms.Textarea(attrs={'placeholder': 'What is on your mind?'}),
'categories': forms.TextInput()
}
I have solved this error just like this:
from django.contrib.auth import get_user_model
author = models.OneToOneField(get_user_model(),on_delete=models.CASCADE)
You're giving the username instead of the user itself:
new_post.author = request.user.username
A ForeignKey takes an instance of the given Model, User in this case.

Allow the user to input only a part of django model creaton form (add to form after user submitted it)

How I can add data to form that user submitted ? I want the user to fill in the "name" and "done" in the form and automatically add "user" (creator) and "board"
code:
#views.py
#login_required(login_url='loginPage')
def taskAdd(request, pk):
board = Board.objects.filter(user=request.user).get(pk=pk)
form = AddTaskForm()
if request.method == "POST":
form = AddTaskForm(request.POST)
if form.is_valid():
form.initial['user'] = request.user
form.initial['board'] = board
# that doesn't seem to work....
form.save()
return redirect('insideBoard', pk)
context = {'form': form}
return render(request, 'tasks/taskAdd.html', context)
#forms.py
class AddTaskForm(ModelForm):
class Meta:
model = Task
fields = "__all__"
exclude = ('user', 'board',)
#models.py
class Board(models.Model):
title = models.CharField(max_length=50, null=True)
user = models.ForeignKey(User, null=True, on_delete=models.CASCADE)
def __str__(self):
return self.title
class Task(models.Model):
title = models.CharField(max_length=200, null=True)
done = models.BooleanField(default=False, null=True)
created_at = models.DateTimeField(auto_now_add=True, null=True)
user = models.ForeignKey(User, null=True, on_delete=models.CASCADE)
board = models.ForeignKey(Board, null=True, on_delete=models.CASCADE)
def __str__(self):
return self.title
You can edit the instance wrapped in the form:
from django.shortcuts import get_object_or_404
#login_required(login_url='loginPage')
def taskAdd(request, pk):
board = get_object_or_404(Board, user=request.user, pk=pk)
form = AddTaskForm()
if request.method == 'POST':
form = AddTaskForm(request.POST)
if form.is_valid():
form.instance.user = request.user
form.instance.board_id = pk
form.save()
return redirect('insideBoard', pk)
context = {'form': form}
return render(request, 'tasks/taskAdd.html', context)
Note: It is often better to use get_object_or_404(…) [Django-doc],
then to use .get(…) [Django-doc] directly. In case the object does not exists,
for example because the user altered the URL themselves, the get_object_or_404(…) will result in returning a HTTP 404 Not Found response, whereas using
.get(…) will result in a HTTP 500 Server Error.

ImageField Form doesn't work in django

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)

Django get form with data from the database

I am trying to create a form that allows users to edit their profile data. As such I want to have the most recent data from the database be displayed when the user goes to edit the form. Heres what I have so far:
# models.py
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
location = models.CharField(max_length=30, blank=True)
birthdate = models.DateField(null=True, blank=True)
def __str__(self):
return self.user.username
# forms.py
class EditProfileForm(forms.ModelForm):
class Meta:
model = Profile
fields = ['location', 'birthdate']
# views.py
class EditProfileFormView(View):
form_class = EditProfileForm
template_name = 'forums/edit-profile.html'
def get(self, request, username):
try:
user = User.objects.get(username=username)
except User.DoesNotExist:
raise Http404('The User "' + username + '" could not be found.')
if (not request.user.is_authenticated):
return HttpResponseForbidden()
elif (user.id is not request.user.id):
return HttpResponseForbidden()
form = self.form_class(None)
return render(request, self.template_name, {'form': form})
Setting the form to form_class(None) is what gives me an empty form, however dropping user.profile in the same spot gives me an error 'Profile' object has no attribute 'get'
Try populating the form with an instance
form = self.form_class(instance=user.profile)
Note: this would probably be easier with a standard UpdateView

Categories