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.
Related
So i have a Car model. And every car is submitted is assigned to a user. Also every user has his own dashboard where they can submit cars (Only for logged in users).
from django.db import models
from django.contrib.auth.models import User
class Car(models.Model):
user = models.ForeignKey(User,on_delete=models.CASCADE,null=True)
model_car= models.CharField(max_length=200)
description = models.TextField()
car_image = models.ImageField(null=True, blank=True)
date_created = models.DateTimeField(auto_now_add=True)
This is my forms.py where i create cars. And then i render this form to the frontend.
from django import forms
from django.forms import ModelForm
from tasks.models import Car
class CreateCarForm(ModelForm):
class Meta:
model=Car
fields='__all__'
exclude = ('user',)
Views.py
def create_car(request):
form = CreateCarForm()
if request.method=="POST":
form = CreateCarForm(request.POST,request.FILES)
if form.is_valid():
form.save()
messages.success(request,'Car was Created')
return redirect('create_car')
context={'form':form}
return render(request, 'dashboard/create_car.html',context)
Now it just creates a car instance, but with no selected user. What i would like to do is to create this Car instance, but in the user field, to auto assign the current logged-in user username.
How can i achieve this?
You can set the .user instance of the Car instance wrapped in the CreateCarForm:
from django.contrib.auth.decorators import login_required
#login_required
def create_car(request):
form = CreateCarForm()
if request.method=='POST':
form = CreateCarForm(request.POST,request.FILES)
if form.is_valid():
form.instance.user = request.user
form.save()
messages.success(request,'Car was Created')
return redirect('create_car')
context={'form':form}
return render(request, 'dashboard/create_car.html', context)
I apologize if my mistake is incredibly simple but I am completely new to Django. Currently, my models.py currently contains 2 types of profiles extending off of the default Django User model:
from django.db import models
from django.contrib.auth.models import User
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete = models.CASCADE)
first_name = models.CharField(max_length = 50)
last_name = models.CharField(max_length = 50)
def __str__(self):
return self.user.username
class PCOProfile(models.Model):
user = models.OneToOneField(User, on_delete = models.CASCADE)
org_name = models.CharField(max_length = 100)
org_phone = models.CharField(max_length = 20)
is_active = models.BooleanField(default = False)
def __str__(self):
return f"{self.user.username} | {self.org_name}"
I have a views.py file which contains 2 functions, one called register and another register-pco that collects base user information, as well as information related to only one of of these models as a form on the same page which will be submitted at the same time as the base user information:
from django.shortcuts import render, redirect
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from .forms import UserRegistrationForm, UserProfileForm, PCOProfileForm
def register(request):
if request.method == 'POST':
user_form = UserRegistrationForm(request.POST)
profile_form = UserProfileForm(request.POST)
if user_form.is_valid() and profile_form.is_valid():
user = user_form.save()
# Hooking up user_profile model to django default user model
profile = profile_form.save(commit=False)
profile.user = user
profile.save()
username = user_form.cleaned_data.get('username')
messages.success(request, f'Your account has been created. You can now login as {username}!')
return redirect('login')
else:
user_form = UserRegistrationForm()
profile_form = UserProfileForm()
context = {'user_form':user_form, 'profile_form':profile_form, 'title':'Register'}
return render(request, 'users/register.html', context)
def register_pco(request):
if request.method == 'POST':
user_form = UserRegistrationForm(request.POST)
pco_profile_form = PCOProfileForm(request.POST)
if user_form.is_valid() and pco_profile_form.is_valid():
user = user_form.save()
# Hooking up pco model to django default user model
pco_profile = PCOProfileForm.save(commit=False)
pco_profile.user = user
pco_profile.save()
username = user_form.cleaned_data.get('username')
messages.success(request, f'Your account has been created. You can now login as {username}!')
return redirect('login')
else:
user_form = UserRegistrationForm()
pco_profile_form = PCOProfileForm()
context = {'user_form':user_form, 'pco_profile_form':pco_profile_form, 'title':'Register'}
return render(request, 'users/register.html', context)
#login_required
def profile(request):
return render(request, 'users/profile.html')
The problem I am currently experiencing is that when I submit the registration form on the register-pco path, it fails to instantiate a PCOprofile object while the base user information gets saved in the database just fine. The end result is a TypeError at /register-pco/ save() missing 1 required positional argument: 'self'. Additionally, the regular register path works just as expected, adding a user in the database with a corresponding profile.
For reference, I was following this guide to try and get user types setup in a simple manner (via 1-1 fields) but it seems as if there might be something wrong with the way I am making the forms since the models themselves work (I tested them in the django shell).
Here is the forms.py file without the imports:
class UserRegistrationForm(UserCreationForm):
email = forms.EmailField()
class Meta:
model = User
fields = ['username','email','password1','password2']
class UserProfileForm(ModelForm):
class Meta:
model = UserProfile
fields = ['first_name','last_name']
class PCOProfileForm(ModelForm):
class Meta:
model = PCOProfile
fields = ['org_name','org_phone']
You're not calling save() on the instance of form you created, but on the form class. So instead of this:
# Hooking up pco model to django default user model
pco_profile = PCOProfileForm.save(commit=False)
you should call it with the form instance you assigned into variable pco_profile_form a few lines above:
# Hooking up pco model to django default user model
pco_profile = pco_profile_form.save(commit=False)
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.
First attempt at trying to create a student user by extending the User model.
Issue: Upon clicking register btn i.e.Login (btn) instead of
redirecting to home it shows the following: NameError at /register/
...name 'user' is not defined
File "E:\ifb299\tutorial2\accounts\views.py", line 33, in register
Students.objects.create(user=user) NameError: name 'user' is not defined [25/Mar/2018 14:38:07] "POST /register/ HTTP/1.1" 500 67801
Not really sure what I'm doing wrong, why is Students.objects.create(user=user) wrong and how do i fix it, please?
views.py
from django.shortcuts import render
from django.shortcuts import redirect
from accounts.forms import RegistrationForm, EditProfileForm
from django.contrib.auth.models import User
from accounts.models import Students
from django.contrib.auth.forms import UserChangeForm
from django.http import HttpResponse
from django.contrib.auth.decorators import login_required
def home(request):
return render(request, 'accounts/home.html')
def login_redirect(request):
return redirect('/login/')
def register(request):
# Once register page loads, either it will send to the server POST data (if the form is submitted), else if it don't send post data create a user form to register
if request.method == "POST":
form = RegistrationForm(request.POST)
if form.is_valid():
form.save()
Students.objects.create(user=user)
return redirect('../home/')
else:
# Create the django default user form and send it as a dictionary in args to the reg_form.html page.
form = RegistrationForm()
args = {'form': form}
return render(request, 'accounts/reg_form.html', args)
#login_required
def view_profile(request):
args = {'user': request.user}
return render(request, 'accounts/profile.html', args)
#login_required
def edit_profile(request):
# Handle post request - if the user submits a form change form details and pass the intance user
if request.method == 'POST':
form = EditProfileForm(request.POST, instance=request.user)
if form.is_valid():
form.save()
return redirect('../profile')
# Handles the get request - if no post info is submitted then get the form and display it on the edit profile page.
else:
form = EditProfileForm(instance=request.user)
args = {'form': form}
return render(request, 'accounts/profile_edit.html', args)
models.py
from django.db import models
from django.contrib.auth.models import AbstractUser
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.db.models.signals import *
from django.conf import settings
class Students(AbstractUser):
bio = models.TextField(max_length=500, blank=True)
location = models.CharField(max_length=30, blank=True)
birth_date = models.DateField(null=True, blank=True)
forms.py
from django import forms
from django.contrib.auth.models import User
from .models import *
from django.contrib.auth.forms import UserCreationForm, UserChangeForm
from betterforms.multiform import MultiModelForm
from django.contrib.auth.forms import UserCreationForm
# Create a custom form that inherites form UserCreationForm (adding our own fields to save i db)
# Inheriting form in the paramters ()
class RegistrationForm(UserCreationForm):
email = forms.EmailField(required=True)
class Meta:
model = Students
fields = (
'username',
'first_name',
'last_name',
'email',
'password1',
'password2',
'bio',
'location',
'birth_date',
)
def save(self, commit=True):
user = super(RegistrationForm, self).save(commit=False)
user.first_name = self.cleaned_data['first_name']
user.last_name = self.cleaned_data['last_name']
user.email = self.cleaned_data['email']
if commit:
user.save()
return user
# Inherits from UserChangeForm class - we keep everything i.e. methods, functionality same but change the things we want to show - connected to the User model
class EditProfileForm(UserChangeForm):
class Meta:
model = User
# Create fields variable get has all the fields we want to show
fields = (
'email',
'first_name',
'last_name',
'password'
)
first, you did not save the return value of form.save() to the variable user.
second, there is no field user your model Student.
I have looked at a lot of different places but none of their solutions work. This is most likely to do them being for older versions of django or my own stupidity. So I am making a blog type of app that for some reason is called reviews instead of blog... anyway I need to automatically fill up an author field with the username of the logged in user. Here is my models.py:
from django.db import models
from django.contrib.auth.models import User
#vars
# Create your models here.
class reviews(models.Model):
title = models.CharField(max_length=100)
author = models.ForeignKey(User, on_delete=models.PROTECT,)
body = models.TextField()
date = models.DateTimeField(auto_now_add=True, blank=True)
and forms.py:
from django import forms
from django.forms import ModelForm
from .models import reviews
from django.contrib.auth.decorators import login_required
class CreatePost_form(ModelForm):
class Meta:
model = reviews
exclude = ['author']
fields = ['title', 'body',]
and views:
from django.shortcuts import render, render_to_response
from .forms import CreatePost_form
from django.http import HttpResponseRedirect
# Create your views here.
def reviewlist(request):
return render
def index(request, ):
return render(request, template_name="index.html")
def CreatePost(request):
form = CreatePost_form(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('/reviews/succesfulpost')
return render(request, "reviews/CreatePostTemplate.html", {'form':form})
def succesfulpost(request):
return render(request, "reviews/succesfulpost.html")
def CreatePost(request):
form = CreatePost_form(request.POST)
if form.is_valid():
form.save(commit=False)
form.author = request.user
form.save()
return HttpResponseRedirect('/reviews/succesfulpost')
As simple as that. Rather than actually saving and committing the data, you simply save without committing then you're able to change the value of the excluded field.