Django delete models based on form input - python

I have a form and a model, in my views I take the data from form and use it to delete the object from my model, but it does not delete the object at all, even though if I use the shell and create the same query set with the same syntax it works. What am I missing here?? Thx
Code from views:
form = SecondForm()
query_list = DictWord.objects.all()
dict_DictWord = {'words': query_list,"form":form}
if request.method == "POST":
form = SecondForm(request.POST)
if form.is_valid():
##Does not delete the object from models
data = form.cleaned_data['name']
DictWord.objects.filter(name=data).delete()
return render(request, 'appone/index.html', context = dict_DictWord)
else:
messages.error(request, "Error")
return render(request,'appone/index.html',context=dict_DictWord)
But if I use manage.py shell, I import my model and this syntax works, and it returns the dict with the deleted object:
from app.models import DictWord
DictWord.objects.filter(name="SomeName").delete()

#try this
record=DictWord.objects.get(name=data)
record.delete()
return render(request, 'appone/index.html', context = dict_DictWord)

Related

Unable to get or create object within a form

I am trying to get or create an object when another one is created with a form :
def index(request, log_id, token):
log = get_object_or_404(LogBook, pk=log_id)
logmessages = LogMessage.objects.filter(logbook=log_id)
form = CreateLogMessage(request.POST)
if request.method == "POST":
if form.is_valid():
instance = form.save(commit=False)
instance.reported_by = request.user
instance.logbook = log
instance.save()
logdone = LogDone.objects.get_or_create(logmessage=logmessages, done_status=False)
I am trying to figure out a way to get the id of the logmessage created to pass it to my logdone instance.
I don't find a way to do it so far, any help will be appreciate it.
The object that is created is the instance, you thus can implement this as:
from django.shortcuts import redirect
def index(request, log_id, token):
log = get_object_or_404(LogBook, pk=log_id)
if request.method == 'POST':
form = CreateLogMessage(request.POST)
if form.is_valid():
form.instance.reported_by = request.user
form.instance.logbook = log
instance = form.save()
logdone = LogDone.objects.get_or_create(
logmessage=instance,
done_status=False
)
return redirect('name-of-some-view')
else:
form = CreateLogMessage(request.POST)
…
Since your form creates a new object every time, this however always create an object.
Note: In case of a successful POST request, you should make a redirect
[Django-doc]
to implement the Post/Redirect/Get pattern [wiki].
This avoids that you make the same POST request when the user refreshes the
browser.
Note: You can limit views to a view to authenticated users with the
#login_required decorator [Django-doc].

Obtaining data from the form with GET data. Django

How can I get data from the form using the GET method?
For example, I have this form:
class LoansSearchForm(forms.Form):
balance = forms.IntegerField(label='', required=False)
In my view display in the form template this way:
def search_results(request):
form = LoansSearchForm(request.GET)
cd = form.cleaned_data
word = cd['balance']
context = {'form': form,
'test': word,}
return render(request, 'search_results.html', context)
But i still a error:
'LoansSearchForm' object has no attribute 'cleaned_data'
When trying to get them this way:
word = form['balance']
I receive a field with completed data. How to get the data from my the form correctly?
Is my form written correctly? Should I use something like that?
(sorry if my question is trivial, but I found very little information about GET forms)
if request.method == 'GET':
form = LoansSearchForm(request.GET)
if form.is_valid():
print('Hello World')
else:
form = LoansSearchForm()
Recommended: run form.is_valid() and then you do form.cleaned_data
def search_results(request):
form = LoansSearchForm(request.GET)
if form.is_valid():
cd = form.cleaned_data
word = cd['balance']
else:
word = None
context = {'form': form,
'test': word,}
return render(request, 'search_results.html', context)
Forms only get a cleaned_data attribute when is_valid() has been called, and you haven't called it anywhere.
more on cleaned data - documentation
def search_results(request):
form = LoansSearchForm(request.GET)
cd = form.cleaned_data # here <------
word = cd['balance']
context = {'form': form,
'test': word,}
return render(request, 'search_results.html', context)
The problem with your code is that forms are not filled on initialization but when you call form.is_valid, if the form is indeed valid, then it populates cleaned_data
You can read more about the related documentation.
I used name=form.data['field_name'], think it answers your answer of obtaining form values on submit.

Django validator not triggering on file upload

I have wrote a Django app for the user to upload files and see a list of uploaded files. I want to restrict the uploads to only using gif format and wrote a simple validator. Then I pass that validator in the Model, however it never triggers and the file is saved regardless of the format. Here's what I got so far.
views.py
def list(request):
# Handle file upload
if request.method == 'POST':
form = DocumentForm(request.POST, request.FILES)
if form.is_valid():
newdoc = Document(docfile=request.FILES['docfile'])
newdoc.save()
messages.add_message(request, messages.INFO, "Saved")
# Redirect to the document list after POST
return HttpResponseRedirect(reverse('list'))
else:
form = DocumentForm() # A empty, unbound form
# Load documents for the list page
documents = Document.objects.all()
# Render list page with the documents and the form
return render(
request,
'list.html',
{'documents': documents, 'form': form}
)
checkformat.py
def validate_file_type(upload):
if not (upload.name[-4:] == '.gif'):
raise ValidationError('File type not supported.')
models.py
from .checkformat import validate_file_type
def content_file_name(instance, filename):
return '/'.join(['documents', str(filename), filename])
class Document(models.Model):
docfile = models.FileField(upload_to=content_file_name, validators=[validate_file_type], null=False, verbose_name="File")
forms.py
class DocumentForm(forms.Form):
docfile = forms.FileField(
label='Select a file', widget=forms.FileInput(attrs={'accept':'image/gif'})
)
Is there something I'm missing? I've just started learning Django. Also, I know this is not a sercure way to check for a file type, but I just want to see it work to continue. Thank you for your time.
if form.is_valid():
newdoc = Document(docfile=request.FILES['docfile'])
if not '.gif' in newdoc.name:
raise ValidationError('File type not supported.')
else:
newdoc.save()
messages.add_message(request, messages.INFO, "Saved")
try this simple solution, hope it works as you need
Looks right so far. Maybe it's simply a lower/upper case issue?
A more accurate solution might be:
import os
def validate_file_type(upload):
if os.path.splitext(upload.name)[1].lower() != '.gif':
raise ValidationError('File type not supported.')
If it's still not working try to add a break point within the validation method and check the value of upload.name.
I think the problem is the form is derived from a simple Model class, but in your case you must use ModelForm instead.
This way the form knows about the Document model, and you can do some fancy operations, like calling the save mehond in the Form object so save the model instance. Also the is_valid method calls all the validations defined in the model, in addition to the validations defined in the Form itself.

Python Django - Access Response Headers In View

I am working on a web application which works with entities that all have their unique IDs.
I have a submit form for users to create these entities and this form is in several steps (i.e. view 1 redirects to view 2, etc... until the end of the submission process).
The first view will create the ID of the entity after form submission and I then need to use the ID of the instance created in the other views.
I do not want to pass this ID as a URL parameter to the other views as these will be POST and that means that users could easily manipulate these and create records in models for several IDs. I have managed to pass this ID to several views using the session parameters (request.session) but this is not ideal as this is permanent for the session. Current code below:
def view1(request):
if request.method == 'POST':
form = xxx_creation_form(request.POST)
if form.is_valid():
cleaned_form_data = form.cleaned_data
xxx_entry = Model.objects.create(
... object creation ...
)
request.session['xxx_id'] = xxx_entry.id
return HttpResponseRedirect(reverse('form_2'))
else:
form = xxx_creation_form()
return render(request, 'xxx_form.html', {'form': form})
def view2(request):
xxx_id = request.session['property_id']
if xxx_id == 'SET_BACK_BLANK':
return render(request, 'no_xxx_id.html')
if request.method == 'POST':
form = xxx_form2(request.POST)
if form.is_valid():
cleaned_form_data = form.cleaned_data
xxx_entry = Model.objects.create(
id = xxx_id, #use the id created in step 1
... rest of object creation ...
)
request.session['xxx_id'] = 'SET_BACK_BLANK' #to avoid the misuse during other user interactions.
return HttpResponseRedirect(reverse('thanks'))
else:
form = xxx_form2()
return render(request, 'xxx_form2.html', {'form': form})
Ideally, I would like to pass this ID parameter in the headers of the response as this will avoid having the ID as a session parameter. So I have amended the code to the below:
def view1(request):
if request.method == 'POST':
form = xxx_creation_form(request.POST)
if form.is_valid():
cleaned_form_data = form.cleaned_data
xxx_entry = Model.objects.create(
... object creation ...
)
response = HttpResponseRedirect(reverse('form_2'))
response['xxx_id'] = xxx_entry.id
return response
else:
form = xxx_creation_form()
return render(request, 'xxx_form.html', {'form': form})
def view2(request):
xxx_id = HttpResponseRedirect(request).__getitem__('xxx_id')
if request.method == 'POST':
form = xxx_form2(request.POST)
if form.is_valid():
cleaned_form_data = form.cleaned_data
xxx_entry = Model.objects.create(
id = xxx_id, #use the id created in step 1
... rest of object creation ...
)
return HttpResponseRedirect(reverse('thanks'))
else:
form = xxx_form2()
return render(request, 'xxx_form2.html', {'form': form})
However the above does not work and the error message seems to indicate that there is no 'xxx_id' in the response header.
It would be great if anyone could let me know how to access a response's header in a view as it seems that we cannot amend the request's headers.
Thanks.
What you're asking doesn't really make sense. The response is what is sent from Django to the browser, it is not what the browser sends to Django. That's a completely separate request; in the case of a redirect, your response is simply an instruction to the browser to make that request to a new URL.
The correct thing to do is to use the session, as you are doing. If you are worried about the value being persisted, then pop it out of the session when you use it:
xxx_id = request.session.pop('property_id')

django-form show form data after saving it

I want to show same data to user as posted by him using form after saving it in database.
I am not getting the logic for it.
I am trying to do something like this:
def CreateDeal(request):
if request.method == "POST":
form = DealForm(request.POST)
if form.is_valid():
form.save(commit = True)
data = form.data
return render(request, '/path_to/deal_detail.html',data=data)
Is it ok ?
Is there any better way to do it?
If you do it this way, a redirect of the "detail" page will resubmit the form. This is generally not desired behaviour.
A better way would be to create a detail view for you saved object (if you haven't already) and redirect the user to the detail view of that particular object:
from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse
def CreateDeal(request):
if request.method == "POST":
form = DealForm(request.POST)
if form.is_valid():
obj = form.save(commit=True)
return HttpResponseRedirect(reverse('deal-detail-view', args=(obj.id,)))
# or return HttpResponseRedirect(obj.get_absolute_url())
# if `get_absolute_url` is defined

Categories

Resources