Django model form not submitting correctly - python

I've created a model form which is then rendered in a context processor as the form is included on every page. Once the form is submitted it should re-direct to a 'thank you' page. However it just seems to re-load the page and remove the form. I had it all working when rendering on a page via a URL. Since moving the function to my context processor it doesn't redirect correctly.
It also saves the information that's provided into the model, in the admin. So I'm guessing it is something to do with redirect.
Here is my context processor:
from django.conf import settings
from contact_enquiries import forms
from django.shortcuts import render
from django.http import HttpResponseRedirect
def contact(request):
if request.method == 'POST':
form = forms.ContactUsForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('/thanks/')
else:
form = forms.ContactUsForm()
return {
'contact_form' : form,
}
forms.py
class ContactUsForm(ModelForm):
class Meta:
model = ContactUs
fields = ['name', 'contact_number', 'email', 'enquiry']
models.py
class ContactUs(models.Model):
name = models.CharField(max_length=200)
contact_number = models.IntegerField(max_length=50)
email = models.EmailField(max_length=300)
enquiry = models.TextField()
class Meta:
verbose_name_plural = "Contact Us"
def __unicode__(self):
return self.name

A context processor should always return a dictionary, it shouldn't return an http response.
One option is to make your contact form post to a different view. You do this by changing the action attribute of the form in your template.
<form action="{% url 'contact' %}" method="post">
Your contact view and url patterns would look something like this:
url('^/contact/$', contact, name="contact"),
def contact(request):
if request.method == 'POST':
form = forms.ContactUsForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('/thanks/')
else:
form = forms.ContactUsForm()
return render(request, "contact.html", {
'contact_form' : form,
})
Your context processor then simplifies to:
def contact(request):
form = forms.ContactUsForm()
return {'contact_form' : form}

Related

Python crash course 19-5 object has no attribute 'owner'

learning python through the python crash course book. Having this issue where somehow it says that there is no attribute 'owner' for each blogpost when there seems to be one? Would appreciate any guidance, cheers all!
Added to the very bottom of settings.py
#MY SETTINGS
LOGIN_URL = 'users:login'
models.py
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class BlogPost(models.Model):
title = models.CharField(max_length=50)
text = models.CharField(max_length=200)
date_added = models.DateTimeField(auto_now_add=True)
owner = models.ForeignKey(User, on_delete=models.CASCADE)
def __str__(self):
return self.title
This is the code when i run django shell to see the owner associated with each blogpost
from blogs.models import BlogPost
for a in BlogPost.objects.all():
print(a, a.owner)
My first post! aaaaaa ll_admin
Second blog post ll_admin
No season 2 in product ll_admin
ll_admin
is this the tutle ll_admin
ssd ll_admin
ssaaa ll_admin
views.py
from django.shortcuts import render, redirect
from django.contrib.auth.decorators import login_required
from .models import BlogPost
from .forms import BlogPostForm
# Create your views here.
def index(request):
"""The home page for blogs"""
return render(request, 'blogs/index.html')
#login_required
def posts(request):
"""Show all blogposts"""
posts = BlogPost.objects.filter(owner=request.owner).order_by('date_added')
context = {'posts': posts}
return render(request, 'blogs/posts.html', context)
#login_required
def new_post(request):
"""Add a new blogpost"""
if request.method != 'POST':
#No data submitted; create a blank form.
form = BlogPostForm()
else:
#POST data submitted, process data
form = BlogPostForm(data=request.POST)
if form.is_valid():
form.save()
return redirect('blogs:posts')
#Display a blank or invalid form
context = {'form': form}
return render(request, 'blogs/new_post.html', context)
#login_required
def edit_post(request, post_id):
"""Edit existing post"""
post = BlogPost.objects.get(id=post_id)
if request.method != "POST":
#Initial request, pre-fill form with the current post
form = BlogPostForm(instance=post)
else:
#Post data submitted, process data
form = BlogPostForm(instance=post, data=request.POST)
if form.is_valid():
form.save()
return redirect('blogs:posts')
#return redirect('blogs:posts', post_id=post.id)
context = {'post':post, 'form':form}
return render(request, 'blogs/edit_post.html', context)
This is all that I have edited to add in the login functions, cant seem to spot the error. Thank you for helping!
In your posts view:
#login_required
def posts(request):
"""Show all blogposts"""
posts = BlogPost.objects.filter(owner=request.owner).order_by('date_added') # here
context = {'posts': posts}
return render(request, 'blogs/posts.html', context)
The request object is storing 2 values:
The instance of the currently logged in user under the name user (changes to AnonymousUserObject instance when logged out)
auth depending on the type of authentication used
You are calling request.owner and obviously getting an error because a request object has no owner attribute, change the marked line line this:
posts = BlogPost.objects.filter(owner=request.user).order_by('date_added')
And it should work.

Upload Multiple files in Django 3

I am new to pyhthon\Django and would like to get my Django 3 app to have the ability to upload multiple files but I am struggling to get this functionality, below is my sample code which uploads a single file, I beleive I need to enable multiple files in the forms.py and then override the post method to deal with multiple files.
As I bonus I would also like to use a field name from the form in the file path when it is saved.
(Pyhton 3.8/Django 3)
thanks
Model.py
class Predocs(models.Model):
doc_files = models.FileField(blank=True)
Form.py
from .models import Predocs
class PostForm(forms.ModelForm):
class Meta:
model = Predocs
fields = ['doc_files']
View.py
from django.shortcuts import render, redirect
# Create your views here.
from .forms import PostForm
from PredocsForm.models import Predocs
def create(request):
if request.method == 'POST':
form = PostForm(request.POST, request.FILES)
if form.is_valid():
# save form
form.save()
data = "test data"
return render(request, 'preform/created.html', {
'data': data
})
else:
form = PostForm()
return render(request,
'preform/create.html',
{
'form': form
})
def created(request):
return render(request, 'preform/created.html')

Django add data to manyToManyField on form submission

I would like to automatically add the User who submitted the form to the users many to many field on the below-given model when the form submits, how could I do this from the view?
The model:
class Project(MainAbstractModel):
users = models.ManyToManyField(User)
title = models.CharField(max_length=25, default="Conflict")
The view:
def myconflicts(request):
if request.method == "POST":
form = ProjectForm(request.POST)
if form.is_valid():
form.save()
else:
form = ProjectForm()
return render(request, 'conflictmanagement/myconflicts.html')
And my form is simply:
class ProjectForm(ModelForm):
class Meta:
model = Project
fields = ["title"]
You can add the user in the view, for example with:
from django.contrib.auth.decorators import login_required
from django.shortcuts import redirect
#login_required
def myconflicts(request):
if request.method == 'POST':
form = ProjectForm(request.POST)
if form.is_valid():
project = form.save()
project.users.add(request.user)
return redirect('name-of-some-view')
else:
form = ProjectForm()
return render(request, 'conflictmanagement/myconflicts.html', {'form': form})
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].

Django ModelForm ignores the data supplied via form and saves the superuser name in the table

I'm new at using Django forms (Django altogether), and on my first form, I have encountered this error. No matter what data I post via the form it saves the superuser name in all the fields.
Here are the files,
forms.py
from django.forms import ModelForm
from .models import *
class NewCustomer(ModelForm):
class Meta:
model = Customer
fields = ('name', 'mobile_number', 'email', 'address')
Views.py
from django.shortcuts import render, get_object_or_404, redirect
from .models import *
from .forms import *
# Create your views here.
def customers(request):
customers = Customer.objects.all().order_by('id')
return render(request, "customers.html", {'customers': customers, 'custactive': "active"})
def customer_details(request, pk):
customer = get_object_or_404(Customer, pk=pk)
return render(request, "customer_details.html", {'customer': customer})
def new_customer(request):
if request.method == 'POST':
form = NewCustomer(request.POST)
if form.is_valid():
customer = form.save(commit=False)
customer.name = request.user
customer.mobile_number = request.user
customer.email = request.user
customer.address = request.user
customer.save()
return redirect ('customers')
else:
form = NewCustomer()
return render(request, "new_customer.html", {'form': form})
Can someone tell me what's wrong with the code? Understandably I need to save new data that I supply with the form.
Really appreciate your help...
The problem is that you need to tell the form which fields to get from User object.
Now if you have extended the User model and have name, mobile_number, address specified, you need to modify your code.
def new_customer(request):
if request.method == 'POST':
form = NewCustomer(request.POST)
if form.is_valid():
customer = form.save(commit=False)
customer.name = request.user.name
customer.mobile_number = request.user.mobile_number
customer.email = request.user.email
customer.address = request.user.address
customer.save()
return redirect ('customers')
The reason whz superuser's name is saved in all fields is because all models have their str method, which tells python what to print out if object itself is used.

Form inside page in Django

I want to make a DetailView page, like:
class TaskDetailView(DetailView):
model = Task
template_name = 'todo/task_detail.html'
and place form inside this page, so user can add this task.
Its easy, if create new page for this form:
forms.py
class TaskForm(ModelForm):
class Meta:
model = task
fields = __all__
views.py
def TaskForm_view(request, pk):
if request.method == 'POST':
form = TaskForm(request.POST)
if form.is_valid(): # All validation rules pass
task.save()
return HttpResponseRedirect('/admin/') # Redirect after POST
else:
form = TaskForm() # An unbound form
return render(request, 'todo/add_task.html', {
'form': form,
})
urls.py:
url(r'^(?P<pk>\d+)/add/', 'todo.views.TaskForm_view', name='add')
but how to create a DetailView page with form inside? I cant find an exemple, help plz!
You can add the form in a context variable, so you can access to it from the template as: form
class TaskDetailView(DetailView):
model = Task
template_name = 'todo/task_detail.html'
def get_context_data(self, **kwargs):
context = super(TaskDetailView, self).get_context_data(**kwargs)
context['form'] = TaskForm()
return context
Consider using CreateView, UpdateView, DeleteView.
DetailView are designed to display data.
Here is described Form handling with class-based views in django

Categories