Why won't my text posts save, it worked before? - django

My text posts were working before adding a notification feature but now they aren't, I have a debug print but instead of seeing the post object, I'm seeing the user that posted it. I haven't changed anything other than getting the post id, timesince and the notify function, I've used the exact same method with my picture and video posts and they work fine, so it doesn't make sense to me. I've got a debug print in the notification function to make sure the post type and id have been passed correctly and those indeed show the id and type
views.py
#login_required()
def text_post(request):
if request.method == "POST":
form = TextPostForm(request.POST)
if form.is_valid():
t_post = form.save(commit=False)
t_post.author = request.user
t_post.save()
id = t_post.id
time = timesince
print(t_post) # t_post shows the user instead of the post
followers = list(request.user.followers.all())
notify(followers,
request.user,
f"{request.user.username} posted {time}",
id,
'text'
)
print(t_post)
#redirect to last page
return redirect('home')
else:
form = TextPostForm()
post_type = 'text'
return render(request, 'create_post.html', {'form': form, 'post_type': post_type})
forms.py
class TextPostForm(forms.ModelForm):
class Meta:
model = TextPost
fields = ('description','privacy', 'categories')

Related

limit django query to current session and pass it to a function view

So I'm trying to make a calculator of sorts where the user enters some data and then they are presented with a view that gives them the results they need (printer-friendly format so they can print it).
What I've done so far:
Created a model and a form which they work as intended.
**class CalcModel**(models.Model):
income = models.DecimalField...
civil_status = models.CharField...
have_children = models.CharField..
**class CalcForm**(ModelForm):
class Meta:
**model = Calculate**
fields = ['income', 'civil...]
The view that processes the form and redirects to another view if submitted data is valid:
data_d = {}
def createcalculation(request):
form = CalcForm()
if request.method == 'POST':
form = CalcForm(request.POST)
if form.is_valid():
**data_d['cleaned_data'] = form.cleaned_data**
form.save()
return redirect('res-view')
context = {'c_form': form}
return render(request, 'calc/calc.html', context)
I think there should be a way to pass the model instance data to the view where the user is redirected but I can't figure it out. So, help is highly appreciated. Right now, I'm 'manually' passing a dictionary containing the data from the form but it doesn't work:
def res_ca(request):
context = data_d
return render(request, 'calc/res_ca.html', context)
I can't seem to figure out how to pass the data for the current session to the res_ca view.
The urls if that helps:
path('calc', createcalculation, name='calculate'),
path('res/', res_ca, name='res-view'),
As suggested by #vinkomlacic, I found a way to include the id of the model instance by switching to the render method instead of redirect and it worked like a charm.
if form.is_valid():
messages.success(request, f'Successful!')
item = form.save()
m_data = Calculate.objects.get(id=item.id)
context = {'c_data': form.cleaned_data, 'm_data': m_data}
return render(request, 'calc/res_ca.html', context)
This way, the form is saved, I can pass that instance of the model to the next view and it also allows me to add additional context to the template directly from model methods.

Django update functionality

I've got a model, with two forms. When a calf is scanned in, it gets one set of information, then when it's shipped out, it's a separate form with different information. For example when scanned in, it takes DOB and arrival date, when scanned out we need ship out date, milk consumed during it's stay(2 quarts per day), where it is going, and any medication while at the depot.
Right now I have the two forms below:
Scan in form
scan out form
Now you can see when I try to update an entry I get an error that it already exists
Here is my view:
def scanoutcalf(request, id=None):
form = ScanOutForm(request.POST or None)
context = {
'form': form,
}
form = ScanOutForm(request.POST or None)
if form.is_valid():
form.save()
return render(request, 'calves/scan_out.html', context)
And my forms:
class ScanOutForm(forms.ModelForm):
class Meta:
model = Calf
fields = [
'eid', 'ship_out_date', 'program', 'destination', 'medical_history', 'milk_consumed'
]
widgets = {
'ship_out_date': forms.widgets.DateInput(
attrs={'type': 'date'}
)
}
I've googled around, but couldn't find an example of how to update without having to create a queryset or a URL with instance ID.
The idea here is that a user can just scan when calves are leaving, update with the information that is essential, and the form will check the EID, and update the DB if it exists, or create it if it doesn't. Any help would amazing
Query the instance before saving and pass into ScanOutForm as keyword argument instance.
Like so:
def scanoutcalf(request, id=None):
form = ScanOutForm(request.POST or None)
context = {
'form': form,
}
if request.method == 'POST':
try:
calf = Calf.objects.get(eid=request.POST['eid'])
except:
calf = None
if calf is not None:
form = ScanOutForm(request.POST, instance=calf)
if form.is_valid():
form.save()
return render(request, 'calves/scan_out.html', context)
Note: As you use unique identifier in the form this must be directly extracted from request.POST with validation.

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

Django initial value for MultiChoice Field ignored for ModelForm

this is my first post here and I am very new to Django but I just can't seem to find a solution for this problem... I've searched stackoverflow and google but nothing seems to work for me...
I have a wine-app and want to be able to add and remove wines from the user's stock. In the list of wines the user can choose a wine to add and the ID of this wine is passed in the POST data. Since the data is getting lost after the first time the view is rendered I saved the ID in a cookie, which is working, but the problem is when I work with ModelForm de user has to select the foreign key for the user and for the wine, which is bad, so I tried to make it hidden and set the Fk_user and Fk_wine after the user choose the number of bottles to be added but before validation. Here's the problem after google everyone suggested I should use the "initial" and pass that to the form, but this is clearly not working because if I make the fields visible in the form I can see that it is not preselected...
viewy.py:
def addStockView(request):
wineId = request.POST.get('addStock')
if 'addStock' in request.POST:
wine = get_object_or_404(Wine, idwine=int(wineId))
userId = request.user.id
user = get_object_or_404(AuthUser, id=userId)
if request.method == 'POST':
#wineIdNew = request.COOKIES.get('wineIdToAdd')
#wineNew = get_object_or_404(Wine, idwine=wineIdNew)
form = StockForm(request.POST, initial={'fk_wine': wineNew.idwine, 'fk_auth_user': user.id})
if form.is_valid():
form.save()
return redirect('home')
else:
form = StockForm(initial={'fk_wine': wine.id,
'fk_auth_user': user.id})
response = render(request, 'addToStock.html', {'form': form})
response.set_cookie('wineIdToAdd', wineId)
return response
forms.py:
class StockForm(forms.ModelForm):
#fk_wine = ModelChoiceField(queryset=Wine.objects.all(),
# widget=HiddenInput())
#fk_auth_user = ModelChoiceField(queryset=AuthUser.objects.all(),
# widget=HiddenInput())
class Meta:
model = UserWineStock
fields = ['fk_auth_user', 'fk_wine', 'number']
can anyone help me with this..?
Yes, initial data is ignored when a form is bound to submitted data.
Instead of using initial here, you should exclude those two fields from the form and set them on the created object:
form = StockForm(request.POST)
if form.is_valid():
item = form.save(commit=False)
item.fk_wine = wine
item.fk_auth_user = request.user
item.save()
return redirect('home')
(Also, please don't call your fields things like fk_auth_user. Just call it user.)

django form errors before submit

My django form has errors in the initial page load, before the form even has a chance to be submitted.
My view:
def example_function(request):
if request.method == 'POST':
# the request is GET
else:
form = MyForm(user=request.user)
import pdb;pdb.set_trace()
return render_to_response('templates/example.html', locals(), context_instance=RequestContext(request),)
Where I have my pdb imported, in the console I can see that my form already has errors. The output of form.errors in my console is all the fields in the model which are set to not null.
(Pdb) form.errors
{'example_field_1': [u'This field is required.'], 'example_field_2': [u'This field is required.']}
The form has not submit yet, but I am still getting errors. Can someone explain?
I'm using django 1.4.
My form:
class MyForm(forms.ModelForm):
captcha = ReCaptchaField()
_readonly_template = form.TextInput(attrs={'readonly':'readonly'})
first_name = forms.CharField(widget = _readonly_tempalte)
def __init__(self, data=None, *args, **kwargs):
data = data or {}
if 'user' in kwargs:
user = kwargs['user']
del kwargs['user']
data.update({
'first_name' : user.first_name,
})
super(MyForm, self).__init__(data, *args, **kwargs)
class Meta:
model = MyModel
My model:
class MyModel(models.Model):
first_name = models.CharField(max_length=255)
example_field_1 = models.CharField(max_length=255)
example_field_2 = models.CharField(max_length=255)
https://docs.djangoproject.com/en/1.8/ref/forms/validation/
accessing the form.errors attribute will trigger the various form validation methods. Those errors shouldn't show up when you render the form.
I'm not sure how the user field is structured, but keep in mind that if you want the user name, you may want to change that from request.user to request.user.username.
I hope you resolved your issue, but in case you haven't, I had a similar issue which I was able to resolve by using "or None" when setting the form after checking if it is a POST (or GET) request.
In your case it looks like this may be a slightly different issue, but I wondered if this snippet might fix things up:
if request.method == "POST":
form = MyForm(request.POST or None)
# .. do stuff....
else: #.....this is a GET
data = {'user': request.user.username} #note this is changed to username
form = MyForm(data)
Not sure if still useful, but adding it here, as I just ran into this for my ChoiceField items within my form.
I was getting the same error messages, but eventually found out I had forgotten to ad 'or None' when initiating the form inside my view.
The initial code inside my view function that was displaying the error messages from the start:
form=FormName(request.POST)
I just added the 'or None' to it:
form=FormName(request.POST or None)
And all good after that.
Don't you need to do something like this
form = NameForm(request.POST)
Rather then attempting to use the user object to populate the form? Will the user object have an example_field_1 in it?
https://docs.djangoproject.com/en/1.8/topics/forms/
This is the normal behavior.
Some properties of fields are checked on client side. The error messages belong to the form, are part of the html but are not displayed until needed. It saves a client-server request.