Django Creation View Doesn't save any data - django

My creation view redirect to blog main page well after creation but
i can't find any post's been created in the posts or admin page posts, can anyone help please
here is my view
#login_required
def add_post(request):
if request.method == 'POST':
post_form = PostForm(request.POST, request.FILES, instance=request.user)
snippet_form = SnippetForm(request.POST)
if post_form.is_valid() and snippet_form.is_valid():
post = post_form.save(commit=False)
snpt = snippet_form.save(commit=False)
post.creator = request.user
snpt.id = post.id
post.save() and snpt.save()
return redirect('blog:index')
else:
post_form = PostForm()
snippet_form = SnippetForm()
return render(request, 'blog/add_post.html', {'post': post_form, 'snpt': snippet_form})
what's wrong in this view cause i been able to save new post from admin add new post but from client it doesn't save anything
Do I need to use model create() method here or what?
*Any required snippet i will provide but the problem is in this snippet
any help is really appreciable
Update:
my Post model
class Post(models.Model):
...
creator = models.OneToOneField(settings.AUTH_USER_MODEL...
snippet = models.OneToOneField(Snippet,...
...

post.save() and snpt.save()
should be:
post.save()
snpt.save()
I suspect you were thinking (by using the keyword and) that you want to ensure both models are saved at the same time, but you are actually asking Python to compare the return results of the two functions to see if they are both True; this is breaking your code (as save() returns None, only your first save() is running as Python will not even execute the second as there's no way they can both be True when the first has already returned Falsey).
You may find this question useful in your scenario.

in case anyone interested to know
Firstly
As The relation between Post model and Snippet model is OneToOne, following line
snpt.id = post.id
need to be removed
would violates the unique pk constraint, if you changed the relation to foreign key that would add another instance of snippet with another pk
you can remove it or assign instead
post.snippet = snpt
Secondly
No need for commit=False in snpt_form as it already an instance of post_form and i didn't want to change anything else except the form fields
Thirdly
Either put
creator=request.user
instead of
instance=request.user
inside the post_form
or remove it and leave
post.creator = request.user
forth
Also as #bigkeefer mentioned but this is secondly arises after solving the main problem
the short circuit python precedence rule causing this line to fail
post.save() and snpt.save()
instead put
post.save()
snpt.save()

Related

How to update data in Django when getting unique field error

first thing first I'm sorry for my bad english. I hope so u can understand me easily.
I'm trying to make a blog with django but there's a place I can't solve. I used unique slug field instead of id for url, whenever I want to update the data I get the UNIQUE constraint failed: post_post.url_text error (url_text is slugfield variable name). Here is the my model,
and the Form looks like this,
At first I followed a way to update the data here:
#login_required(login_url='login')
def post_update(request, url_text=None):
post = get_object_or_404(Post, url_text=url_text)
form = PostWrite(request.POST or None, instance=post)
if form.is_valid():
post_author = request.user
post_title = form.cleaned_data.get('post_title')
post_content = form.cleaned_data.get('post_content')
post_tags = form.cleaned_data.get('tags')
post = Post(post_author=post_author, post_title=post_title, post_content=post_content, tags=post_tags)
post.save()
context = {
'post': post,
'form': form,
}
return render(request, 'post/re_write.html', context)
and I got the error I mentioned at the beginning of the post. Then I found a solution like this in the forums,
if form.is_valid():
form.save()
This time it does not give any error but does not update the data. Despite hours of research, for some reason I could not find a tangible solution. I wanted to ask you esteemed coders as a last resort and I look forward to your help.
The issue is that you're creating a new post with the following code while this view appears to be an update:
post = Post(post_author=post_author, post_title=post_title, post_content=post_content, tags=post_tags)
post.save()
Instead, you should utilize the modelform you're already using to save the changes to the instance:
if form.is_valid():
post = form.save()
I'm guessing maybe because you weren't capturing the post from form.save() the rendered template appeared to not have the data updated because the instance passed into the template was from before the changes.
Other issue:
You're overriding the save method, but not always calling super().save. This means that you're only saving the post when the url_text property is not set. Instead always call super().save
def save(self, *args, **kwargs):
if ...
# other stuff
super().save(*args, **kwargs)

need to make my create post FBV not include the user currently signed in

hi guys so I just started studying django about 1.5 weeks ago so im like really new but I'm finally starting to understand the gist of everything and I wanted to test myself by making a blog app w/o help on tutorials on youtube and I did finish the app (like everything works) but theres one part thats really bugging me. So in my create_post FBV, I wanted to make it so that when the signed in user makes a post, my postform doesn't show the username, but only the title and the content to create. but when I first excluded it, the post wouldn't create since the computer doesn't know who the user is. I tried looking stuff up for the longest time and what to do and not searching on youtube, but the best thing I could find was passing it initial. After i finished everything else I saw someone did it by using a CBV but i only just started reading the source code and documentation for like two days so I'm no where near comfortable with them. This is my code:
#login_required
def create_post(request):
form = PostForm(initial={'author':request.user})
if request.method == 'POST':
form = PostForm(request.POST, initial={'author':request.user})
if form.is_valid():
form.save()
return redirect('blog-home')
context = {
'form': form
}
return render(request, 'posts/create_post.html', context)
so my postform has a user attribute which is a one-to-many relationship with the User so when I create a post on admin, I can choose among a whole list of users which is what i wanted. but on the blog site itself when I create a post as im already signed in, my code makes it that the drop down menu still shows but my username is just automatically filled in. so technically a user can post as a different user than who hes signed in as. I tried looking all over but couldn't find the solution other than using CBV. I can start reading on them a lot more but is there any way to do this with FBVs?
you need to get the user before saving the the form.
#login_required
def create_post(request):
if request.method == 'POST':
form = PostForm(request.POST)
if form.is_valid():
post = form.save(commit=False)
post.user = request.user
post.save()
return redirect('blog-home')
context = {
'form': form
}
return render(request, 'posts/create_post.html', context)
In post.user, the user is the name of the fields you define when getting the user as one-to-many in Post model.

Problems when obtaining an id, sent by a form

Good evening, I am trying to get the id of my model Note that is sent by means of a form, but when I put form.id it tells me that id is not defined, try to get it through the user session but it says that it was not found.
def add_book(request):
template_name = 'books/create_note.html'
book = get_or_create_book(request)
form = NoteForm(request.POST)
if request.method == 'POST' and form.is_valid():
note = Note.objects.get(pk=form.pk)
book.notes.add(note)
form.save()
return redirect('books:book')
return render(request, template_name, {
'form': form,
})
and this is the form
class NoteForm(ModelForm):
class Meta:
model = Note
fields = (
'title', 'nota'
)
labels = {
'title': 'Titulo',
'nota': 'Nota',
}
try creating an instance of my Note model but when it comes time to create it tells me it is empty.
I'm new to Django, but I had similar problems that frustrate me. not sure if I have the hang of it yet, but I think what might be happening is that when you first go to the page there is a GET request, so your if statement misses it. It then it reaches the last line and goes to template_name without the form being assigned so the form never gets a Post requests. In the terminal you can see the POST and GET requests. I ended up also printing out request.method a lot before and after if statements just to help trace what was going on.
else:
form=NoteForm()
Then your return render(request,....
making sure it goes back to the correct html page.
The thing that worked for me eventually was something like
def Search_Page(request):
if request.method=='POST':
form = Search_Page_Form(request.POST)
if form.is_valid():
do some stuff and save the change to the model
return(redirect('mainapp:Evaluate_Page'))
else:
form=Search_Page_Form()
return render(request, 'mainapp/Search_Page.html', {'form': form})

Custom UpdateView in Python

I am trying to get a custom UpdateView to work in Python/Django. I believe that the code that I've writtten is mostly correct, as it seems to be returning the proper Primary Key ID in the URL when I click on the associated dropdown. The problem is that I am not seeing any of the data associated with this record on the screen in update mode. The screen appears in edit mode, but there is no data. I suspect the problem is perhaps the django template in the html form? However, I have played with the form and used {{ form }} and it too returns a blank form. I've played with this all afternoon and I'm out of guesses. Here is my view:
def updating_document(request, pk):
doc = get_object_or_404(Doc, pk=pk)
form = Update_Doc_Form(request.user, request.POST)
if request.method == 'GET':
if form.is_valid():
form.save()
return HttpResponseRedirect(reverse('App:main_procedure_menu'))
else:
print("Form is invalid!")
return render(request,'Doc/update_doc.html',{'form':form })
I also have an associated form...
Form.py
class Update_Doc_Form(forms.ModelForm):
class Meta:
model = Doc
exclude = ['user']
doc_name = forms.CharField(widget=forms.TextInput)
description = forms.CharField(required=True,widget=forms.Textarea)
team = forms.CharField(widget=forms.Select)
document = forms.CharField(required=True,widget=forms.Textarea)
def __init__(self, *args, **kwargs):
super(Update_Doc_Form, self).__init__(*args, **kwargs)
self.fields['doc_name'].widget.attrs['class'] = 'name'
self.fields['description'].widget.attrs['class'] = 'description'
self.fields['team'].widget.attrs['class'] = 'choices'
self.fields['team'].empty_label = ''
I'm a newbie, but I do want to use a custom UpdateView so that I can alter some of the fields and pass user information. I feel like the code is close, just need to figure out why it's not actually populating the form with data. Thanks in advance for your help!
What a difference a day makes. Found an answer on SO this morning. Not sure how to credit the person or issue number....
The answer was to add the following line of code to my form:
user = kwargs.pop('object_user')
I also needed to add the following function to my View:
def get_form_kwargs(self):
kwargs = super(ViewName,self).get_form_kwargs()
kwargs.update({'object_user':self.request.user})
return kwargs
This question was answered originally in 2013 by Ivan ViraByan. Thanks Ivan!
I ultimately went with a standard class based UpdateView and scrapped my plans for the custom UpdateView once I was able to figure out how to use the Class Based View(UpdateView) and "pop" off the user information when passing it to the form based on Ivan ViraByan's answer in 2013.
The code above allows you to get the user but not pass it to the ModelForm so that you don't get the unexpected user error.

Form Validation Error when a required field is remained blank in django

I want to have errors as a label above a field if it is not filled.
This is my views.py:
#login_required(login_url='user_profile:login')
def NewWriting(request):
if request.method=="POST":
form=WritingForm(request.POST)
if form.is_valid():
post=form.save(commit=False)
post.author=request.user
post.save()
return redirect('user_profile:index')
else:
form = WritingForm()
subject = Subject.objects.all()
return render(request,'user_profile/writing_form.html', {'form':form , 'subject':subject})
what should I add to my code?
Thanks
Without seeing your form class ...
Option 1:
If you really want the user to be able to submit the form with empty data and then specifically show them that error using the form, set the required=False kwarg for the specific field in your WritingForm class. Then override the clean_<fieldname> (link) method and then you could do:
def clean_<fieldname>:
if self.cleaned_data['<fieldname>'].strip() == '':
raise ValidationError('This field cannot be blank!')
return self.cleaned_data['<fieldname>']
Replacing <fieldname> with whatever that fieldname is.
Option 2:
The default for any form is to make all fields required (IE: required=True kwarg on the field). So in general, if the field is required most browsers will at least move the cursor to the empty field and won't allow the form to be submitted while there is no data in the field.
You also need to return a bound form in the case where form.is_valid() returns False or you won't ever see the errors (right now you don't return anything if the form is invalid). Please see the django docs here for a common functional view pattern using forms.
You need to add another all to render if the form is not valid, and in your template, you need to make use of form.errors. Something like this should work so that form validation errors are then passed back to the UI/template for display to the user:
#login_required(login_url='user_profile:login')
def NewWriting(request):
form = None
if request.method=="POST":
form=WritingForm(request.POST)
if form.is_valid():
post=form.save(commit=False)
post.author=request.user
post.save()
return redirect('user_profile:index')
if form is None:
form = WritingForm()
subject = Subject.objects.all()
return render(request,'user_profile/writing_form.html', {'form':form , 'subject':subject})