django forms post request raising an error on __init__ method - python

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

Related

Django form not sending data to admin

I have a form users can fill out to reserve a table at a restaurant. However when they submit the form no data gets sent to the admin side.
I have watched some tutorials and read other posts on this site and nothing seems to fix it. I feel like it is something so small but I just cant figure it out.
views.PY
from django.shortcuts import render, get_object_or_404
from django.views import generic, View
from .models import Book
from .forms import BookForm
from django.http import HttpResponseRedirect
def Book(request):
"""
Renders the book page
"""
if request.user.is_authenticated:
form = BookForm(request.POST or None)
context = {
"form": form,
}
else:
return HttpResponseRedirect("accounts/login")
book_form = BookForm(data=request.POST)
if book_form.is_valid():
instance = book_form.save(commit=False)
instance.save()
else:
book_form = BookForm()
return render(
request,
"book.html",
{
"book_form": BookForm(),
}
)
models.py
from django.db import models
from django.contrib.auth.models import User
from django.core.validators import MinValueValidator
from cloudinary.models import CloudinaryField
class Book(models.Model):
name = models.CharField(max_length=50)
number_of_guests = models.PositiveIntegerField(validators=[MinValueValidator(1)])
date = models.DateTimeField()
email = models.EmailField()
requests = models.TextField(max_length=200)
created_on = models.DateTimeField(auto_now_add=True)
updated_on = models.DateTimeField(auto_now=True)
approved = models.BooleanField(default=False)
class Meta:
ordering = ['date']
def __str__(self):
return f"{self.date} for {self.name}"
forms.py
from .models import Book
from django import forms
class BookForm(forms.ModelForm):
class Meta:
model = Book
fields = (
'name',
'number_of_guests',
'date',
'email',
'requests',
)
Try this view:
from django.contrib.auth.decorators import login_required
from django.shortcuts import redirect,render
#login_required(login_url="accounts/login")
def Book(request):
if request.method=="POST":
book_form = BookForm(request.POST)
if book_form.is_valid():
book_form.save()
return redirect("some_success_page")
else:
return redirect("some_error_page")
else:
book_form = BookForm()
return render(
request,
"book.html",
{
"book_form": book_form,
}
)
In settings.py
LOGIN_URL="accounts/login"

Django pass time value and user value to forms.py

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.

Empty django models

Hi I'm getting tottaly empty Comments. And I don't really know why.
Here is my view file.
from django.shortcuts import render, redirect
from .forms import PostForm
from django.views.generic import TemplateView
from .forms import CommentForm
from django.shortcuts import get_object_or_404
from .models import Post
class createPost(TemplateView):
template_name = 'forum/createPost.html'
def get(self, request):
form = PostForm()
return render(request, self.template_name, {'form': form})
def post(self, request):
form = PostForm(request.POST)
if(form.is_valid()):
form.save()
return redirect('/forum')
def add_comment(request, pk):
post = get_object_or_404(Post, pk=pk)
if(request.method == 'POST'):
form = CommentForm(request.POST)
if(form.is_valid()):
comment = form.save(commit=False)
comment.post = post
comment.save()
return redirect('/forum/')
else:
form = CommentForm()
template = 'forum/addComment.html'
context = {'form': form}
return render(request, template, context)
And here is my models file
from django.db import models
class Post(models.Model):
title = models.CharField(max_length=140)
body = models.CharField(max_length=500)
date = models.DateTimeField()
def __str__(self):
return self.title
class Comment(models.Model):
post = models.ForeignKey(Post, related_name='comments', null=True, on_delete=models.SET_NULL)
com_title = models.CharField(max_length=140)
com_body = models.CharField(max_length=500)
def __str__(self):
return self.com_title
And lastly here is forms
from django import forms
from .models import Post, Comment
class PostForm(forms.ModelForm):
title = forms.CharField(max_length=140)
body = forms.CharField()
date = forms.DateTimeField()
class Meta:
model = Post
fields = ('title', 'body', 'date')
class CommentForm(forms.ModelForm):
title = forms.CharField(max_length=140)
body = forms.CharField(max_length=500)
class Meta:
model = Comment
fields = ('title', 'body')
I don't really know why I'm getting this error. I get a comment but It is totaly blank. Mabye It has something to do with the comment = form.save(commit=False), but i don't know.
I am really new to Django so please let me know if you know how to solve it. Also if there is somthing more I have to add to this question like urls and stuff please let me know.
Thanks ;)
Try changing your view to
class createPost(CreateView):
template_name = 'forum/createPost.html'
model=Post
form_class=PostForm
def form_valid(self, form):
form.save()
return http.HttpResponseRedirect('/forum')
and then form to
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = ('title', 'body', 'date')
PS: If you don't want to make any changes to your form fields, then form_class is not required. You may provide the fields to the View itself.

Django - Why am I getting this IntegrityError: NOT Null constraint failed: restaurants_restaurantlocation.owner_id?

I am trying to make a website where people can find restaurants and menu items based on their pickiness. Currently I am trying to do it so when I add something to the restaurants through forms I have it associated to an user but when I submit the form I get this error:
IntegrityError
NOT Null constraint failed: restaurants_restaurantlocation.owner_id
Here is my forms.py:
from django import forms
from .models import RestaurantLocation
from .validators import validate_category
class RestaurantCreateForm(forms.Form):
name = forms.CharField()
location = forms.CharField(required = False)
category = forms.CharField(required = False)
def clean_name(self):
name = self.cleaned_data.get("name")
if name == "Hello":
raise forms.ValidationError("This is an invalid name. You stubid boy.")
return name
class RestaurantLocationCreateForm(forms.ModelForm):
#email = forms.EmailField()
#category = forms.CharField(validators = [validate_category], required = False)
class Meta:
model = RestaurantLocation
fields = [
"name",
"location",
"category"
]
def clean_name(self):
name = self.cleaned_data.get("name")
if name == "Hello":
raise forms.ValidationError("This is an invalid name. You stubid boy.")
return name
My models.py:
from django.conf import settings
from django.db import models
from django.db.models.signals import pre_save, post_save
from .utils import unique_slug_generator
from .validators import validate_category
# Create your models here.
User = settings.AUTH_USER_MODEL
class RestaurantLocation(models.Model):
owner = models.ForeignKey(User)
name = models.CharField(max_length=120)
location = models.CharField(max_length=120, null=True, blank=True)
category = models.CharField(max_length=120, null=True, blank=True, validators= [validate_category])
slug = models.SlugField(null=True, blank=True)
timestamp = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
def __str__(self):
return self.name
#property
def title(self):
return self.name #obj.title
def rl_pre_save_reciever(sender, instance, *args, **kwargs):
instance.category = instance.category.capitalize()
if not instance.slug:
instance.slug = unique_slug_generator(instance)
pre_save.connect(rl_pre_save_reciever, sender=RestaurantLocation)
My views.py:
from django.db.models import Q
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render, get_object_or_404
from django.views import View
from django.views.generic import TemplateView, ListView, DetailView, CreateView
from django.utils.datastructures import MultiValueDictKeyError
from .forms import RestaurantCreateForm, RestaurantLocationCreateForm
from .models import RestaurantLocation
# Create your views here
def restaurant_createview(request):
form = RestaurantLocationCreateForm(request.POST or None)
errors = None
if form.is_valid():
# customise
# like a pre save
form.save()
# like a post save
return HttpResponseRedirect("/restaurants/")
if form.errors:
errors = form.errors
template_name = "restaurants/form.html"
context = {"form" : form, "errors" : errors}
return render(request, template_name, context)
def restaurant_listview(request):
template_name = "restaurants/restaurants_list.html"
queryset = RestaurantLocation.objects.all()
context = {
"object_list": queryset
}
return render(request, template_name, context)
class RestaurantListView(ListView):
def get_queryset(self):
slug = self.kwargs.get("slug")
if slug:
queryset = RestaurantLocation.objects.filter(
Q(category__iexact = slug) |
Q(category__icontains = slug)
)
else:
queryset = RestaurantLocation.objects.all()
return queryset
class RestaurantDetailView(DetailView):
queryset = RestaurantLocation.objects.all()
class RestaurantCreateView(CreateView):
form_class = RestaurantLocationCreateForm
template_name = "restaurants/form.html"
success_url = "/restaurants/"
If you need any other piece of code please ask, thank you
Looking at your RestaurantLocation model, you have a foreign key into the User table:
class RestaurantLocation(models.Model):
owner = models.ForeignKey(User)
By default this can't be empty (this is what "NOT null constraint" means). And indeed it looks like your form does not do anything to fill in a restaurant owner, so you will get a database constraint error when you try to commit.
"This is an invalid name. You stubid boy."
Not a very nice thing to say to your users.

How can I set a default value to the model in Django?

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 }}

Categories