Django does not save the form (nothing happens) - python

\\models.py
class BasicSettings(models.Model):
user = models.OneToOneField(
settings.AUTH_USER_MODEL,
default=None,
null=True,
on_delete=models.CASCADE,
)
settings_description = models.BooleanField(default=False)
settings_photo = models.BooleanField(default=False)
settings_username = models.BooleanField(default=False)
settings_background = models.BooleanField(default=False)
\\views.py
try:
basic_settings = request.user.basicsettings
except BasicSettings.DoesNotExist:
basic_settings = BasicSettings(user=request.user)
if request.method == 'POST':
basicsettings_form = BasicSettingsForm(
request.POST, instance=basic_settings)
else:
basicsettings_form = BasicSettingsForm(instance=basic_settings)
return render(request, 'dashboard.html', {'basicsettings_form': basicsettings_form})
\\forms.py
class BasicSettingsForm(forms.ModelForm):
class Meta:
model = BasicSettings
fields = (
'settings_description',
'settings_photo',
'settings_username',
'settings_background',
)
widgets = {
'settings_description': forms.TextInput(attrs={'type': 'checkbox', 'class': 'checkbox', 'id': 'test1'}),
'settings_photo': forms.TextInput(attrs={'type': 'checkbox', 'class': 'checkbox', 'id': 'test2'}),
'settings_username': forms.TextInput(attrs={'type': 'checkbox', 'class': 'checkbox', 'id': 'test3'}),
'settings_background': forms.TextInput(attrs={'type': 'checkbox', 'class': 'checkbox', 'id': 'test4'}),
}
\.html
<form method="POST">
{% csrf_token %}
{{ basicsettings_form }}
<button type="submit">Dad9adbaiduaadtest</button>
When I click on the submit button, the page just refreshes but nothing happens. What might be the reason for this?
The code above is just a snippet. Maybe nothing happens because I have multiple forms in one view? The whole view looks like this https://pastebin.com/Bu5NLTX1 but I just wanted to give you the relevant part

This might be the problem..
From Creating forms from models:
Every ModelForm also has a save() method. This method creates and saves a database object from the data bound to the form. A subclass of ModelForm can accept an existing model instance as the keyword argument instance; if this is supplied, save() will update that instance. If it’s not supplied, save() will create a new instance of the specified model:
So maybe try:
basicsettings_form = BasicSettingsForm(
request.POST, instance=basic_settings)
if basicsettings_form.is_valid():
basicsettings_form.save()

Have you added action in your form action=your_action_url
<form action ="{% url 'your_url_name' %}" method="POST">
{% csrf_token %}
{{ basicsettings_form }}
<button type="submit">Dad9adbaiduaadtest</button>

Related

Why i get this value

I want to when i click on the user discharge button it will go to the page and the all user information take automatically. But i cannot get this value. Here is the image in the discharge button i click but its shows like this.
Here is my code : views.py
def discharge_view(request, pk):
form = DischargForm()
if request.method == 'POST':
form = DischargForm(request.POST)
if form.is_valid():
form.save()
messages.success(request, 'Successfull')
return redirect('discharge-patient')
context = {
'form': form,
}
return render(request, 'hospital/discharge.html', context)
forms.py :
class DischargForm(forms.ModelForm):
class Meta:
model = PatientDischarge
fields = ('assign_doctor', 'admitted', 'release_date', 'medicine_cost', 'other_charge')
widgets = {
'assign_doctor': forms.Select(attrs={'class': 'form-control'}),
'admitted': forms.Select(attrs={'class': 'form-control'}),
'release_date': forms.TextInput(attrs={'class': 'form-control'}),
'medicine_cost': forms.TextInput(attrs={'class': 'form-control'}),
'other_charge': forms.TextInput(attrs={'class': 'form-control'}),
}
models.py
class PatientDischarge(models.Model):
assign_doctor = models.ForeignKey(Doctor, on_delete=models.CASCADE)
admitted = models.ForeignKey(Admitted, on_delete=models.CASCADE)
release_date = models.DateField(auto_now_add=False)
medicine_cost = models.IntegerField(null=True)
other_charge = models.IntegerField()
def __str__(self):
return self.admitted.patient_name if all([self.admitted, self.admitted.patient_name]) else 0
def days_count(self):
return self.release_date - self.admitted.admited_date if all([self.admitted, self.admitted.admited_date]) else 0
def room_bill(self):
return self.days_count() * self.admitted.room_service if all([self.admitted, self.admitted.room_service]) else 0
def total_bill(self):
return self.room_bill().days + self.medicine_cost + self.other_charge
discharge.html
<form action="" method="POST" enctype="multipart/form-data">
{% csrf_token %}
{% for fields in form %}
<div class="form-group"></div>
{{ fields.label_tag }}
{{ fields }}
{% endfor %}
<br>
<input type="submit" value="Submit">
To pass an instance to the form you can do this form = DischargForm(instance=<DischargeInstance>) and the template will have pre-filled values in the form as per the instance.
Can you provide your models.py.

How to can I upload a form on django

I am trying to make a matchmaking project on python django such as snapchat's hoop, but first I am trying to do the easiest part(what I know) which is just making the user create a profile to find a mate and then show that created profile to the other users, currently I am not using any matchmaking based on questions, I need to first show the created user to other users. The error comes when I pass the variables to the html via for loops, and now the mates.html file doesnt show anything. Please if you need more explanation let me know in the comments.
models.py (Profile model show the profile of the user which is created by default wen the user is created and Mates model shows the profile that the user has to create which provide an image and a description)
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
bio = models.CharField(max_length=400, default=1, null=True)
class Mates(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="user")
users_requests = models.ManyToManyField(User, related_name="users_requests")
req_bio = models.CharField(max_length=400)
req_image = models.ImageField(upload_to='requestmates_pics', null=True, blank=True, default=False)
views.py
def matesmain(request):
contents = Mates.objects.all()
args123 = {
'contents': contents,
}
return render(request, 'mates.html', args123)
def mates(request):
if request.method == 'POST':
form_mates = MatesForm(request.POST, request.FILES)
if form_mates.is_valid():
instance = form_mates.save(commit=False)
instance.user = request.user
instance.save()
return redirect('mates-main')
print('succesfully uploded')
else:
form_mates = MatesForm()
print('didnt upload')
return render(request, 'mates.html', {'form_mates': form_mates})
forms.py
class MatesForm(forms.ModelForm):
class Meta:
model = Mates
fields = ('req_bio', 'req_image',)
urls.py
urlpatterns = [
path('mates', views.mates, name='mates'),
path('mates-main', views.matesmain, name='mates-main'),
]
mates.html
<div class="mates">
<div class="mates-container">
{% for content in contents %}
<div class="mates-item">{{ content.user }}
</div>
{% endfor %}
<div class="mates-item">content(picture)
<form action="{% url 'mates' %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form_mates.as_p }}
</form>
</div>
</div>
</div>
If you are displaying the form with the second function (mates), then you aren't sending any context for your fields to iterate over. Try like so:
def mates(request):
if request.method == 'POST':
form_mates = MatesForm(request.POST, request.FILES)
if form_mates.is_valid():
instance = form_mates.save(commit=False)
instance.user = request.user
instance.save()
return redirect('mates-main')
print('succesfully uploded')
else:
form_mates = MatesForm()
print('didnt upload')
context = {
'form_mates': form_mates,
'contents': Mates.objects.all()
}
return render(request, 'mates.html', context)
and in your other view (matesmain):
contents = Mates.objects.all()
args123 = {
'contents': contents,
'form_mates': MatesForm()
}
return render(request, 'mates.html', args123)
I'm not sure I understand, however, why you have two separate views for this.

Unable to display my CreateForm in Django

I have created a form and a view in Django and I'm trying to display it in the HTML but it isn't loading anything and I don't know why.
alumno2.html
{% block header %}
<header class="masthead bg-white text-dark text-uppercase">
<div class="container">
<h3 class="text-center">Añadir alumno</h3>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button class="btn btn-secondary" type="submit">Guardar</button>
</form>
</div>
</header>
{% endblock %}
form.py
class AlumnoForm2(forms.ModelForm):
class Meta:
model = Alumno
#fields = ['dni', 'nombre', 'apellido1', 'apellido2','email','repetidor']
fields = ['dni', 'nombre', 'apellido1', 'apellido2','email','repetidor','curs']
labels = {
'dni': 'dni',
'nombre': 'nombre',
'apellido1': 'Primer Apellido',
'apellido2': 'Segundo Apellido',
'email': 'Email',
'repetidor': 'repetidor',
'curs': 'curs'
}
widgets = {
'dni': forms.TextInput(attrs={'class': 'form-control'}),
'nombre': forms.TextInput(attrs={'class': 'form-control'}),
'apellido1': forms.TextInput(attrs={'class': 'form-control'}),
'apellido2': forms.TextInput(attrs={'class': 'form-control'}),
'email': forms.TextInput(attrs={'class': 'form-control'}),
'repetidor': forms.CheckboxInput(attrs={'class':'form-control-checkbox','id': 'repetidor'}),
'curs':forms.Select(attrs={'class': 'form-control'}),
}
view.py
class crea_alumno(CreateView):
model = Alumno
form_class = AlumnoForm2
template_name = '/alumno2.html'
success_url = reverse_lazy('mostrar_alumnos')
url.py
url(r'^alumno2/$', crea_alumno.as_view(),name='alumno2'),
models.py
class Alumno(models.Model):
dni = models.CharField(max_length=9,primary_key=True)
nombre = models.CharField(max_length=100)
apellido1 = models.CharField('Primer apellido',max_length=50)
apellido2 = models.CharField('Segundo apellido',max_length=50)
email = models.EmailField("Correo electronico",null=True)
repetidor = models.BooleanField()
curs = models.ManyToManyField(Curso, blank=True, related_name="Historico_de_cursos")
Nivel = models.ManyToManyField('Nivel', through = 'Completado',through_fields=('Alumno','Nivel'))
Practica = models.ManyToManyField('Practica', through = 'Nota',through_fields=('Alumno','Practica'))
Curso = models.ManyToManyField('Curso',through = 'Curso_alumno',through_fields=('Alumno','Curso'))
def __str__(self):
return self.dni
the html only display the save button, is not loading the create form. The html is inside the template folders thats why I have this urls.
EDIT:
I have removed the template I had also
url(r'^alumno2/$', TemplateView.as_view(template_name='alumno2.html'),name='alumno2'),
and I'm not sure if i need to put this in the url.py so now I only have the view and is unable to find my template withouth that
Remove the line
url(r'^alumno2/$', TemplateView.as_view(template_name='alumno2.html'),name='alumno2'),
from your urls.py and only keep this one:
url(r'^alumno2/$', crea_alumno.as_view(),name='alumno2'),
And inside your view, remove the / in the template name: instead of
template_name = '/alumno2.html'
Use
template_name = 'alumno2.html'
And replace CreateView with FormView as per the documentation

Creating a form out of relation based key, values in django

I have a django based application where I want to create a form out of key, value pairs from a model. The `Child' model consists of the following rows of data:
(<parent 1>, 'component 1', 'dummy content 1'),
(<parent 1>, 'component 2', 'dummy content 2'),
Here is are my models:
# models.py
class Parent(models.Model):
class Meta:
verbose_name = 'Parent'
db_table = "parent"
title = models.CharField(max_length=28)
def __str__(self):
return self.title
class Child(models.Model):
class Meta:
verbose_name = 'Child'
db_table = "child"
parent = models.ForeignKey(Parent, on_delete=models.CASCADE)
key = models.CharField(max_length=20)
value = models.TextField()
def __str__(self):
return self.parent
Following is the direct model to form mapping I am currently using for my other forms to keep it straight forward and simple
# forms.py
class MyForm(ModelForm):
class Meta:
model = Child
fields = () # fields go here
Then I pass this form to my view. The view page_view takes pk of the parent, gets the parent and passes it to the form. The form is then passed on to the template parent_view.html via the view.
# views.py
#login_required
def page_view(request, parent_pk):
parent = get_object_or_404(Parent, pk=pk)
my_form = MyForm(request.POST, instance=parent)
return render(request, 'parent_view.html', {
'parent': parent,
'my_form': my_form,
})
In the template I render the form like this:
<!-- page_view.html -->
{{ my_form }}
However, I would also like to write the html for this manually to add any design changes locally. I would like the forms.py MyForm to construct a form from the model by collecting key, value pairs for the provided parent.
So it should render it like this:
<form action=''>
<label for='component_1'>component 1</label>
<textarea name='component_1' type='text'>dummy content 1</textarea>
<label for='component_2'>component 2</label>
<textarea name='component_2' type='text'>dummy content 2</textarea>
</form>
But I can't seem to get my head around how to handle that in the `MyForm'. I have looked around a couple of solutions over stackoverflow but none of them point me in the right direction for this problem. If anyone has any ideas I would highly appreciate. Thanks in advance.
If there are multiple Child instances, then a single form will not be of much use, you will have to use a formset (a model formset to be precise).
As per the docs,
A formset is a layer of abstraction to work with multiple forms on the same page
# forms.py
# You can provide a text area widget for the field that you want to be displayed as a text area
class MyForm(ModelForm):
class Meta:
model = Child
fields = () # fields go here
widgets = {
'field_name': forms.Textarea(attrs={'cols': 80, 'rows': 3}),
}
ChildFormset = forms.modelformset_factory(Child, ChildForm, exclude=[], extra=0)
Then in your views, you can pass a queryset of all the objects that you want in your form
# views.py
from .forms import ChildFormset
#login_required
def page_view(request, parent_pk):
parent = get_object_or_404(Parent, pk=pk)
child_queryset = parent.child_set.all()
if request.method == 'GET':
child_formset = ChildFormset(queryset=child_queryset)
return render(request, 'parent_view.html', {
'parent': parent,
'my_formset': child_formset,
})
else:
child_formset = ChildFormset(request.POST, queryset=child_queryset)
if child_formset.is_valid():
for form in child_formset:
form.save()
# ... Do whatever else you want to do with the data
In your templates, you will then have to traverse through all the form objects in the formset. Then you can display them in whatever way you want to.
# parent_view.html
{{ child_formset.management_form }}
{% for form in child_formset %}
<div class="hidden">{{ form.id }}</div>
{% for field in form.visible_fields %}
{{ field }}
{% endfor %}
{% endfor %}
NOTE: The Foreign Key field will be displayed as a drop down for the user to select a parent object from the list of parent objects.

Django UpdateView - no object due to POST call

I have two UpdateViews, one works and the other doesn't... Please see Update IV
The working model is:
views.py
class JuryUpdate(UpdateView):
model = Jury
fields = [
'jury_name',
]
template_name_suffix = '_update_form'
def get_object(self, *args, **kwargs):
return get_object_or_404(Jury, jury_id=self.kwargs['jr'])
def form_valid(self, form):
form.instance.customer_id = self.kwargs['pk']
form.instance.court_year = self.kwargs['yr']
form.instance.jury_id = self.kwargs['jr']
return super(JuryUpdate, self).form_valid(form)
templates/jury_update_form.html (in relevant part)
<div class="container">
<h5>Update {{for.instance.jury_name}}</h5>
<form method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Save" />
</form>
</div>
This setup will render an updateview with the object labels and existing field data from the object. This next setup doesn't work...
views.py
class CustomerUpdate(UpdateView):
model = Customer
fields = [
'customer',
]
template_name_suffix = '_update_form'
def get_object(self, *args, **kwargs):
return get_object_or_404(Customer, customer_id=self.kwargs['pk'])
def form_valid(self, form):
form.instance.customer_id = self.kwargs['pk']
return super(CustomerUpdate, self).form_valid(form)
templates/customer_update_form.html (in relevant part)
<div class="container">
<h5>Update {{form.instance.customer}}</h5>
<form method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Save" />
</form>
</div>
The second updateview does provide an update form but it doesn't populate with the calling object's data. It would seem that the object is there since the {{form.instance.customer}} contains the correct customer data for the call (no different than the JuryUpdate view).
I've tried to explicitly call get_initial (as described here) and print, but the result is {}. I've also tried variation of the form_valid call but as presented above, I believe I'm getting the correct object. There are several examples (such as here) that use get_initial to pre-populate with existing information - but that doesn't work in this instance and it isn't needed in my JuryUpdate view.
Any help is appreciated.
UPDATE I
models.py
class Customer(models.Model):
class Meta:
verbose_name = "Customer"
verbose_name_plural = "Customers"
customer_id = models.AutoField(
primary_key=True)
customer = models.CharField(
max_length=40)
# table fields
def get_absolute_url(self):
return reverse(
'customer-detail-view',
kwargs={'pk':self.pk})
def __str__(self):
return self.customer
class Jury(models.Model):
class Meta:
verbose_name = "Jury"
verbose_name_plural = "Juries"
customer = models.ForeignKey(
Customer,
on_delete=models.CASCADE)
court_year = models.ForeignKey(
CourtYear,
on_delete=models.CASCADE)
jury_id = models.AutoField(
primary_key=True)
jury_name = models.CharField(
max_length=20)
# other table fields
def get_absolute_url(self):
return reverse(
'jury-list-view',
kwargs={'pk':self.customer_id, 'yr':self.court_year_id})
def __str__(self):
return self.jury_name
urls.py
path('add_customer/', views.CustomerCreate.as_view(), name='customer-add'),
path('<int:pk>/', views.CustomerDetailView.as_view(), name='customer-detail-view'),
path('<int:pk>/delete/', views.CustomerDelete.as_view(), name='customer-delete'),
path('<int:pk>/update/', views.CustomerUpdate.as_view(), name='customer-update'),
path('<int:pk>/<int:yr>/', views.JuryListView.as_view(), name='jury-list-view'),
path('<int:pk>/<int:yr>/add_jury/', views.JuryCreate.as_view(), name='jury-add'),
path('<int:pk>/<int:yr>/<int:jr>/updatejury', views.JuryUpdate.as_view(), name='jury-update'),
path('<int:pk>/<int:yr>/<int:jr>/deletejury', views.JuryDelete.as_view(), name='jury-delete'),
UPDATE II
I've added a get_initial() method to my CustomerUpdate(UpdateView) as follows:
def get_initial(self):
initial = super(CustomerUpdate, self).get_initial()
print('initial data', initial)
customer_object = self.get_object()
initial['customer'] = customer_object.customer
# other fields omitted...
print('initial data updated', initial)
return initial
The initial data print returns {}. The initial data updated print returns {'customer': 'John Doe'} (plus the "other fields"). So it seems that the right information is getting pulled and delivered - It must be in the html?
Update III
I've taken the CustomerUpdate(UpdateView) down to the very basic class model:
class CustomerUpdate(UpdateView):
model = Customer
fields = [
'customer',
]
template_name_suffix = '_update_form'
The template is already the basic format (docs) - the rendered webpage still doesn't have object data for updating...
Update IV
I think I've figured out the problem - but don't know how to fix...
When I use the JuryUpdate call the console shows:
[02/Jun/2018 16:19:19] "GET /myapp/1/3/9/updatejury/?csrfmiddlewaretoken=1kHK4xgqdbBfXsv6mtz0WKgKpewFwLVtpUX5Z51qnLsGaMDVmpdVHKslXAXPhvY8 HTTP/1.1" 200 3687
When I use the CustomerUpdate call the console shows:
[02/Jun/2018 16:18:57] "POST /myapp/5/update/ HTTP/1.1" 200 3354
So my updateview on the Jury update is a GET call while my udpateview on Customer is aPOST call. In looking through the docs, I can see that the GET call with show the data while the POST call is (I think) assuming a black data set. I can't figure out why I'm getting a different result - where would this be set/changed?
After 3 days - I traced the issue - it had nothing to do with the view, model, url or the update template. The offending code was actually attached to the update button. Very specifically the page that had the button for "Update" used the following <form> code:
<form action="{% url 'customer-update' pk=customer.client_id %}" method="post" style="display: inline;">
{% csrf_token %}
<button type="submit" class="btn btn-outline-primary btn-custom-xs">U</button>
</form>
In the form call the method used was "POST" - and although I don't exactly understand the intracacies, the result is a blank UpdateView. The following code in the calling page fixed the problem.
<form action="{% url 'customer-update' pk=customer.client_id %}" style="display: inline;">
{% csrf_token %}
<button type="submit" class="btn btn-outline-primary btn-custom-xs">U</button>
</form>

Categories