Error after posting new data to the web server - python

It all looks good by when i try to add some post to my topic I have an error created_by=user
:
Here is my forms.py
from django import forms
from .models import Topic
class NewTopicForm(forms.ModelForm):
message = forms.CharField(
widget=forms.Textarea(
attrs={'rows': 5, 'placeholder': 'What is on your mind?'}
),
max_length=40000,
help_text='The max length of the text is 4000.')
class Meta:
model = Topic
fields = ['subject', 'message']
and my view function for this form:
def new_topic(request, pk):
board = get_object_or_404(Board, pk=pk)
user = User.objects.first()
if request.method == 'POST':
form = NewTopicForm(request.POST)
if form.is_valid():
topic = form.save(commit=False)
topic.board = board
topic.starter = user
topic.save()
post = Post.objects.create(
message=form.cleaned_data.get('message'),
topic=topic,
created_by=user
)
return redirect('board_topics', pk=board.pk)
else:
form = NewTopicForm()
return render(request, 'new_topic.html', {'board': board, 'form': form})
models.py
class Post(models.Model):
message = models.TextField(max_length=4000)
topic = models.ForeignKey(Topic, related_name='t_posts', on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(null=True)
created_by = models.ForeignKey(Topic, related_name='posts', on_delete=models.CASCADE)
updated_by = models.ForeignKey(User, related_name='+', null=True, on_delete=models.CASCADE)

There is a mistake in your Post model
created_by needs to be a Foreign Key to the User table
created_by = models.ForeignKey(User, related_name='created_by', on_delete=models.CASCADE)
run the following commands after the above changes to reflect the changes in the database
python manage.py makemigrations
python manage.py migrate

Related

Send id from one table to another automatically in form with ForeignKey in Django

#HELP in python (DJANGO 4)
I send this message here because I have not been able to find an answer elsewhere.
Currently I’m on a project where I have to create a booking form.
The goal is that when the user submit the Reservation form, I send the data in BDD, and I retrieve the user's id by a relation (ForeignKey).
And my difficulty is in this point precisely, when I send my form in BDD I recover the information, except the id of the user…
I did a Foreignkey relationship between my 2 tables and I see the relationship in BDD but I don’t receive the id of the User table, but null in the place….
Does anyone of you know how to help me please?
Thank you all.
--My model.py --
class Reservation(models.Model):
fullName = models.CharField('Nom Complet', max_length=250, null=True)
adress = models.CharField('Adresse', max_length=100, null=True)
zip_code = models.IntegerField('Code Postal', null=True)
city = models.CharField('Vile', max_length=100, null=True)
email = models.EmailField('Email', max_length=250, null=True)
phone = models.CharField('Telephone', max_length=20, null=False)
date = models.CharField('Date', max_length=20, null=True, blank=True)
hour = models.CharField('Heure', max_length=20, null=True, blank=True)
message = models.TextField('Message', null=True)
accepted = models.BooleanField('Valide', null=True)
created_at = models.DateTimeField('Date Creation', auto_now_add=True, null=True)
modified_at = models.DateTimeField('Date Mise Jour', auto_now=True, null=True)
user = models.ForeignKey(User, null=True, on_delete=models.SET_NULL)
def __str__(self):
return self.fullName
-- my views.py --
#login_required()
def user_new_reservation(request, pk=None):
user = User.objects.get(id=pk)
if request.method == 'POST':
form = ReservationForm(request.POST)
if form.is_valid():
form.save()
messages.success(request, 'Votre réservation a bien été envoyé!')
return redirect('reservation:user_reservation', pk=request.user.id)
else:
form = ReservationForm()
context = {'form': form}
return render(request, 'reservation/new_reservation.html', context)
-- My Form.py --
class ReservationForm(forms.ModelForm):
class Meta:
model = Reservation
fields = [
'fullName',
'adress',
'zip_code',
'city',
'email',
'phone',
'date',
'hour',
'message',
]
Thank you all.
Inside your form.save use:
user = form.save(commit=False)
user.user = request.user
user.save()
user=your field name in your model
request user= in django when you use authentication you can access some of information based on request like user and other
Good luck

How to use default field values for ForeignKey?

I'm just starting to learn Django and building a simple blog with it.
So i have two models Post and PostStatistics. When ever i add a new post, i want that PostStatistics contains all specified default values. How can i achieve this correctly?
models.py
class PostStatistics(models.Model):
id = models.UUIDField(primary_key=True, default=uuid4)
post_views = models.IntegerField(default=0)
post_likes = models.IntegerField(default=0)
post_favorites = models.IntegerField(default=0)
class Post(models.Model):
id = models.UUIDField(primary_key=True, default=uuid4)
user = models.ForeignKey(UserProfile, null=True, on_delete=models.CASCADE)
statistics = models.ForeignKey(PostStatistics, null=True, on_delete=models.CASCADE)
title = models.CharField(max_length=200)
body = RichTextField(blank=True, null=True)
draft = models.BooleanField(default=False)
views.py
def add_post(request: HttpRequest):
form = PostForm(request.POST)
is_draft = True if form.data.get("draft") == "on" else False
post = Post(
title=form.data["title"],
body=form.data["post"],
user=request.user,
draft=is_draft,
statistics = PostStatistics() -> this is not correct
)
post.save()
return redirect("post")
At the moment i get FOREIGN KEY constraint failed.
You create a new one:
def add_post(request: HttpRequest):
form = PostForm(request.POST)
is_draft = form.data.get('draft') == 'on'
post_statistics = PostStatistics.objects.create()
Post.objects.create(
title=form.data['title'],
body=form.data['post'],
user=request.user,
draft=is_draft,
statistics = post_statistics
)
return redirect('post')
It however does not make much sense to store the statistics in a separate model, since there is a clear one-to-one relation, and thus the statistics can be stored in the Post model.
Furthermore you can use the form to validate the input and also create the object (or at least parts of it). A better modeling thus might be:
from django.conf import settings
class Post(models.Model):
id = models.UUIDField(primary_key=True, default=uuid4)
user = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, on_delete=models.CASCADE, editable=False)
title = models.CharField(max_length=200)
body = RichTextField(blank=True, null=True)
draft = models.BooleanField(default=False)
post_views = models.IntegerField(default=0, editable=False)
post_likes = models.IntegerField(default=0, editable=False)
post_favorites = models.IntegerField(default=0, editable=False)
and then work with a ModelForm where you let the form do all the proper validation and cleaning:
from django.contrib.auth.decorators import login_required
#login_required
def add_post(request: HttpRequest):
if request.method == 'POST':
form = PostForm(request.POST)
if form.is_valid():
form.instance.user = request.user
form.save()
return redirect('post')
else:
form = PostForm()
return render(request, 'name-of-some-template.html', {'form': form})
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.
Note: You can limit views to a view to authenticated users with the
#login_required decorator [Django-doc].

IntegrityError at /create/ NOT NULL constraint failed: main_post.author_id

When i try to create an new post with http://localhost:8000/create/ , i get this error. I couldn't find the solution thought they seem similar. I follows some blog tutorial
I can't paste the settings.py here because there to much code in the post but i think the settings.py is fine btw
My models.py (* i deleted some code maynot involve)
User = get_user_model()
class Author(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
profile_picture = models.ImageField()
def __str__(self):
return self.user.username
class Post(models.Model):
title = models.CharField(max_length=100)
overview = models.TextField()
detail = models.TextField()
timestamp = models.DateTimeField(auto_now_add=True)
content = RichTextUploadingField(config_name='post_ckeditor')
comment_count = models.IntegerField(default=0)
view_count = models.IntegerField(default=0)
author = models.ForeignKey(Author, on_delete=models.CASCADE)
thumbnail = models.ImageField()
categories = models.ManyToManyField(Category)
featured = models.BooleanField()
previous_post = models.ForeignKey('self', related_name='previous', on_delete=models.SET_NULL, blank = True, null = True)
next_post = models.ForeignKey('self', related_name='next', on_delete=models.SET_NULL, blank = True, null = True)
My views.py
def get_author(user):
qs = Author.objects.filter(user=user)
if qs.exists():
return qs[0]
return None
pass
def post_create(request):
form = PostForm(request.POST or None, request.FILES or None)
author= get_author(request.user)
if request.method == 'POST':
if form.is_valid():
form.instance.author = author
form.save()
return redirect(reverse('post-detail', kwargs={
'id': form.instance.id
}))
context = {
'form': form
}
return render(request, 'post_create.html', context)
pass
My forms.py
from django import forms
from .models import Post, Comment
class PostForm(forms.ModelForm):
content = forms.CharField
class Meta:
model = Post
fields = ('title', 'overview', 'content', 'thumbnail', 'categories', 'featured', 'previous_post', 'next_post')
class CommentForm(forms.ModelForm):
content = forms.CharField(widget=forms.Textarea(attrs={
'class':'form-control',
'placeholder':'Type your comment',
'id':'usercomment',
'rows':4
}))
class Meta:
model = Comment
fields = ('content', )
Please help !
If you are trying to save request.user in the author field you don't need to write the extra methods just do like this.
if request.method == 'POST':
if form.is_valid():
post =form.save(commit=False)
post.author = request.user
post.save()
return redirect(reverse('post-detail', kwargs={'id': post.id }))
Whenever there is a change in model fields or new model added or removed, you should migrate. And pass a default object to foreign key if not null.

Django save ManyToManyField Model with ModelMultipleChoiceField

So I know there are a few similar questions but none of the solutions worked for me. I've tried save(commit=false) and save_m2m as well as a bunch of other stuff but i get the error
NOT NULL constraint failed: home_services.managers_id
Anyways here's my code:
views.py
def service(request):
if request.user.is_authenticated:
if request.method == 'POST': #Create Service
form = CreateServiceForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('/service') #Later change this to redirect to server page
else:
form = CreateServiceForm()
args = {'user': request.user, 'form': form}
return render(request, 'service.html', args)
else:
return HttpResponseRedirect('/feed')
models.py
class Services(models.Model):
name = models.CharField(max_length=100, default='')
description = models.CharField(max_length=500, default='')
owner = models.OneToOneField(User, on_delete=models.CASCADE)
managers = models.ForeignKey(User, related_name="managers", on_delete=models.CASCADE)
members = models.ManyToManyField(User, related_name="members")
def __str__(self):
return str(self.name) + ": id" + str(self.id)
forms.py
class CreateServiceForm(forms.ModelForm):
owner = forms.ModelChoiceField(queryset=User.objects.all())
members = forms.ModelMultipleChoiceField(queryset=User.objects.all())
class Meta:
model = Services
fields = [
'name',
'description',
'owner',
'members',
]
I want the user to be able to create a service and select 1 or more members that is in the default django User model.
I want the user to be able to create a service and select 1 or more members that is in the default django User model.
You are not providing managers, which is not allowed as per the current configuration.
So, change:
managers = models.ForeignKey(
User,
related_name="managers",
on_delete=models.CASCADE,
)
To:
managers = models.ForeignKey(
User,
related_name="managers",
on_delete=models.CASCADE,
blank=True,
null=True,
)
You might want to read more about blank and null.

Django Foreign key field validation in a forms or models ( getting info created by only that user from foreign key)

I'm trying to build courses and add lessons to a course later and the problem I encounter is that every user can choose to add courses to another person created courses.
Like if you create some courses, another user will see as an option to add his lesson to it
views.py
def creatingLessonsForm(request):
form = CreatingLessonsForm(request.POST or None)
if form.is_valid():
post = form.save(commit=False)
post.CreatedBy = request.user
post.save()
form = CreatingLessonsForm()
context = {'form': form}
return render(request, 'courses/creatingLessonsForm.html', context)
models.py
class CreatingCourses(models.Model):
NameOfTheCourses = models.CharField("Name of the courses", max_length=60, blank=False)
Category = models.ForeignKey(Subject, on_delete=models.CASCADE)
CreatedBy = models.ForeignKey(User, on_delete=models.CASCADE, null=True)
Document = models.ForeignKey(Document, on_delete=models.SET_NULL, verbose_name= "Select document for courses introduction", blank=True , null=True)
IncludeTest = models.ForeignKey(GenaratedTest, on_delete=models.SET_NULL, verbose_name= "Include test for courses", blank=True , null=True)
AdditionalInfo = models.TextField("Additional info for courses introduction", max_length=300, blank=False)
Note = models.TextField("Notes", max_length=180, blank=True)
Show_the_courses = models.BooleanField(verbose_name= "Show the courses for everyone?",default=True)
def __str__(self):
return str(self.NameOfTheCourses) if self.NameOfTheCourses else ''
class CreatingLessons(models.Model):
Courses = models.ForeignKey(CreatingCourses, on_delete=models.SET_NULL, null=True)
NameOfTheLesson = models.CharField(max_length=60, verbose_name= "Name of the lesson", blank=False)
Document = models.ForeignKey(Document, on_delete=models.SET_NULL, verbose_name= "Document for lesson", blank=True , null=True)
CreatedBy = models.ForeignKey(User, on_delete=models.CASCADE, null=True)
Lesson = models.TextField(max_length=250, verbose_name= "Lesson", blank=False)
Note = models.TextField("Notes", max_length=100, blank=True)
Show_the_lesson = models.BooleanField(verbose_name= "Show the lesson inside courses?",default=True)
forms.py
class CreatingCoursesForm(forms.ModelForm):
class Meta:
model = CreatingCourses
fields = ['NameOfTheCourses', 'Category', 'IncludeTest', 'Document' , 'AdditionalInfo', 'Note', 'Show_the_courses' ]
class CreatingLessonsForm(forms.ModelForm):
class Meta:
model = CreatingLessons
fields = ['Courses', 'NameOfTheLesson', 'Document', 'Lesson', 'Note', 'Show_the_lesson']
Image of webpage:
You need to pass the user when you initialize the form and then filter the queryset for the available courses that can be selected
class CreatingLessonsForm(forms.ModelForm):
def __init__(self, data=None, user=None, **kwargs):
super().__init__(data, **kwargs)
self.fields['Courses'].queryset = CreatingCourses.objects.filter(CreatedBy=user)
And then when you initialize the form pass the user
# When rendering the initial form
form = CreatingLessonsForm(user=request.user)
# When passing POST data to the form
form = CreatingLessonsForm(request.POST, user=request.user)
One option would be to modify your to filter the courses by user.
class CreatingLessonsForm(forms.ModelForm):
...
def __init__(self, *args, **kwargs):
request_user = kwargs.pop('request_user')
super().__init__(*args, **kwargs)
self.fields['Courses'].queryset = self.fields['Courses'].queryset.filter(
CreatedBy=request_user)
For that to work you will need to pass in the user of the request to the form, maybe like this:
def creatingLessonsForm(request):
data = request.POST.copy()
data['request_user'] = request.user
form = CreatingLessonsForm(data)
...

Categories