I have a model like this:
from django.db import models
from django.contrib.auth.models import User
class Task(models.Model):
title = models.CharField(max_length=200)
pub_date = models.DateTimeField(default)
completed = models.BooleanField(default=False)
description = models.TextField()
user = models.ForeignKey(User, on_delete=models.CASCADE)
def summary(self):
return self.description[:50]
def pub_date_pretty(self):
return self.pub_date.strftime('%b %e %Y')
def __str__(self):
return self.title
I have a forms.py like this because I don't want the user to be able to determine which user is saving the data and I want the pub_date to be the time now:
from django import forms
from .models import Task
from django.utils import timezone
class Taskform(forms.ModelForm):
class Meta:
model = Task
fields = ['title', 'description', 'completed']
My view is like this:
#login_required
def create(request):
form = Taskform(request.POST or None)
task = Task()
task.pub_date = timezone.datetime.now()
task.user = request.user
if form.is_valid():
form.save()
return redirect('')
return render(request, 'home/create.html', {'form': form})
I want to pass the time and the user to the form as it validates but I'm not sure how?
You can use form.save() with commit=True argument to take task instance and update it:
if form.is_valid():
task = form.save(commit=False)
task.pub_date = timezone.datetime.now()
task.user = request.user
task.save()
return redirect('')
Check detail here.
Related
I'm new to Django and i'm trying to build a Todo app with user authentication but i want to add sessions to it whereby everyone can have different tasks attached to their accounts but i don't know how to go about it. I've checked the Django documentation on it but i still don't get it.
Here's my models.py
from django.db import models
from django.contrib.auth.models import AbstractUser
# Create your models here.
class Task(models.Model):
name = models.CharField(max_length=15)
completed = models.BooleanField(default=False)
def __str__(self):
return self.name
class User(AbstractUser):
name = models.CharField(max_length=200, null=True)
email = models.EmailField(unique=True, null=True)
bio = models.TextField(null=True, blank=True)
USERNAME_FIELDS = "email"
REQUIRED_FIELDS = []
Then here's my view.py
from django.shortcuts import render, redirect
from .models import Task, User
from .forms import AddTaskForm
#login_required(login_url="loginPage")
def home(request):
tasks = Task.objects.all()
context = {"tasks": tasks, }
return render(request, "task/home.html", context)
# Add task view
# login_required(login_url="loginPage")
def addTask(request):
addTaskForm = AddTaskForm()
if request.method == "POST":
addTaskForm = AddTaskForm(request.POST)
if addTaskForm.is_valid():
addTaskForm.save()
return redirect('home')
context = {"addTaskForm": addTaskForm}
return render(request, "task/addtask.html", context)
# Update task view
#login_required(login_url="loginPage")
def update(request, pk):
updateTask = Task.objects.get(id=pk)
updateTaskForm = AddTaskForm(instance=updateTask)
if request.method == "POST":
updateTaskForm = AddTaskForm(request.POST, instance=updateTask)
if updateTaskForm.is_valid():
updateTaskForm.save()
return redirect('home')
context = {"updateTaskForm": updateTaskForm}
return render(request, "task/update-task.html", context)
# Delete task view
# login_required(login_url="loginPage")
def delete(request, pk):
deleteTask = Task.objects.get(id=pk)
if request.method == 'POST':
deleteTask.delete()
return redirect("home")
context = {"deleteTask": deleteTask}
return render(request, "task/delete-task.html", context)
Don't need to go with sessions. You need to improve model using Django ORM.
Like:
#models.py
class User(AbstractUser):
name = models.CharField(max_length=200, null=True)
email = models.EmailField(unique=True, null=True)
bio = models.TextField(null=True, blank=True)
USERNAME_FIELDS = "email"
REQUIRED_FIELDS = []
class Task(models.Model):
user = models.ForeignKey(User,on_delete=models.CASADE)
name = models.CharField(max_length=15)
completed = models.BooleanField(default=False)
def __str__(self):
return self.name
While saving tasks in Task model, provide the id of the user in the user field.
check this simple use of sessions in django :
from django.http import HttpResponseRedirect
from django.shortcuts import render
from django import forms
from django.urls import reverse
class NewTaskForm(forms.Form) :
task = forms.CharField(label="Add Task ")
# Create your views here.
Tasks = []
def index(request) :
if "Tasks" not in request.session :
request.session["Tasks"] = []
return render(request , "tasks/index.html",{
"tasks" : request.session["Tasks"]
})
def add(request) :
if request.method == "POST" :
form = NewTaskForm(request.POST)
if form.is_valid() :
task = form.cleaned_data["task"]
request.session["Tasks"] += [task]
return HttpResponseRedirect(reverse("index"))
else :
return render(request , "tasks/add.html" , {
"form" : form
})
return render(request , "tasks/add.html" ,{
"form" : NewTaskForm()
})
with this method each user views their own task lists, i have a project same as what you looking for, here
I have a model where a user posts a job vacancy, then other users can submit applications. The submit application model is called 'CandidatesSubmission' & pulls the 'title' from a different app/model 'JobPosts'.
I can add submit applications through the ADMIN page fine, but when trying to do so with a form I get "IntegrityError NOT NULL constraint failed: candidates_candidatessubmission.title_id."
I believe that I'm missing something in my Views.py that essentially says "use the title of job vacancy as the title field.
I have tried adding null=True, blank=False but which stops the error but the title isn't saved to the database.
Any suggestions on what I'm doing wrong would be great. Thank you
models.py
class CandidatesSubmission(models.Model):
title = models.ForeignKey('jobs.JobsPost', on_delete=models.CASCADE)
Fee = models.CharField(max_length=50, null=False, blank=False)
CandidateFirstName = models.CharField(max_length=50, null=True, blank=False)
CandidateSecondName = models.CharField(max_length=50, null=True, blank=False)
created = models.DateTimeField(auto_now_add=True)
author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
views.py
from django.shortcuts import render, redirect, get_object_or_404
from django.db.models import Q
from django.http import HttpResponseNotFound
from jobs.models import JobsPost
from candidates.models import CandidatesSubmission
from candidates.forms import CreateCandidatePostForm
from account.models import Account
from operator import attrgetter
# Create your views here.
def submit_candidates_view(request, slug):
context = {}
user = request.user
if not user.is_authenticated:
return redirect('must_authenticate')
form = CreateCandidatePostForm(request.POST or None, request.FILES or None)
if form.is_valid():
obj = form.save(commit=False)
author = Account.objects.filter(email=user.email).first()
obj.author = author
obj.save()
form = CreateCandidatePostForm()
context['form'] = form
accounts = CandidatesSubmission.objects.all()
context['accounts'] = accounts
return render(request, 'candidates/submit_candidates.html', context)
def response_view(request):
context = {}
accounts = CandidatesSubmission.objects.all()
context['accounts'] = accounts
return render(request, "candidates/response.html", context)
forms.py
from django import forms
from candidates.models import CandidatesSubmission
class CreateCandidatePostForm(forms.ModelForm):
class Meta:
model = CandidatesSubmission
fields = ['Fee', 'CandidateFirstName', 'CandidateSecondName']
def save(self, commit=True):
submission_post = self.instance
submission_post.Fee = self.cleaned_data['Fee']
submission_post.CandidateFirstName = self.cleaned_data['CandidateFirstName']
submission_post.CandidateSecondName = self.cleaned_data['CandidateSecondName']
if commit:
submission_post.save()
return submission_post
if you have "current" title, so your slug might store it, so you can use it like that.
def submit_candidates_view(request, slug):
context = {}
user = request.user
if not user.is_authenticated:
return redirect('must_authenticate')
form = CreateCandidatePostForm(post_slug=slug, request.POST or None, request.FILES or None)
if form.is_valid():
obj = form.save(commit=False)
author = Account.objects.filter(email=user.email).first()
obj.author = author
obj.save()
form = CreateCandidatePostForm()
context['form'] = form
accounts = CandidatesSubmission.objects.all()
context['accounts'] = accounts
return render(request, 'candidates/submit_candidates.html', context)
in your forms.py we replace __init__ method to receive slug of your title
class CreateCandidatePostForm(forms.ModelForm):
class Meta:
model = CandidatesSubmission
fields = ['Fee', 'CandidateFirstName', 'CandidateSecondName']
def __init__(self, *args, **kwargs):
self.post_slug = kwargs.pop("post_slug", None)
super().__init__(*args, **kwargs)
def save(self, commit=True):
submission_post = self.instance
submission_post.title = JobsPost.objects.get(slug=self.post_slug)
if commit:
submission_post.save()
return submission_post
I have a django form which takes a paramater from the view to initialize the MultipleChoiceField based on the user instance.
The form is working fine when loading the template.
when i submit the form the init method in the form raising an error.
My Model models.py
from django.db import models
from django.contrib.auth.models import User
class Group(models.Model):
group_name = models.CharField('Group name', max_length=50)
def __str__(self):
return self.group_name
class GroupMembers(models.Model):
group_name = models.ManyToManyField(Group)
members = models.ForeignKey(User, on_delete=models.CASCADE)
class Transactions(models.Model):
bill_type = models.CharField('Bill type',max_length=200)
added_by = models.ForeignKey(GroupMembers, on_delete=models.CASCADE)
added_to = models.ForeignKey(Group, on_delete=models.CASCADE)
purchase_date = models.DateField(auto_now=True)
share_with = models.CharField('Share among',max_length=250)
amount = models.IntegerField(default=0)
def __str__(self):
return self.bill_type
forms forms.py
from django import forms
from .models import Transactions, GroupMembers
class Bill_CreateForm(forms.ModelForm):
def __init__(self, user_list, *args, **kwargs):
super(Bill_CreateForm, self).__init__(*args, **kwargs)
self.fields['share_with'] = forms.MultipleChoiceField(widget=forms.CheckboxSelectMultiple,choices=tuple([(name, name.members) for name in user_list]))
class Meta:
model = Transactions
fields = (
'bill_type',
'amount',
'added_by',
'added_to',
'share_with',
)
** RESOLVED MY ISSUE WITH THE HELP OF #Alasdair "
EDITED SOLUTION
views views.py
from django.shortcuts import render, redirect
from django.contrib.auth.models import User
from .models import Transactions, Group, GroupMembers
from .forms import Bill_CreateForm
from django.http import HttpResponse, HttpResponseRedirect
def add_bills_home(request, id=None):
user = User.objects.get(pk=id)
grpname = Group.objects.filter(groupmembers__members=user)
gm = GroupMembers.objects.filter(group_name__group_name=grpname[0])
users_list = [i for i in gm]
if request.method == 'POST':
form = Bill_CreateForm(users_list, request.POST)
if form.is_valid():
print(form.cleaned_data['share_with'])
form.save()
form = Bill_CreateForm(users_list)
return render(request, 'bills/create_bill.html', {'form':form})
else:
form = Bill_CreateForm(users_list)
return render(request, 'bills/create_bill.html', {'form':form})
The error is
After submiting the form with data
the request.POST method returning
below data
i don't know if the request.POST method re-initializes the form with the filled data and pass it to the init method in the form.py.
Please help me with this
Hi I am having trouble figuring out how to solve this error. I was creating a form to be able to add new topics to a website I am working on. After creating the form and trying to use it to submit a request to add a new topic I got a integrityError which I haven't encountered before. After doing some research I know it has something to do with a foreign key relationship where there is a field that is empty inside the database but I am not sure how to root cause it.
here is my Models.py file:
from django.db import models
# Create your models here.
class Category(models.Model):
"""A category the user is writing about"""
text = models.CharField(max_length=200)
class Meta:
verbose_name_plural = 'Categories'
def __str__(self):
"""Return a string represtation of the model."""
return self.text
class Topic(models.Model):
"""A topic that is associated with a certain Category"""
category = models.ForeignKey(Category, on_delete=models.CASCADE)
text = models.CharField(max_length=200)
date_added = models.DateTimeField(auto_now_add=True)
class Meta:
verbose_name_plural = 'Topics'
def __str__(self):
"""Return string represtation of the model."""
return self.text
class Entry(models.Model):
"""A entry associated with a certain topic"""
topic = models.ForeignKey(Topic, on_delete=models.CASCADE)
text = models.TextField()
date_added = models.DateTimeField(auto_now_add=True)
class Meta:
verbose_name_plural = 'Entries'
def __str__(self):
"""Return string represtation of the model."""
return self.text[:50] + "..."
forms.py
from django import forms
from .models import Category, Topic
class CategoryForm(forms.ModelForm):
class Meta:
model = Category
fields = ['text']
labels = {'text': ''}
class TopicForm(forms.ModelForm):
class Meta:
model = Topic
fields = ['text']
labels = {'text': ''}
views.py
from django.shortcuts import render
from django.http import HttpResponseRedirect
from django.urls import reverse
from .models import Category, Entry, Topic
from .forms import CategoryForm, TopicForm
# Create your views here.
def index(request):
"""The home page for Learning Logs"""
return render(request, 'blogging_logs/index.html')
def categories(request):
"""show all categories"""
categories = Category.objects.all()
context = {'categories': categories}
return render(request, 'blogging_logs/categories.html', context)
def topics(request, category_id):
"""Show all topics for a single category"""
category = Category.objects.get(id=category_id) # get category that was requested
topics = category.topic_set.all() # get all topics associated with category that was requested
context = {'category': category, 'topics': topics}
return render(request, 'blogging_logs/category.html', context)
def topic(request, entry_id):
"""Show entry for single topic"""
topic = Topic.objects.get(id=entry_id)
entries = topic.entry_set.all()
context = {'topic': topic, 'entries': entries}
return render(request, 'blogging_logs/topic.html', context)
def new_category(request):
"""Add a new category"""
if request.method != 'POST':
# No data submitted; create a blank formself.
form = CategoryForm()
else:
# POST data submitted; process data
form = CategoryForm(data=request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect(reverse('blogging_logs:categories'))
context = {'form': form}
return render(request, 'blogging_logs/new_category.html', context)
def new_topic(request):
""" Add new topic to category """
if request.method != 'POST':
# No data submitted; create a blank formself.
form = TopicForm()
else:
form = TopicForm(data=request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect(reverse('blogging_logs:topics'))
context = {'form': form}
return render(request, 'blogging_logs/new_topic.html', context)
Any help to point me in the right direction is appreciated thank you!
Select Category
Add new topic to category
class Topic(models.Model):
category = models.ForeignKey(Category, on_delete=models.CASCADE, blank=True, null=True)
#your other fields
Run python manage.py makemigrations and python manage.py migrate command, the error will be removed.
I want to create a Invitation app which has a sender, receiver and message.
How can I set the current logged in user as a sender which is immutable?
In the model.py
class Invitation(models.Model):
from_user = models.CharField(max_length=100)
to_user = models.ForeignKey(User, related_name="invitations_received")
message = models.CharField(max_length=300)
timestap = models.DateTimeField(auto_now_add=True)
def __str__(self):
return "{} to {}: {}".format(self.from_user, self.to_user, self.message)
In the views.py
from django.shortcuts import render, redirect
from django.contrib.auth.decorators import login_required
from .models import Game
from .models import Invitation
from .forms import InvitationForm
#login_required
def new_invitation(request):
if request.method == 'POST':
form = InvitationForm(data=request.POST, from_user=request.user)
if form.is_valid():
form.save()
return redirect('profiles_home')
else:
form = InvitationForm()
return render(request, "arosis/new_invitation.html", {'form': form})
In the forms.py
from django.forms import ModelForm
from .models import Invitation
from django.shortcuts import render
class InvitationForm(ModelForm):
class Meta:
model = Invitation
You cannot simply default to the current user because Django ORM is not normally aware of Django authentication system. You should either:
1) Pass the request.user while creating the model instance, like:
invitation = Invitation(from_user=request.user)
or
2) Use a middleware that adds the current user to the model each time it is saved. You can try one of these packages: https://www.djangopackages.com/grids/g/model-audit/
I solved it easily for myself as below:
In the models.py:
class Invitation(models.Model):
from_user = models.ForeignKey(User, related_name="invitations_sent")
to_user = models.ForeignKey(User, related_name="invitations_received",
verbose_name="User to invite",
help_text="Please Select the user you want.")
message = models.CharField("Optional Message", max_length=300, blank=True,
help_text="Adding Friendly Message")
timestap = models.DateTimeField(auto_now_add=True)
def __str__(self):
return "{} to {}: {}".format(self.from_user, self.to_user, self.message)
In the views.py:
def new_invitation(request):
if request.method == 'POST':
invitation = Invitation(from_user=request.user)
form = InvitationForm(data=request.POST, instance=invitation)
if form.is_valid():
form.save()
return redirect('arosis_invite')
else:
form = InvitationForm(data=request.POST)
return render(request, "arosis/new_invitation.html", {'form': form})
In the forms.py:
class InvitationForm(ModelForm):
class Meta:
model = Invitation
exclude = ['from_user']
And in the template file:
I solved it really easy! by using:
{{ user.username }}