My symptom is when I click the modify button and then I write down the information on new window that is implemented by bootstrap div part. However, my database doesn't change at all. Please ignore ... in codes, I delete attributes that looks messy. Codes can have typo, because I wrote it down manually to find a bug, but I didn't find.
I tried in view.py, address_modify makes return Httpresponse(street), but It returned None.
view.py
def address_modify(request, adid):
cat = get_object_or_404(Address, adid=adid)
if request.method == "POST":
old_adid = adid
email = request.user.email
street = request.POST.get("street", None)
city = request.POST.get("city", None)
...
Address.objects.filter(adid=adid).update(..., street=street, city=city, state=state, ...)
return redirect('/address/')
return redirect('/address/')
template ( I name it address.html)
<button class="btn btn-success" data-toggle="modal" data-target="#modify">MODIFY</button>
<div class ="model fade" id="modify" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<from action="" method="POST">{% csrf_token %}
</div>
<div class="modal-body">
<input type="text" name="street">
<input type="text" name="city">
...
...
<input type="text" name="zipcode">
</div>
<div class="modal-footer">
<a href="{% url 'address_modify' i.adid %}">{% csrf_token %}
<button type="button" class="btn btn-primary">Save Change</button></a>
<div></form>
urls.py
url(r'^address_modify/(?P<adid>[0-9]+)/$', MyAppView.address_modify, name='address_modify'),
In django the best practice is to create a forms.py file to handle forms, its really easy you can read the doumentation on it, basically the form will ensure that all your data are read.
That is not how you implement form and form submit. Your link is not submitting anything, it's just opening a link. This is the standard form syntax:
<form method="POST">
{% csrf_token %}
... your form input fields here ...
<input type="submit" value="Save changes">
</form>
You must submit the form. Note type="submit" there.
Next to that, Django has forms feature. Use it. Create forms.py as #Saumel-Omole suggested. Form for model Address would look like this:
class AddressForm(forms.ModelForm):
class Meta:
model = Address
fields = '__all__'
Then you modify your view to use the form like:
def address_modify(request, adid):
cat = get_object_or_404(Address, adid=adid)
form = AddressForm(instance=cat)
if request.method == 'POST':
form = AddressForm(request.POST, instance=cat)
if form.is_valid():
form.save()
return redirect('/address/')
else:
print(form.errors) # change to logging
return render(request, 'address.html', {'form': form})
Go over the official Django tutorial. These basics are all there. Maybe it is going to take you a day or two to get through it, but long-term that's going to be far less than guessing and googling around for days for basic stuff.
Related
Basically, I would like to get some advice about how to transition from a form page back to a previous page when the form is submitted.
There are other posts on similar situations but none seem to show how to implement this using a class-based view, so any advice here would be most appreciated.
So far I have come up with the approach below. Here, I am trying to pass a parameter holding the URL of the previous page, from the template for the previous page to urls.py and then onto the view. However, I don't think I am using the correct syntax in urls.py as the value of the previous_url parameter in the view is simply "previous_url".
Link in the template for the table page
Edit
URL
path('entry/<int:pk>/edit/', EntryUpdateView.as_view(previous_url="previous_url"), name='entry_update'),
View
class EntryUpdateView(LoginRequiredMixin, UpdateView):
model = Entry
template_name = 'entry_update.html'
fields = ('source', 'target', 'glossary', 'notes')
previous_url = ""
def form_valid(self, form):
obj = form.save(commit=False)
obj.updated_by = self.request.user
obj.save()
return HttpResponseRedirect(self.previous_url)
Update form
<form method="POST" novalidate>
{% csrf_token %}
<div class="mb-3">
{{ form.source|as_crispy_field }}
</div>
<div class="mb-3">
{{ form.target|as_crispy_field }}
</div>
<div class="mb-3">
{{ form.glossary|as_crispy_field }}
</div>
<div class="mb-3">
{{ form.notes|as_crispy_field }}
</div>
<div class="text-center mt-3">
<button type="submit" class="btn btn-outline-primary mx-2">Update</button>
</div>
</form>
Error
Page not found (404)
Request Method: GET
Request URL: http://localhost:8000/entry/5131/edit/previous_url
If this helps anyone, I was able to get the value of previous_url within form_valid() using self.request.GET.get('previous_url').
def form_valid(self, form):
obj = form.save(commit=False)
obj.updated_by = self.request.user
obj.save()
previous_url = self.request.GET.get('previous_url')
return HttpResponseRedirect(previous_url)
I am trying to add a subscribe to newsletter option on a django website. When a visitor enters
a valid email address it will be stored in the database. The subscription form is part of the base.html template.
All other templates of the website extend this template. I wish to implement this in a DRY way.
This is how I am trying to do it :
forms.py :
from dataclasses import fields
from django import forms
from . models import Subscribers, MailMessage
class SubcribersForm(forms.ModelForm):
class Meta:
model = Subscribers
fields = ['email', ]
views.py :
def base(request):
if request.method == 'POST':
form = SubcribersForm(request.POST)
if form.is_valid():
form.save()
return redirect('/')
else:
form = SubcribersForm()
context = {'form': form}
return render(request, 'base.html', context)
The template: base.html
<form method = "POST" class="signup-form form-inline justify-content-center pt-3">
{% csrf_token %}
<div class="form-group">
<label class="sr-only" for="semail">{{context}}</label>
<input type="email" id="semail" name="semail1" class="form-control mr-md-1 semail" placeholder="Enter email">
</div>
<button type="submit" class="btn btn-primary">Subscribe</button>
</form>
models.py :
class Subscribers(models.Model):
email = models.EmailField(null=True)
date = models.DateTimeField(auto_now_add=True)
def __str__self(self):
return self.email
In the backend, I can see that the Subscribers table has been created. However, when I enter any email address from the home
page and click subscribe button it does not store it in the database. What could be the issue here?
It could be that you have no action declared in your form. Assuming you have a url like this:
path('add-subscriber/', base, name='base'),
...your form would need a way to call it upon submit, like this:
<form method = "POST" action="{% url 'base' %}" class="signup-form form-inline justify-content-center pt-3">
{% csrf_token %}
<div class="form-group">
<label class="sr-only" for="semail">{{context}}</label>
<input type="email" id="semail" name="semail1" class="form-control mr-md-1 semail" placeholder="Enter email">
</div>
<button type="submit" class="btn btn-primary">Subscribe</button>
</form>
I am making a complaint management system where different users can log in and add complaints to the system. I need to make a page where the user can add complaints that will be saved in the admin panel but idk how to do it. I have created the model and the template but idk what else to add in the views or the forms. I've tried a bunch of different things but none seem to work. can someone please tell me how to do it?
Models.py:
class Complaints(models.Model):
user = models.ForeignKey(User, on_delete= models.CASCADE, null = True, blank=True)
title = models.CharField(max_length=300)
description = models.TextField(null=True, blank= True)
highpriority = models.BooleanField(default=False)
document = models.FileField(upload_to='static/documents')
def __str__(self):
return self.title
Template:
<div class="col-lg middle middle-complaint-con">
<i class="fas fa-folder-open fa-4x comp-folder-icon"></i>
<h1 class="all-comp">New Complaint</h1>
<form class="" action="" method="POST" enctype="multipart/form-data">
{% csrf_token %}
<input type="email" class="form-control col-lg-10 comp-title-field" placeholder="Complain title">
<p class="desc">Description</p>
<button type="button" class="btn btn-secondary preview-btn">Preview</button>
<textarea class="form-control comp-textarea" rows="7" placeholder="Enter text here"></textarea>
<button type="file" name="myfile" class="btn btn-secondary attach-btn"><i class="fas fa-file-upload"></i> Attachment</button>
<button type="submit" class="btn btn-secondary save-btn" value="submit"><i class="fas fa-save"></i> Save</button>
</form>
</div>
It needs to look like this:
Please help me with this... I've been at this the whole day and Idk what else to do so figured might as well just ask here.
This is not perfect but worked for me with very basic model form:
if request.method == 'POST':
form = ComplaintForm(request.POST or None)
if form.is_valid():
instance = form.save(commit=False)
instance.user = request.user
instance.save()
else:
form = ComplaintForm()
Also, you may need to authenticate the user with login_ decorator or is_authenticated method as well as validate the input data.
Some useful links:
Django Forms Validation
Render Django Form Manually
I'm trying to create a page where admins can upload some files using some FileField. The problem is that I can't manage to display any field from my form, I must be missing something important but I can't find out what, hope anyone can help me.
Here is the code related to this form:
urls.py
urlpatterns = patterns(
'',
url(r'^admin_fichiers_phyto/$', phyto_views.AdminFichiersPhyto.as_view(), name='phyto-admin-fichiers-phyto'),
)
phyto_admin_fichiers.html
{% block forms %}
{% if user.is_staff%}
<fieldset>
<div>
<span>{{ form.other }}</span>
</div>
</fieldset>
<p>
<input id="submit" class="btn btn-primary" type="submit" value="Synchronisation Autre" name="autre"/>
<input id="submit" class="btn btn-primary" type="submit" value="Synchronisation Traitements généraux" name="trtm_gen"/>
</p>
{% endif %}
{% endblock %}
views.py
class AdminFichiersPhyto(TemplateView):
template_name = 'phyto/phyto_admin_fichiers.html'
form_class = forms.PhytoFileForm
current_url = 'phyto-files'
context_object_name = 'phyto_files'
def post(self, request, *args, **kwargs):
if request.POST.get('autre'):
return HttpResponse('<h1>autre</h1>')
if request.POST.get('trtm_gen'):
return HttpResponse('<h1>Traitement Generaux</h1>')
forms.py
class PhytoFileForm(forms.Form):
class Meta:
model = models.PhytoFile
fields = ['general_treatment', 'other']
def __init__(self, *args, **kwargs):
super(PhytoFileForm, self).__init__(*args, **kwargs)
models.py
class PhytoFile(models.Model):
general_treatment = models.FileField(upload_to='fichiers_phyto/', blank=True, null=True)
other = models.FileField(upload_to='fichiers_phyto/', blank=True, null=True)
Here is what my webpage is showing :
https://imgur.com/a/yH0be0K
I can't understand why the Field isn't displayed, I really hope somebody have the knowledge to help me with my problem ! ^_^
Have a nice day ! :D
You have several major issues here.
TemplateView doesn't know anything about form_class (or context_object_name, for that matter). And by defining post like that you've avoided actually doing anything with the uploaded data. You need to use a view that deals with forms; in your case, a CreateView would be ideal. Inside that view, that response code needs to go in form_valid.
Secondly, PhytoFileForm needs to inherit from forms.ModelForm; a standard Form class doesn't know anything about models and doesn't use a Meta class. However, since you're not customizing the form beyond the field selection, you can just rely on the automatic form created by CreateView.
Next, your template is broken; it doesn't have an HTML form element. Also, since your form class has two fields but you only display one on the template, the form will never be valid.
So, putting it together:
class AdminFichiersPhyto(CreateView):
template_name = 'phyto/phyto_admin_fichiers.html'
model = models.PhytoFile
def form_valid(self, form):
form.save()
if request.POST.get('autre'):
return HttpResponse('<h1>autre</h1>')
if request.POST.get('trtm_gen'):
return HttpResponse('<h1>Traitement Generaux</h1>')
{% block forms %}
{% if user.is_staff%}
<form method="post" action="" enctype="multipart/form-data">
<fieldset>
<div>
<span>{{ form.other }}</span>
</div>
<div>
<span>{{ form. general_treatment }}</span>
</div>
</fieldset>
<p>
<input id="submit" class="btn btn-primary" type="submit" value="Synchronisation Autre" name="autre"/>
<input id="submit" class="btn btn-primary" type="submit" value="Synchronisation Traitements généraux" name="trtm_gen"/>
</p>
</form>
{% endif %}
{% endblock %}
I'm stuck on creating form, looks like {{ forms.as_p }}.
I need to login to website using this form. Uing forms.as_p it everything works perfectly, but I need to create my own customized form.
Problem is, that after reading lot's of website's and documentation I still can't understand, how to create custom form with my css class and input fields.
I tried this one:
action="", method ="post"
<div class="form-group">
<input type="text" class="form-control" placeholder="Username" required="">
</div>
<div class="form-group">
<input type="password" class="form-control" placeholder="Password" required="">
</div>
<input type="submit" class="btn btn-primary block full-width m-b" value="Log In" />
But it doesn't work.
What fields, I've missed.
Also I have another question: Is it possible to custom "next" variable to redirect after login on my custom page? And how I can do it?
Normally you use your forms.py to create a form that you can use in your HTML-Code via Jinja.
Your forms.py could look like this:
from django import forms
class ProfileForm(forms.Form):
name = forms.CharField(label='Your name', max_length=100)
age = forms.IntegerField(label='Your age')
Then you would do some cleaning to make sure the data passed to the form has the right format.
def clean_name(self):
name = self.cleaned_data.get('name')
if not name:
raise forms.ValidationError('You have to type in a name.')
return name
In your views.py:
def some_view(request):
form = ProfileForm(request.POST or None)
if form.is_valid():
name = form.cleaned_data.get('name')
//do something with the name
user = User.objects.get(username=username)
user.username = name
user.save()
return redirect('to_profile_of_user')
return render(request, 'change_profile.html', {'form':form})
Here it is very important that you pass the form to your template(HTML).
Your change_profile.html:
<form action="" method="POST" enctype="multipart/form-data">
{{form.as_p}} //That is the form you passed
<input type="submit" value="Change" />
</form>
I hope my answer gives you a little bit of advice. Now you have seen a complete roundtrip. Maybe you should have a closer look at the Django documentation. It is very helpful.
The code is written on the fly and not tested. But it is enough for an overview. You should not forget to import the things you need. I did not do that.