I am rendering a form and when I am submitting that form getting this error
IntegrityError at /business/
NOT NULL constraint failed: app_business.user_id
models.py
class business(models.Model):
user = models.ForeignKey(User)
name = models.CharField(max_length=400)
rate_it = models.BooleanField(default=False)
availibility = models.BooleanField(default=True)
def __str__(self):
return self.name
forms.py
class businessform(forms.ModelForm):
class Meta:
model = business
fields = ['name', 'rate_it', 'availibility']
views.py
def formview(request):
if request.method == 'POST':
form = businessform(request.POST)
if form.is_valid():
form.save()
return HttpResponse('saved')
else:
form = businessform
return render(request, 'business.html', {'form':form})
html file
<form method="POST" action="">
{% csrf_token %}
{{form.as_p}}
<input type="submit" name="submit">
</form>
I don't know why this error is coming.
When you are saving the form you haven't passed any user object. Either pass user object while saving the form or make the user field null=True, blank=True in your model.
user = models.ForeignKey(User, null=True, blank=True)
EDIT
Create an user object and save it first. Then pass that instance in the form to update values you got from template. Then save the form.
user = User.objects.create_user(username=username, password=password)
user.save()
obj = business.objects.create(user=user, name="")
form = form = businessform(request.POST, instance=obj)
if form.is_valid():
form.save()
return HttpResponse('saved')
Be careful about the usernames. Usernames must be unique. So, you need to generate those.
Related
In my django app I have a User model that has a Boolean field of is_manager.
User model in models.py:
class User(AbstractUser):
name = models.CharField(max_length=15, null=True, blank=True)
last_name = models.CharField(max_length=15, null=True, blank=True)
title = models.CharField(max_length=50, null=True, blank=True)
email = models.EmailField(unique=True)
bio = models.TextField(null=True, blank=True)
company = models.ForeignKey(Company, on_delete=models.DO_NOTHING, null=True)
is_manager = models.BooleanField(default=False)
can_assign = models.BooleanField(default=False)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['username']
I've been trying to create an edit page in order for managers and users to be able to change some of their fields.
Regular users should be able to change their bio and title, and the managers can change the can_assign Boolean.
I have a form that deals with the logic of that in forms.py:
class EditUserForm(ModelForm):
def __init__(self, *args, **kwargs):
self.user = kwargs.pop('user')
if self.user.is_manager:
super().__init__(**kwargs)
else:
super().__init__(**kwargs)
del self.fields['can_assign']
class Meta:
model = User
fields = ['title', 'can_assign', 'bio']
views.py:
#login_required
def editUser(request, pk):
user = User.objects.get(id=pk)
if request.user.is_manager or request.user == user:
#POST
if request.method == 'POST':
form = EditUserForm(request.POST, instance=user, user=request.user)
if form.is_valid():
form.save()
redirect('user-page', pk)
else:
print('nope')
#GET
form = EditUserForm(user=request.user, instance=user)
context = {'user': user, 'form': form}
return render(request, 'users/user_edit.html', context)
else:
return HttpResponse('<h1>Access Denied</h1>')
template:
{% extends 'main.html' %}
{% block content %}
<form method="POST" action="">
{% csrf_token %}
{{form.as_p}}
<input type="submit" value="Submit">
</form>
{% endblock content %}
for some reason the form.is_valid() method returns False. I have no idea why.
I have tried to use the .errors method on the form and on the form fields. No errors shown.
Thanks for any help!
" Oh! I completely missed that. I think the *args is required because that's how you pass in the request.POST. if you would have an explicit key like myform(data=request.POST) it would have worked because it would be in the *kwargs .. So it was basically failing cause it was acting like you were just initiating a new form, not submitting one –
Nealium
"
I have made a new Comment Model in my Django Project but the form is not showing in the browser although I added the form in the template.
Here is the models.py
class Comment(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
post = models.ForeignKey(Post, on_delete=models.CASCADE)
body = models.TextField(max_length=300)
def __str__(self):
return str(self.pk)
Here is the views:
def comment_create(request, self):
post = get_object_or_404(Post, slug=self.kwargs['slug'])
user = User.objects.get(user=request.user)
c_form = CommentModelForm()
context = {
'post': post,
'user': user,
'c_form': c_form,
}
return context
Here is the forms.py
class CommentModelForm(forms.ModelForm):
body = forms.CharField(label='',
widget=forms.TextInput(attrs={'placeholder': 'Add a comment...'}))
class Meta:
model = Comment
fields = ('body',)
Here is the urls.py
path('blogs/comment', comment_create, name='comment-post'),
Here is the template:
<form action="" method="POST"class='ui fluid form'>
{% csrf_token %}
<input type="hidden" name="post_id" value={{post.id}}>
{{ c_form }}
<button type="submit" name="submit_c_form" class="">Send</button>
</form>
First, you have to get the type of request, I added a if/else for GET and POST requests. Added form.is_valid check.
In your function you are trying to get a kwarg form the url but you don't have a kwarg in your path.
path('blogs/<slug:slug>/comment', comment_create, name='comment-post'),
views.py
def comment_create(request, self):
post = get_object_or_404(Post, slug=self.kwargs['slug'])
if request.method == 'POST': # If user submitted form
c_form = CommentModelForm(request.POST) # Get form response
if c_form.is_valid(): # Chekc if form is valid
c_form.user = User.objects.get(user=request.user) # Get user and add it to form
c_form.post = post # Add post to form
c_form.save() # Save form
else:
c_form = CommentModelForm() # Pass form
context = {
'post': post,
'c_form': c_form,
}
return render(request, 'app/comment.html', context) # change template
forms.py
class Meta:
model = Comment
fields = ['body'] # When I set tuples it normally gives me an error
I have created this application but the problem I face now is one that has kept me up all night. I want users to be able to see and select only their own categories when they want to create a post. This is part of my codes and additional codes would be provided on request
category model
class Category(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, default=1,related_name='categories_created')
name = models.CharField(max_length = 120)
slug = models.SlugField(unique= True)
timestamp = models.DateTimeField(auto_now=False, auto_now_add=True)
post model
class Post(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, default=1,related_name='posts_created') #blank=True, null=True)
title = models.CharField(max_length = 120)
slug = models.SlugField(unique= True)
category = models.ForeignKey(Category, on_delete=models.CASCADE, related_name='category_created', null= True)
addition codes would be provided immediately on request. Thanks
View.py in post app
def create(request):
if not request.user.is_authenticated():
messages.error(request, "Kindly confirm Your mail")
#or raise Http404
form = PostForm(request.POST or None, request.FILES or None)
user = request.user
categories = Category.objects.filter(category_created__user=user).distinct()
if form.is_valid():
instance = form.save(commit=False)
instance.user = request.user
instance.save()
create_action(request.user, 'Posts', instance)
messages.success(request, "Post created")
return HttpResponseRedirect(instance.get_absolute_url())
context = {
"form": form,
}
template = 'create.html'
return render(request,template,context)
Form
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = [
"title",
"content",
"category",
]
html
{% if form %}
<form method="POST" action="" enctype="multipart/form-data">{% csrf_token %}
{{ form|crispy|safe }}
<input type="submit" name="submit" value="Publish">
</form>
{% endif %}
What you need to do is well-described here. Basically, you are using ModelForm which generates the form from your model. Your model doesn't know anything about filtering by user, so you will need to explicitly add a QuerySet to your form that only shows the desired categories. Change your "categories = ..." line to something like:
form.category.queryset = Category.objects.filter(user=user)
form.fields['category'].queryset = Category.objects.filter(user=user)</strike>
I'm trying to user Django model formset factory to render a template where a user can add images and change the images they have uploaded(very similar to what can be done in the admin). I currently can render the template and its correct fields to the template. What I cannot do is have the user preselected(want currently logged in) and when I refresh the page the image will be posted again(not sure if this is preventable). Below is my code. Thanks!
Model:
class Image(models.Model):
user = models.ForeignKey(User)
image = models.ImageField(upload_to=content_file_name, null=True, blank=True)
link = models.CharField(max_length=256, blank=True)
Form:
class ImageForm(forms.ModelForm):
image = forms.ImageField(label='Image')
class Meta:
model = Image
fields = ('image',
'link',
)
View:
#login_required
def register(request):
user_data = User.objects.get(id=request.user.id)
ImageFormSet = modelformset_factory(Image,
fields=('user', 'image', 'link'), extra=3)
if request.method == 'POST':
print '1'
formset = ImageFormSet(request.POST, request.FILES, queryset=Image.objects.all())
if formset.is_valid():
formset.user = request.user
formset.save()
return render(request, 'portal/register.html', {'formset': formset, 'user_data': user_data})
else:
print '2'
formset = ImageFormSet(queryset=Image.objects.all())
return render(request, 'portal/register.html', {'formset': formset, 'user_data': user_data})
Template:
<form id="" method="post" action=""
enctype="multipart/form-data">
{% csrf_token %}
{{ formset.management_form }}
{% for form in formset %}
{{ form }}
{% endfor %}
<input type="submit" name="submit" value="Submit" />
let me explain the way you can do it.
MODELS
from django.utils.text import slugify
from django.db import models
from custom_user.models import AbstractEmailUser
# User model
class UserModel(AbstractEmailUser):
full_name = models.CharField(max_length=255)
def __str__(self):
return str(self.id)
# Function for getting images from instance of user
def get_image_filename(instance, filename):
title = instance.id
slug = slugify(title)
return "user_images/%s-%s" % (slug, filename)
# Save images with user instance
class UserImages(models.Model):
user = models.ForeignKey('UserModel', db_index=True, default=None)
image = models.ImageField(upload_to=get_image_filename, verbose_name='Image', db_index=True, blank=True, null=True)
In forms it's a just a two form, one for model User, other for UserImages model.
# Images forms
class ImageForm(forms.ModelForm):
image = forms.ImageField(label='Image', required=False)
class Meta:
model = UserImages
fields = ('image',)
# User form
class UserForm(forms.ModelForm):
full_name = forms.CharField(required=True)
class Meta:
model = UserModel
fields = ('full_name','email','password',)
And in Views for post you can do something like this
# View
from models import *
from forms import *
#csrf_protect
def post_view(request):
template = 'some_template.html'
ImageFormSet = modelformset_factory(UserImages, form=ImageForm, extra=15)
if request.method == 'POST':
user_form = UserForm(request.POST, prefix='form1')
formset = ImageFormSet(request.POST, request.FILES, queryset=UserImages.objects.none(), prefix='form2')
if user_form.is_valid() and formset.is_valid():
# Save User form, and get user ID
a = user_form.save(commit=False)
a.save()
images = formset.save(commit=False)
for image in images:
image.user = a
image.save()
return HttpResponseRedirect('/success/')
else:
user_form = UserForm(prefix='form1')
formset = ImageFormSet(queryset=UserImages.objects.none(), prefix='form2')
return render(request, template, {'form_user':user_form,'formset':formset})
In template you are doing the right thing.
I want to save an add under the current user that i'm logged in as, but i keep getting the error outlined in the subject.
My models:
class CustomUser(User):
nickname = models.CharField(max_length=255)
phone = models.CharField(max_length=255)
address = models.CharField(max_length=255)
objects = UserManager()
city = models.ForeignKey(locations, unique=False)
def __str__(self):
return self.nickname
class Admin:
pass
class listings(models.Model):
title = models.CharField(max_length=255)
category = models.ForeignKey('category')
description = models.CharField(max_length=255)
published = models.DateField(auto_now=True)
user = models.ForeignKey(CustomUser, unique=False)
def __str__(self):
return self.naslov
class Admin:
pass
The form:
class jobOfferForm(forms.ModelForm):
title = forms.CharField(max_length=255)
description = forms.CharField(max_length=255)
category = forms.ModelChoiceField(queryset=kategorii.objects.all())
class Meta:
model = listings
The template:
<div class="span8">
<form action="" method="POST">
{% csrf_token %}
{{form.as_p}}
<input type="submit" name="submit" value="Save"/>
</form>
</div>
The view!
def displisting(request):
if request.method == 'POST':
form = jobOfferForm(request.POST)
if form.is_valid():
title = form.cleaned_data['title']
description = form.cleaned_data['description']
new_listng = form.save(commit = False)
new_listng.user = request.user
new_listng.object.save()
return HttpResponseRedirect('/listing/review')
else:
form = jobOfferForm()
return render(request,'listings.html',{'form':form,})
I fear the custom user is preventing me from doing that?
But i need the extra attributes?
this error will happen if your user is not logged in.
login using the bundled /admin site and your request.user object will be a valid User instance
request.User isn't an instance of your custom CustomerUser, it's a django.contrib.auth.models.User. Hence the assignment:
new_listng.user = request.user
isn't valid.
You probably want your request.User to be downcast to your CustomerUser (or other subclasses, if you have them). You can add a custom middleware, modeled off django.contrib.auth.middleware.AuthenticationMiddleware that does this.
django-model-util's InheritanceManager has some useful helpers like select_subclasses that make this easy.