Not able to save data using Django form - python

I stack. I try many thinks. I want to put 2 forms in my mainpage. Models, forms in index.html, ModelForm, save(), urls.. I think everything ok. But submit button do nothing.
#models.py
from django.db import models
class Iletisim(models.Model):
DURUM = [
('KT', 'Keşif Talebi'),
('AB', 'Arıza Bildirimi'),
('IL', 'İletişimden'),
]
SINIF = [
('Konut', (
('SI', 'Site '),
('DA', 'Apartman Dairesi'),
('VI', 'Yazlık/Bağ/Villa'),
)
),
('İşyeri', (
('OF', 'Ofis/Büro/Dükkan'),
('FA', 'Fabrika/Şantiye/Otel/Okul'),
)
),
('DG', 'Diğer'),
]
name = models.CharField(max_length=100, verbose_name="Ad/Soyad")
phone = models.CharField(max_length=100, verbose_name="Telefon")
address = models.CharField(max_length=250, verbose_name="Adresi")
message = models.CharField(max_length=1000, verbose_name="Mesaj")
email = models.EmailField(max_length=40, verbose_name="E-Posta")
province= models.CharField(max_length=40,verbose_name="Şehir")
tarih = models.DateTimeField(default=None)
basvuru = models.CharField(max_length=2, choices=DURUM)
sinif = models.CharField(max_length=2, choices=SINIF)
class Meta:
ordering = ["tarih", "email"]
verbose_name = "Mesaj"
verbose_name_plural = "Mesajlar"
def __str__(self):
return self.basvuru
My forms folder
from django.shortcuts import redirect, render
from django.forms import ModelForm
from apps.giris.models import Iletisim
class Kesif_Form(ModelForm):
class Meta:
model = Iletisim
fields = '__all__'
def kesif_kayit(request):
if request.method=='POST':
form = Kesif_Form(request.POST)
if form.is_valid():
yeni_kesif = Iletisim()
yeni_kesif.name = request.POST.get("name")
yeni_kesif.phone = request.POST.get("phone")
yeni_kesif.address = request.POST.get("address")
yeni_kesif.message = request.POST.get("message")
yeni_kesif.email = request.POST.get("email")
yeni_kesif.province = request.POST.get("province")
yeni_kesif.tarih = request.POST.get("tarih")
yeni_kesif.basvuru = request.POST.get("basvuru")
yeni_kesif.sinif = request.POST.get("sinif")
yeni_kesif.save()
return redirect('index')
else:
form = Kesif_Form()
context={'form' : form}
return render(request,'index.html',context)
Main class
...
from forms.formlar import Kesif_Form
class Anasayfa_View(TemplateView, Kesif_Form):
template_name = 'index.html'
def get_context_data(self, **kwargs):
...
context['kform'] = Kesif_Form
...
return context
index.html
...
{{ kform.errors }}
<form action="{% url 'kesif' %}" method="POST" class="php-email-form php-email-form animate__animated animate__fadeInRight">
{{ kform.errors }}
{{ kform }}
<input type="submit" value="gir">
</form>
...
urls.py
...
from forms.formlar import kesif_kayit
urlpatterns = [
path('admin/', admin.site.urls),
path('', Anasayfa_View.as_view(), name='grsndx'),
path('kesif/', kesif_kayit, name='kesif'),
path('<str:ktgr>/', Detaylar_View.as_view(), name='dtyndx'),
path('<str:ktgr>/<str:bslk>/', Detay_View.as_view(), name='dtydty'),
]
and submit not work, every fields in form, I want 2 forms but I have not work anyone.
help..
structure
-project
-apps
-giris
-models.py
+detay
...
+env
-fls
-settings
-urls
-forms
-formlar.py
...
-templates
-index.html
...
-manage.py
...

If you are using Django model form than you have to do something like this first create form class
class Kesif_Form(ModelForm):
class Meta:
model = Iletisim
fields = '__all__'#here you to defined specific you field or all the field
than you have to submit it like this
def kesif_kayit(request):
if request.method=='POST':
form = Kesif_Form(request.POST)
if form.is_valid():
form.save()
return redirect('index')
else:
form = Kesif_Form()
context={'form' : form}
return render(request,'index.html',context)
you don't have save it manually Django Model Form will save it for you.

Related

Django AssertionError when testing Create View

I'm running some tests for my app 'ads', but when I try to test the CreateView it fails with the following message:
AssertionError: 'just a test' != 'New title'
Here's the test:
class AdTests(TestCase):
def setUp(self):
self.user = get_user_model().objects.create_user(
username='test_user',
email='test#email.com',
password='secret'
)
self.ad = Ad.objects.create(
title='just a test',
text='Ehy',
owner=self.user
)
def test_ad_create_view(self):
response = self.client.post(reverse('ads:ad_create'), {
'title': 'New title',
'text': 'New text',
'owner': self.user.id,
})
self.assertEqual(response.status_code, 302)
self.assertEqual(Ad.objects.last().title, 'New title')
self.assertEqual(Ad.objects.last().text, 'New text')
So it could be that the test fails in creating a new ad, and then it compares the fields with the first ad in the setUp method.
I upload the rest of the code if it can help:
urls.py
from django.urls import path, reverse_lazy
from . import views
app_name='ads'
urlpatterns = [
path('', views.AdListView.as_view(), name='all'),
path('ad/<int:pk>', views.AdDetailView.as_view(), name='ad_detail'),
path('ad/create',
views.AdCreateView.as_view(success_url=reverse_lazy('ads:all')), name='ad_create'),
...
]
models.py
class Ad(models.Model) :
title = models.CharField(
max_length=200,
validators=[MinLengthValidator(2, "Title must be greater than 2 characters")]
)
price = models.DecimalField(max_digits=7, decimal_places=2, null=True)
text = models.TextField()
"""We use AUTH_USER_MODEL (which has a default value if it is not specified in settings.py) to create a Foreign Key relationship between the Ad model
and a django built-in User model"""
owner = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
comments = models.ManyToManyField(settings.AUTH_USER_MODEL, through='Comment', related_name='comments_owned')
picture = models.BinaryField(null=True, editable=True)
tags = TaggableManager(blank=True)
content_type = models.CharField(max_length=256, null=True, help_text='The MIMEType of the file')
favorites = models.ManyToManyField(settings.AUTH_USER_MODEL, through='Fav', related_name='favorite_ads')
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
views.py
class AdCreateView(LoginRequiredMixin, View):
template_name = 'ads/ad_form.html'
success_url = reverse_lazy('ads:all')
def get(self, request, pk=None):
form = CreateForm()
ctx = {'form': form}
return render(request, self.template_name, ctx)
# Pull data
def post(self, request, pk=None):
form = CreateForm(request.POST, request.FILES or None)
if not form.is_valid():
ctx = {'form': form}
return render(request, self.template_name, ctx)
pic = form.save(commit=False)
pic.owner = self.request.user
pic.save()
form.save_m2m()
return redirect(self.success_url)
forms.py (the view uses it especially to check and save the image)
class CreateForm(forms.ModelForm):
max_upload_limit = 2 * 1024 * 1024
max_upload_limit_text = naturalsize(max_upload_limit)
# Call this 'picture' so it gets copied from the form to the in-memory model
# It will not be the "bytes", it will be the "InMemoryUploadedFile"
# because we need to pull out things like content_type
picture = forms.FileField(required=False, label='File to Upload <= ' + max_upload_limit_text)
upload_field_name = 'picture'
class Meta:
model = Ad
fields = ['title', 'text', 'price', 'picture', 'tags']
# Check if the size of the picture is less than the one specified (see above).
def clean(self):
cleaned_data = super().clean()
pic = cleaned_data.get('picture')
if pic is None:
return
if len(pic) > self.max_upload_limit:
self.add_error('picture', "File must be < " + self.max_upload_limit_text + " bytes")
# Convert uploaded File object to a picture
def save(self, commit=True):
instance = super(CreateForm, self).save(commit=False)
# We only need to adjust picture if it is a freshly uploaded file
f = instance.picture # Make a copy
if isinstance(f, InMemoryUploadedFile): # Extract data from the form to the model
bytearr = f.read()
instance.content_type = f.content_type
instance.picture = bytearr # Overwrite with the actual image data
if commit:
instance.save()
self.save_m2m()
return instance
I hope it is useful, thanks in advance!
According to Django Doc
Create View:
A view that displays a form for creating an object, redisplaying the form with validation errors (if there are any) and saving the object.
This is not a Valid way to do create View based on my experience. Check the doc Doc here.
if i understand what you are talking about You want to submit Ad Model using Create View, if you want to submit it in form You can something like this:
from django.views.generic import CreateView
from django.contrib.auth.mixins import LoginRequiredMixin
from django.urls import reverse_lazy,
class PostCreativeView(LoginRequiredMixin, CreateView):
model = #Your Model
fields = [#Fields of the model You want to submit]
template_name = #html template you want to submit the form
success_url = reverse_lazy(#url for redirected user when the form is submitted)
def form_valid(self, form):
form.instance.user = self.request.user
return super (PostCreativeView, self).form_valid(form)
in the form template you can add:
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Save">
</form>
for styling you can follow this: Answer

ModelFormset in Django CreateView

I'm still new to Django & I would like to know how can allow user to add more than 1 ReferrerMember on Registration form as I wanted to achieve similar to the image url below
https://imgur.com/a/2HJug5G
I applied modelformset but so far it's giving me an error where "membership_id" violates not-null constraint the moment I submitted the form.
I've searched almost everywhere to find how to implement this properly especially on class-based view instead of function based view but still no luck. If possible please help me point out on any mistakes I did or any useful resources I can refer to
models.py
class RegisterMember(models.Model):
name = models.CharField(max_length=128)
email = models.EmailField()
class ReferrerMember(models.Model):
contact_name = models.CharField(max_length=100)
company_name = models.CharField(max_length=100)
membership = models.ForeignKey(RegisterMember, on_delete=models.CASCADE)
forms.py
class RegisterMemberForm(ModelForm):
class Meta:
model = RegisterMember
fields = ['name', 'email', ]
class ReferrerForm(ModelForm):
class Meta:
model = ReferrerMember
fields = ['contact_name ', 'company_name ', ]
ReferrerMemberFormset = modelformset_factory(ReferrerMember, form=RegisterMemberForm, fields=['contact_name ', 'company_name ', ], max_num=2, validate_max=True, extra=2)
views.py
class RegisterMemberView(CreateView):
form_class = RegisterMemberForm
template_name = 'register.html'
def post(self, request, *args, **kwargs):
member_formset = ReferrerMemberFormset (request.POST, queryset=ReferrerMember.objects.none())
if member_formset .is_valid():
return self.form_valid(member_formset )
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['member_formset'] = ReferrerMember(queryset=ReferrerMember.objects.none())
return context
register.html
<form method="post">
{% csrf_token %}
{{form.as_p}}
{{member_formset.as_p}}
<input type="submit">
</form>

Choices in django form

in my form i want to select department from 2 options: some object(every time only one) and None.
my form.py
class TeamGoalForm(ModelForm):
def __init__(self, *args, **kwargs):
employees = kwargs.pop('employees')
department = kwargs.pop('department')
super().__init__(*args, **kwargs)
self.fields['employees'].queryset = employees
self.fields['department'].choices = [(1, department), (2, None)]
self.fields['department'].initial = [1]
class Meta:
model = TeamGoal
fields = ('team_goal_title','department','employees', 'team_goal_description', 'gpd_year','team_factor_0','team_factor_1','team_factor_2','team_factor_3','team_factor_weight')
widgets = {
'team_goal_title': forms.TextInput (attrs={'class':'form-control', 'placeholder':'Enter the title of goal'}),
'department': forms.Select (attrs={'class': 'form-control', 'placeholder':'Select department'}), }
in my view.py I have had:
if request.method == 'POST':
form = TeamGoalForm(request.POST, employees=employees, department=department)
if form.is_valid():
form.save()
Here my department is an object.
How to implement something like this, 'cos my solution does't work?
You are not showing much of the code, but here is more or less how the different files should look like, hope this helps:
**#models.py**
from django.db import models
class department(models.Model):
# department fields
pass
class TeamGoal(models.Models):
...
deparment = models.ForeignKey(department, on_delete=models.CASCADE)
...
**#forms.py**
from django.forms import ModelForm
from django import forms
class TeamGoalForm(ModelForm):
class Meta:
model = TeamGoal
fields = (
'team_goal_title',
'department',
'employees',
'team_goal_description',
'gpd_year',
'team_factor_0',
'team_factor_1',
'team_factor_2',
'team_factor_3',
'team_factor_weight'
)
deparments = deparment.objects.all()
widgets = {
'deparments': forms.Select(choices=deparments,
attrs={
'class': 'form-control',
'placeholder':'Select department'
})
**#views.py**
from .forms import TeamGoalForm
def AddTeamGoalForm(request):
context = {
'TeamGoalForm': TeamGoalForm,
}
if request.method == 'POST':
addTeamGoalForm = TeamGoalForm(request.POST)
if addTeamGoalForm.is_valid():
newTeamGoalForm = addTeamGoalForm.save()
return redirect('/')
else:
return render(request, '/TeamGoalForm.html', context)
**# TeamGoalForm.html**
<form method="POST">
{% csrf_token %}
{{ TeamGoalForm}}
<button type="submit" class="btn btn-primary">Submit</button>
</form>
NOTE: you may need to adjust it based on the code you've already writen, but hopefully this leads close to a solution.

Django form is valid() returns false

I am trying to do multiple file uploads in Django but am encountering some errors: form.is_valid() returning false. <br>
I have tried printing form.erorrs and it gives me the following:
<ul class="errorlist"><li>uploaded_images<ul class="errorlist"><li>“b'\xbd\x06D\xcd3\x91\x85,\xdf\xa5K\n'” is not a valid value.</li></ul></li></ul>
I am not sure how to interpret this general error. Been searching for quite some time but couldn't find an answer.
Edit:
Im also encountering a "This field is required." error
Perhaps this screenshot may help with debugging:
I must be missing something simple but I just can't find it!!
Another pair of eyes to help me sieve through would be very appreciated!
views.py
from django.shortcuts import render,redirect
from django.views.generic.edit import FormView
from .forms import BRForm
from .models import *
class BRHomeView(FormView):
form_class = BRForm
model = TargetImage
template_name = 'br/br-home.html'
context_object_name = 'bankrecon'
def get(self, request):
form = BRForm(request.POST, request.FILES)
return render(request, self.template_name, {'form': form, 'title': 'Bank Reconcilation'})
def post(self, request, *args, **kwargs):
form_class = self.get_form_class()
form = self.get_form(form_class)
files = request.FILES.getlist('uploaded_images')
print("POST")
print(request.POST)
print("FILES")
print(request.FILES)
print(form.errors)
if form.is_valid():
form.save()
return redirect('br-home')
models.py
from django.db import models
# Create your models here.
class UploadedImages(models.Model):
image_files = models.ImageField(null=True, blank=True, upload_to='images/')
class TargetImage(models.Model):
invoice_date = models.DateTimeField()
recon_date = models.DateTimeField()
uploaded_images = models.ManyToManyField(UploadedImages)
def __str__(self):
return self.invoice_date
forms.py
from django import forms
from django.core.validators import FileExtensionValidator
from .models import *
class BRForm(forms.ModelForm):
class Meta:
model = TargetImage
fields = ('invoice_date', 'recon_date', 'uploaded_images')
widgets = {
'invoice_date': forms.DateInput(attrs={'type': 'date'}),
'recon_date': forms.DateInput(attrs={'type': 'date'}),
'uploaded_images': forms.ClearableFileInput(attrs={'multiple': True, 'accept':'.jpeg, .png, .jpg'}),
}
relevant template code:
<div class="mt-5 d-flex justify-content-center">
<form action="" enctype="multipart/form-data" method="POST">
{% csrf_token %}
{{ form.as_p }}
<div class="d-flex justify-content-center">
<button class="btn btn-success mt-3" type="submit">Submit</button>
</div>
</form>
</div>
Extra info: My request.POST and request.FILES seems to be working fine:
POST
<QueryDict: {'csrfmiddlewaretoken': ['hiding this'], 'invoice_date': ['2021-02-01'], 'recon_date': ['2021-02-01']}>
FILES
<MultiValueDict: {'uploaded_images': [<InMemoryUploadedFile: first_slide (1).jpg (image/jpeg)>, <InMemoryUploadedFile: fourth_slide (1).jpg (image/jpeg)>]}>
Thank you all!!
Some errors that I see in your code:
You're trying to render a POST request in your get method.
You're not passing any data from POST request to your form instance. That's why is_valid() is returning False.
Change your code to something like this and see if it works:
...
def get(self, request):
form = BRForm()
return render(request, self.template_name, {'form': form, 'title': 'Bank Reconcilation'})
def post(self, request, *args, **kwargs):
form = BRForm(request.POST)
if form.is_valid():
form.save()
return redirect('br-home')
I have managed to solve this issue! <br>
Link: https://stackoverflow.com/a/60961015/10732211 <br>
I overhauled the entire thing and followed the above link. Probably the models relations have some issues that does not work. <br>
views.py
class BRHomeView(FormView):
# model = TargetImage
template_name = 'br/br-home.html'
context_object_name = 'bankrecon'
def get(self, request):
form = BRFormExtended()
return render(request, self.template_name, {'form': form, 'title': 'Bank Reconcilation'})
def post(self, request, *args, **kwargs):
form = BRFormExtended(request.POST,request.FILES)
files = request.FILES.getlist('image_files')
if form.is_valid():
print("Form Valid")
print(form.cleaned_data['invoice_date'])
print(form.cleaned_data['recon_date'])
user = request.user
invoice_date = form.cleaned_data['invoice_date']
recon_date = form.cleaned_data['recon_date']
target_image_obj = TargetImage.objects.create(user=user,invoice_date=invoice_date, recon_date=recon_date)
for file in files:
UploadedImage.objects.create(target_image=target_image_obj,image_files=file)
else:
print("Form Invalid")
return redirect('br-home')
forms.py
class BRForm(forms.ModelForm):
class Meta:
model = TargetImage
fields = ['invoice_date', 'recon_date']
widgets = {
'invoice_date': forms.DateInput(attrs={'type': 'date'}),
'recon_date': forms.DateInput(attrs={'type': 'date'}),
}
class BRFormExtended(BRForm):
image_files = forms.FileField(widget=forms.ClearableFileInput(attrs={'multiple': True}))
class Meta(BRForm.Meta):
fields = BRForm.Meta.fields + ['image_files',]
models.py
from django.contrib.auth.models import User
from django.utils import timezone
class TargetImage(models.Model):
user = models.OneToOneField(User,on_delete=models.CASCADE)
uploaded_date = models.DateTimeField(default=timezone.now)
invoice_date = models.DateTimeField()
recon_date = models.DateTimeField()
def __str__(self):
return self.user.__str__()
class UploadedImage(models.Model):
target_image = models.ForeignKey(TargetImage, on_delete=models.CASCADE)
image_files = models.ImageField(null=True, blank=True, upload_to='images/')
Also, it would be helpful to have a media root folder and edits to urls.py is also required.
urls.py
from django.urls import path
from .views import BRHomeView
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
path('', BRHomeView.as_view(), name='br-home'),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
settings.py
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
STATIC_URL = '/static/'
STATICFILES_DIRS = (os.path.join(BASE_DIR, "static"),)
Hopefully this will help someone!

Django - Cannot get model to display in template

I'm creating an availability app for Volunteer Firefighters and cannot get one of the model fields to display in the template:
models.py
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models
# Create your models here.
class Team(models.Model):
name = models.CharField('Name', max_length = 200)
def __str__(self):
return self.name
class Firefighter(models.Model):
RANKS = (
('CFO', 'Chief Fire Officer'),
('DCFO','Deputy Chief Fire Officer'),
('SSO', 'Senior Station Officer'),
('SO', 'Station Officer'),
('SFF', 'Senior Firefighter'),
('QFF', 'Qualified Firefighter'),
('FF', 'Firefighter'),
('RFF', 'Recruit Firefighter'),
('OS', 'Operational Support'),
)
STATUS_OPTIONS = (
('AV', 'Available'),
('OD', 'On Duty'),
('UN', 'Unavailable'),
('LV', 'Leave'),
)
rank = models.CharField("Rank", max_length = 50 , choices=RANKS, default='RFF')
first_name = models.CharField("First Name", max_length = 200)
last_name = models.CharField("Last Name", max_length = 200)
start_date = models.DateField(name="Start Date")
status = models.CharField("Status", max_length = 20 , choices=STATUS_OPTIONS, default='Available')
driver = models.BooleanField('Driver', default=False)
officer = models.BooleanField('Officer Qualified', default=False)
teams = models.ManyToManyField(Team)
def __str__(self):
return self.first_name + ' ' + self.last_name
class Meta:
verbose_name = "Firefighter"
verbose_name_plural = "Firefighters"
views.py
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.shortcuts import render
from django.http import HttpResponse
from django.contrib.auth.decorators import login_required
from django.forms import ModelForm
from .models import Firefighter
from django.http import HttpResponseRedirect
# Create your views here.
#login_required(login_url='/login/')
def status(request):
firefighters = Firefighter.objects.all()
context = {
'firefighters': firefighters,
'availableCount': firefighters.filter(status='AV').count() + firefighters.filter(status='OD').count(),
'leaveCount': firefighters.filter(status='LV').count(),
'unAvCount': firefighters.filter(status='UN').count()
}
return render(request, 'status.html', context)
#login_required(login_url='/login/')
def details(request, id):
class ChangeStatus(ModelForm):
class Meta:
model = Firefighter
fields = ['status']
form = ChangeStatus()
firefighter = Firefighter.objects.get(id=id)
if request.method == 'POST':
form = ChangeStatus(request.POST, instance=firefighter)
if form.is_valid():
form.save()
return HttpResponseRedirect('/status/')
else:
form = ChangeStatus()
context = {
'firefighter': firefighter,
'form': form
}
return render(request, 'details.html', context)
def members(request):
firefighters = Firefighter.objects.all().order_by('rank')
context = {
'firefighters': firefighters,
}
return render(request, 'members.html', context)
and the members.html that won't render correctly:
{% extends "base.html" %}
{% block content %}
<ul>
{% for firefighter in firefighters %}
<li> {{firefighter.rank}} {{firefighter.first_name}} {{firefighter.last_name}} {{firefighter.start_date}}</li>
{% endfor %}
</ul>
{% endblock content %}
The members.html will correctly render firefighter.first_name and firefighter.last_name but nothing displays for firefighter.start_date even though each firefighter has a specified start date in the database.
Any ideas as to why?
Bonus question: Is there any way for me to sort the ranks as they are listed in the model when querying the database?
Where you define the field for the start_date you have:
start_date = models.DateField(name="Start Date")
It should be:
start_date = models.DateField("Start Date")
The first arg in Date_Field is verbose_name which will automatically set the name with a more acceptable snake_case version of the name.
As far as your ordering, try setting variables for your choices with a value that will sort.
CFO = ‘A’
DCFO = ‘B’
...
RANK_CHOICES = (
(CFO, ‘Chief Fire Officer’),
(DCFO, ‘Deputy Chief Fire Officer’)
(...)
)
If you always wanted query results by rank:
class Meta:
ordering = [‘rank’]
If not, use the current query you have.
As mentioned in Zev’s answer “name=‘label’” is not valid for any field. It is verbose_name=‘label. Depending on the field you can put the label as the first argument in quotes, but other fields you have to use verbose_name.

Categories