I want to create a alert message before submitting the page , my
form.py
class NameForm(forms.ModelForm):
translated_names = TranslationField()
class Meta:
fields = "__all__"
model = models.Name
admin py
class NameAdmin(MasterDataBaseAdmin):
form = forms.NameForm
inlines = [AddressInline, RegistrationTypeInline]
queryset = models.Name.objects.prefetch_related(
"names", "name__id", "registrationstype"
)
views.py
class NameViewSet(viewsets.ReadOnlyModelViewSet):
queryset = models.Country.objects.supported().prefetch_related("names",
"registrationstype")
serializer_class = serializers.NameSerializer
I want to just add this meesage in the Message Box
"Are You Sure You Want To Save The Page!"
Try this in your HTML
<input type="submit" onclick="return confirm('Are you sure?')" />
In your html you probably have something like that
<form action="/your-name/" method="post">
<label for="your_name">Your name: </label>
<input id="your_name" type="text" name="your_name" value="{{ current_name }}">
<input type="submit" onclick="return confirm('Are you sure?')" />
</form>
onclick="return confirm('Are you sure?')" here is your massage box
Related
It's my first time doing a Django Form challenge.
The challenge for now is just from a HTML Template get the last_name information and store into DB from views. So I have a scenario below:
models.py:
class Person(models.Model):
first_name = models.CharField(max_length=255)
last_name = models.CharField(max_length=255)
an HTML template, I will put below only the form part:
<form action="{% url 'store' %}" method="post">
{% csrf_token %}
<div class="form-group row">
<label for="last_name" class="col-sm-2 col-form-label">Last Name</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="last_name" placeholder="Last Name">
</div>
</div>
<div class="form-group row">
<div class="col-sm-10">
<button type="submit" class="btn btn-primary">Send Last Name</button>
</div>
</div>
</form>
And the views.py itself... I created a InsertLastName ModelForm to store the data from the form, but didn't work. For some reason, when I tryed to call form.cleaned_data I reveived an error about the is_valid() verification. Seens like that I'm not getting the information from label.
class InsertLastName(forms.ModelForm):
class Meta:
model = Person
fields = ['last_name']
exclude = ['first_name']
def index(request):
persons = Person.objects.all()
context = {'persons': persons}
return render(request, '/index.html', context)
def store(request):
form = InsertLastName(request.POST or None)
print(form.cleaned_data['last_name'])
return HttpResponse("Storing a new Last Name object into storage")
What is the correct way to get the information from last_name label in my form?
I'm following that documentation and coding from a challenge template.
Your just set attr name for your input html tag
Example:
<input type="text" name="first">
And for get input in function store in view.py:
request.POST.get("first")
Add this to your html template in your form
{{persons}}
So I have the following code:
# the view
class UpdateDateView(LoginRequiredMixin, UpdateView):
model = Date
form_class = DateForm
template_name = 'app/form/date_edit_form.html'
def save_photos(self, date) -> None:
photos = self.request.FILES.getlist('photo')
current_photos = self.request.FILES.getlist('custom-photo-name') # this is not working
for photo in photos:
Photo.objects.create(date=date, photo=photo)
def form_valid(self, form):
date = form.save()
self.save_photos(date)
return super().form_valid(form)
# the form
class DateForm(forms.ModelForm):
photo = forms.ImageField(required=False)
class Meta:
model = Date
exclude = ('user',)
# the Edit form
<form action="{% url 'app:edit-date' date.slug %}" method="post" enctype="multipart/form-data">{% csrf_token %}
<div class="form-container">
...
<tr>
<th><label for="id_photo">Image:</label></th>
<td>
<input type="file" name="photo" accept="image/*" id="id_photo" multiple>
</td>
</tr>
<div class="current-photos">
{% for photo in date.photos.all %}
<div class="photo-wrapper-{{ forloop.counter }}">
<img src="{{ photo.photo.url }}" width="200px"><a class="delete-photo" id="{{ forloop.counter }}">Delete</a>
<input type="file" name="custom-photo-name" value="{{ photo }}" class="hide" id="photo_{{ forloop.counter }}">
</div>
{% endfor %}
</div>
</div>
<div class="buttons">
<input type="submit" value="Save" class="create-button redirection no_decoration">
Back
</div>
</form>
# js (jquery)
$('.delete-photo').on('click', function() {
const id = $(this).attr('id');
const div_class = `.photo-wrapper-${id}`;
$(div_class).remove()
});
I have a CreateView and UpdateView. The ImageField is not required, it is optional.
Let's assume I have created a new date with photos. Then I wanted to edit its pictures (delete some and add some new). When I click on tag (Delete), the div wrapper for that photo is being removed. When I try to save my edits, I want to access 2 different lists with photos (ones which were added in the past, and the new photos).
This self.request.FILES.getlist('custom-photo-name') seems to do nothing with current photos. Please help, maybe my code logic is bad in general? What I am missing here? What html form looks for when I submit the form, whether for the tag or maybe name attribute? Huge thanks in advance!
I am making a simple personal website. I make a box to input user data (name, email, and message). I want this data is sent to my django admin. I have test it and it works in local. But when i deploy it, i didn't get any data whenever i submit from the box. Note : i do not use django form for some reason. I want to use my own custom form.
this is my views.py
from django.shortcuts import render
from django.http import HttpResponse
from .models import Feedback
from .forms import FeedbackForm
def index(request):
if (request.method == "POST"):
name = request.POST.get("Name")
email = request.POST.get("Email")
message = request.POST.get("Message")
record = Feedback(name=name, email=email, message=message)
record.save()
return render(request, 'main.html')
this is my models.py
from django.db import models
class Feedback(models.Model) :
name = models.CharField(max_length=50)
email = models.EmailField()
message = models.CharField(max_length=200)
def __str__(self):
return self.name
this is my html form
<form action="{% url 'index' %}" method="POST" target="_self">
{% csrf_token %}
<div class="w3-row-padding" style="margin:0 -16px 8px -16px">
<div class="w3-half">
<input class="w3-input w3-border" type="text" placeholder="Name" required name="Name" >
</div>
<div class="w3-half">
<input class="w3-input w3-border" type="email" placeholder="Email" required name="Email">
</div>
</div>
<input class="w3-input w3-border" type="text" placeholder="Message" required name="Message" >
<button class="w3-button w3-black w3-right w3-section" type="submit">
<i class="fa fa-paper-plane"></i> SEND MESSAGE
</button>
</form>
I'm not sure what platform you have deployed the project on, but one of the first things I would try is to make sure you have run database migration. (Which I'm assuming you have done if you have access to the admin area, but it might be worth running again just to make sure.)
python manage.py makemigrations
python manage.py migrate
I made some modifications to your HTML form to more closely follow the Django documentation. Notably, the addition of enctype="multipart/form-data" and an id tag to each input: i.e. id="name". Here is a link to the documentation: https://docs.djangoproject.com/en/3.1/topics/forms/
<form action="{% url 'index' %}" method="POST" enctype="multipart/form-data">
{% csrf_token %}
<div class="w3-row-padding" style="margin:0 -16px 8px -16px">
<div class="w3-half">
<input class="w3-input w3-border" type="text" placeholder="Name" name="Name" id="name" required>
</div>
<div class="w3-half">
<input class="w3-input w3-border" type="email" placeholder="Email" name="Email" id="email" required>
</div>
</div>
<input class="w3-input w3-border" type="text" placeholder="Message" name="Message" id="message" required>
<button class="w3-button w3-black w3-right w3-section" type="submit"><i class="fa fa-paper-plane"></i>SEND MESSAGE</button>
</form>
It could be an issue with copying/pasting code, but I noticed the fields on your model are over-indented. Make sure you are using a single tab before each field.
# models.py
class Feedback(models.Model):
name = models.CharField(max_length=50)
email = models.EmailField()
message = models.CharField(max_length=200)
def __str__(self):
return self.name
If you are able to see the terminal, are you getting a 200 response with your POST request? It should look something like this:
"POST / HTTP/1.1" 200
One of the other things I'd check is to ensure your database is configured properly in settings.py (This is assuming you are using the sqlite database)
# settings.py
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}
If you aren't seeing anything in the admin area, make sure you have registered your model in admin.py
from django.contrib import admin
from .models import Feedback
admin.site.register(Feedback)
I've 2 model First and Second with a FK from Second to First. I created a form for the 2 class and a inline formset for Second. On template I manually designed my form and with jQuery I'm able to add dynamic forms of Second.
On UpdateView the form is correctly populated, but when I submit the form, all Second instances are created again with new ids instead of updating them. I double checked that on HTML there are name=PREFIX-FORM_COUNT-id with correct ids, but seems that Django ignores it.
I'm using Django 2.2.12 & Python 3.6
Here what I made:
models.py
class First(models.Model):
name = models.CharField(max_length=100, null=False)
class Second(models.Model):
first= models.ForeignKey(First, null=False, on_delete=models.CASCADE)
number= models.FloatField(null=False, default=0)
form.py
class FirstForm(forms.ModelForm):
class Meta:
model = First
fields = "__all__"
class SecondForm(forms.ModelForm):
class Meta:
model = Second
fields = "__all__"
SecondsFormset = inlineformset_factory(First, Second, SecondForm)
view.py
class FirstUpdateView(UpdateView):
template_name = "first.html"
model = First
form_class = FirstForm
context_object_name = "first_obj"
def get_success_url(self):
return reverse(...)
def forms_valid(self, first, seconds):
try:
first.save()
seconds.save()
messages.success(self.request, "OK!")
except DatabaseError as err:
print(err)
messages.error(self.request, "Ooops!")
return HttpResponseRedirect(self.get_success_url())
def post(self, request, *args, **kwargs):
first_form = FirstForm(request.POST, instance=self.get_object())
second_forms = SecondsFormset(request.POST, instance=self.get_object(), prefix="second")
if first_form .is_valid() and second_forms.is_valid():
return self.forms_valid(first_form , second_forms)
...
.html (putted only essential tags)
<form method="post">
{% csrf_token %}
<input type="text" id="name" value="{{ first_obj.name }}" name="name" required>
<input type="hidden" name="second-TOTAL_FORMS" value="0" id="second-TOTAL_FORMS">
<input type="hidden" name="second-INITIAL_FORMS" value="0" id="second-INITIAL_FORMS">
<input type="hidden" name="second-MIN_NUM_FORMS" value="0" id="second-MIN_NUM_FORMS">
<div id="seconds_container">
{% for s in first_obj.second_set.all %}
<input type="hidden" name="second-{{forloop.counter0}}-id" value="{{s.pk}}">
<input type="hidden" name="second-{{forloop.counter0}}-first" value="{{first_obj.pk}}">
<input type="number" min="0" max="10" step="1" value="{{s.number}}" name="second-{{forloop.counter0}}-number" required>
{% endfor %}
</div>
<button class="btn btn-success" type="submit">Update</button>
</form>
I checked how Django creates forms and it will only add DELETE checkbox on it, but all other infos are correctly stored into the formset. When I do .save() it will create new Second element on db instead of change them.
What am I missing?
I solved this!
I setted TOTAL_FORMS and INITIAL_FORMS with wrong values. From Django's docs:
total_form_count returns the total number of forms in this formset. initial_form_count returns the number of forms in the formset that were pre-filled, and is also used to determine how many forms are required. You will probably never need to override either of these methods, so please be sure you understand what they do before doing so.
So the correct way to use it is:
In views:
Generate FormSets with extra=0
In HTML:
Set TOTAL_FORMS with number of rows you are POSTing and change it dinamically if dinamically add/remove rows;
Set INITIAL_FORMSwith number of alredy filled rows (editing/deleting) and never change this;
To delete a pre-filled row use DELETE checkbox instead of removing entire row;
For me i wanted to update my images, everything suggested here and every other forums about handling the hidden form didn't worked until i changed this.
product_img_form = ProductImageFormSet(data=request.FILES or None, instance=your_model_instance)
To this.
product_img_form = ProductImageFormSet(request.POST or None, request.FILES or None, instance=your_model_instance)
Then like magic this ugly error stopped showing, and my new image successfully got updated
<tr><td colspan="2">
<ul class="errorlist nonfield">
<li>(Hidden field TOTAL_FORMS) This field is required.</li>
<li>(Hidden field INITIAL_FORMS) This field is required.</li>
</ul>
<input type="hidden" name="product_images-TOTAL_FORMS" id="id_product_images-TOTAL_FORMS">
<input type="hidden" name="product_images-INITIAL_FORMS" id="id_product_images-INITIAL_FORMS">
<input type="hidden" name="product_images-MIN_NUM_FORMS" id="id_product_images-MIN_NUM_FORMS">
<input type="hidden" name="product_images-MAX_NUM_FORMS" id="id_product_images-MAX_NUM_FORMS">
</td></tr>
I am trying to validate fields, one visible filled by the user, and an other one: hidden for the user but filled by the template.
Here is my form:
class AForm(forms.Form):
xxxx = forms.CharField(max_length=30)
yyyy = forms.CharField(max_length=30,widget=forms.HiddenInput)
def clean(self):
xxxx=self.cleaned_data['xxxx']
yyyy=self.cleaned_data['yyyy'] ##ERROR
if function_check(xxxx,yyyy)==False:
raise forms.ValidationError("Try again!")
return xxxx
In my template I have:
<form method="post" action="">
{% csrf_token %}
{{form.xxxx}}
<input id="id_yyyy" name="yyyy" type="hidden" value='{{ code_generated_value }}' maxlength="30">
<input type="submit"/>
</form>
The only error I get is : 'yyyy' at the yyyy=self.cleaned_data['yyyy'] line.
I found this question: Hidden field in Django form not in cleaned_data
But it was not very helping.
EDIT 1: Generated HTML code
<p><input id="id_xxxx" maxlength="30" name="xxxx" type="text" /></p>
<input id="id_yyyy" maxlength="30" name="yyyy" type="hidden" value='97a8eee9477b73dda401b15369f8db00a0d6ab79.png'>
<input type="submit"/>
Always check generated HTML and POST data for request. You will see any fields missing & stuff. Also, use .get(field_name) method.
Check here for more. How to properly access cleaned_data from super, etc.