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.
Related
I am trying to make a simple to-do list in Django that each user could have their own task list so when they logged in they add a task and its save for themselves and the list only display their own tasks, but when I try to add a task from the template's form it won't save but when I add task manually from admin panel it work.
my models.py
from django.db import models
from django.contrib.auth.models import User
class Tasks(models.Model):
user = models.ForeignKey(User, null=True,on_delete=models.CASCADE)
title = models.CharField(max_length=200)
check = models.BooleanField(default = False)
date = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.title
forms.py
from django import forms
from django.forms import ModelForm
from .models import *
class TaskForm(forms.ModelForm):
class Meta:
model = Tasks
fields = '__all__'
views.py:
from django.shortcuts import render, redirect
from django.contrib.auth.decorators import login_required
from .forms import *
from .models import Tasks
#login_required(login_url = 'login')
def tasks(request):
tasks = Tasks.objects.filter(user = request.user)
context = { 'tasks': tasks }
return render(request,'ToDo/list.html',context)
#login_required(login_url = 'login')
def add_task(request):
form = TaskForm()
if request.method == 'POST':
form = TaskForm(request.POST)
if form.is_valid():
form.save(commit=False)
form.user = request.user
form.save()
return redirect('/')
context = {'form' : form}
return render(request,'ToDo/add.html',context)
where is the problem?
You assign the user to the .user attribute of the form, not of the .instance wrapped in the form. You thus should alter the instance with:
#login_required(login_url = 'login')
def add_task(request):
if request.method == 'POST':
form = TaskForm(request.POST, request.FILES)
if form.is_valid():
form.instance.user = request.user
form.save()
return redirect('/')
else:
form = TaskForm()
return render(request, 'ToDo/add.html', {'form' : form})
You should furthermore only redirect in case of a successful POST request: in case the POST request is not successful, the form can render the error messages, and thus will inform the user what the problem is.
Furthermore you make the user field non-editable:
from django.conf import settings
class Tasks(models.Model):
user = models.ForeignKey(
settings.AUTH_USER_MODEL,
editable=False,
on_delete=models.CASCADE
)
title = models.CharField(max_length=200)
check = models.BooleanField(default = False)
date = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.title
Note: It is normally better to make use of the settings.AUTH_USER_MODEL [Django-doc] to refer to the user model, than to use the User model [Django-doc] directly. For more information you can see the referencing the User model section of the documentation.
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].
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.
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}
I have designed a form in django wherein there are 3 fields "Title","Body" & "Tagline". So my query is that when i press submit button after filling up the data that data should be directly inserted into my "notes" database.
Models.py
from django.db import models
class pim(models.Model):
Title = models.CharField(max_length=40)
Body = models.CharField(max_length=40)
TagLine = models.CharField(max_length=40)
Views.py
from django.shortcuts import render_to_response
from django.http import HttpResponse, Http404
def Notes_create(request):
return render_to_response('notesform.html',locals())
You'll need to create a modelform for your pim model:
class pimForm(ModelForm):
class Meta:
model = pim
And your view will have to display the form and handle it when the request type is a POST:
def new(request):
if request.method == 'POST':
form = pimForm(request.POST)
if form.is_valid():
form.save()
return redirect(reverse('your.pim.detail.view', args=[pim.pk]))
else:
form = pimForm()
return render_to_response('notesform.html', {'form': form}, context_instance=RequestContext(request))
Something like that should work