how to get field value from model - django

I have a model for registering with some fields.
All fields are models I fill in through the form like this.
def get_name(request):
if request.method == 'POST':
user_code = generate_code(8)
subject = 'code'
message = user_code
phone=request.POST['phone']
form = NameForm(request.POST)
if form.is_valid():
date_use = form.cleaned_data.get("date_visit")
time_use = form.cleaned_data.get("time_visit")
purpose_use = form.cleaned_data.get("purpose")
if Registration.objects.filter(date_visit=date_use,time_visit=time_use,purpose=purpose_use).count()==0:
Registration.objects.create(fio=request.POST['fio'],phone=request.POST['phone'],date_visit=request.POST['date_visit'],time_visit=request.POST['time_visit'],
number_car=request.POST['number_car'],purpose=request.POST['purpose'],
tso=request.POST['tso'])
request.session["phone"] = phone
request.session["code"] = user_code
return HttpResponseRedirect('endreg')
else:
form = NameForm()
return render(request, 'registers/detail.html', {'form': form})
The model also has a field
date_register = models.DateTimeField(verbose_name = 'date register', auto_now_add=True)
how can i write date_register value in request.session["date"] ?

Instead of using Registration.objects.create(...) you can use .save method:
obj = Registration()
obj.fio = form.cleaned_data["fio"]
...
obj.save()
request.session["date"] = str(obj.date_register)

By default django use JSONSerializer and it can't dump datetime objects.
The simplest solution is using PickleSerializer as SESSION_SERIALIZER, but it can cause performance issues (docs: https://docs.djangoproject.com/en/3.0/ref/settings/#std:setting-SESSION_SERIALIZER)
Another way to do it - write you custom json serializer, based on django serializer, but with default function for dumping datetime objects, or simple convert date to string format or timestamp before saving to session.

Related

Django - ModelForm - initial value

I'm working with Modelforms and would like to set the initial value of the "feeder" field. I get the following Type Error: "invalid literal for int() with base 10: 'None'" What might be the problem?
Many thanks all
forms.py:
class CashFlowForm(forms.ModelForm):
class Meta:
model = models.CashFlow
fields = ['type', 'amount', 'description','date']
widgets = {'date': DatePicker()}
views.py:
def create_cashflow(request, fundslug):
funddetail = Fund.objects.get(slug=fundslug)
if request.method == 'POST':
cf = CashFlowForm(request.POST)
cf.feeder = funddetail.feeder
if cf.is_valid():
instance_cf = cf.save()
messages.success(request, 'Cash Flow successfully added!')
return redirect('funds:create_cashflow', fundslug = fundslug)
else:
cf = CashFlowForm()
return render(request, 'funds/create_cashflow.html', {'cf': cf})
I fink funddetail.feeder return None or You can try
cf.cleaned_data['feeder'] = funddetail.feeder
Models don't matter unless there's a foreign key involved. For the Type Error, it's mostly to do with the value your model fields are getting from the form.
For assigning value after form submission, do something like
if request.method == 'POST':
cf = CashFlowForm(request.POST)
cf.save(commit=False)
cf.feeder = funddetail.feeder
cf.save()

Add data to ModelForm object before saving

Say I have a form that looks like this:
forms.py
class CreateASomethingForm(ModelForm):
class Meta:
model = Something
fields = ['field2', 'field3', 'field4']
I want the form to have these three fields. However my Somethingclass also has field1. My question is - how do I add data to field1, if I am not using the ModelForm to collect the data. I tried doing something like this, but it isn't working and I am unsure on the proper way to solve this:
views.py
def create_something_view(request):
if (request.method == 'POST'):
# Create an object of the form based on POST data
obj = CreateASomething(request.POST)
# ** Add data into the blank field1 ** (Throwing an error)
obj['field1'] = request.user
# ... validate, save, then redirect
The error I receive is:
TypeError: 'CreateAClassForm' object does not support item assignment
In Django, what is the proper way to assign data to a ModelForm object before saving?
form = CreateASomething(request.POST)
if form.is_valid():
obj = form.save(commit=False)
obj.field1 = request.user
obj.save()
Sometimes, the field might be required which means you can't make it past form.is_valid(). In that case, you can pass a dict object containing all fields to the form.
if request.method == 'POST':
data = {
'fields1': request.user,
'fields2': additional_data,
}
form = CreateASomethingForm(data)
if form.is_valid():
form.commit(save)
There are two ways given by Django official
LINK : https://docs.djangoproject.com/en/3.0/topics/forms/modelforms/
Method 1]
author = Author(title='Mr')
form = PartialAuthorForm(request.POST, instance=author)
form.save()
Method 2]
form = PartialAuthorForm(request.POST)
author = form.save(commit=False)
author.title = 'Mr'
author.save()
Here is a more suitable way to add data especially used during testing:
First convert an existing entry into a dictionary with the model_to_dict function
from django.forms.models import model_to_dict
...
valid_data = model_to_dict(entry)
Then add the new data into this dictionary
valid_data['finish_time'] = '18:44'
This works better than setting the value in the form
update_form.finish_time = '18:44'
Create the form with the valid data and the instance
update_form = UserEntryForm(valid_data, instance=entry)
Do any assertions you require:
self.assertTrue(update_form.is_valid())
entry = update_form.save()
self.assertEqual(
entry.status,
1
)

django prepopulate modelform - nothing happens

This must be a very simple thing however I can not seem to get through it..
I trying to build a form where the user can update a ModelForm. First he inserts a user id and afterwards I want to show him the form pre-populate with the original data so he can change only the fields that he wants.
After some the help of my friend google, stackoverflow and the django documentation, I've come to this:
views.py
user = User.objects.get(user_id=usr)
if request.method == 'POST':
form = TableForm(request.POST)
if form.is_valid():
#do something
else:
form = TableForm(instance=user)
return render_to_response('template.html',{'form':form})
forms.py
class TableForm(forms.ModelForm):
pres_clinic = forms.ModelChoiceField(queryset=PresClinic.objects.all(),
widget=SelectWithPop(), label=ugettext("Clinic presentation"),
required=False)
MAYBECHOICES = (
('', '---------'),
(ugettext('Yes'), ugettext('Yes')),
(ugettext('No'), ugettext('No')))
bcg_scar = forms.ChoiceField(choices=MAYBECHOICES, label=ugettext(
"BCG scar"), required=False)
mantoux_register = forms.ChoiceField(choices=MAYBECHOICES,
label=ugettext("Mantoux register"), required=False)
date_diag = forms.DateField(widget=DateTimeWidget, label=ugettext(
"Diagnosis date"), required=False)
situation = forms.ModelChoiceField(queryset=Situation.objects.all(),
widget=SelectWithPop(), label=ugettext("Patient status"),
required=False)
date_situation = forms.DateField(widget=DateTimeWidget, label=ugettext(
"Date patient status"), required=False)
class Meta:
model = Table
fields = ('pres_clinic', 'bcg_scar', 'mantoux_register',
'date_diag', 'situation', 'date_situation')
def clean(self):
cleaned_data = self.cleaned_data
diag = cleaned_data.get('date_diag')
errors = []
now = datetime.date.today()
if diag is not None and diag != u'':
if diag > now:
errors.append(ugettext('The field "Diagnosis date" should be '
'smaller than the actual date'))
if errors:
raise ValidationError(errors)
return cleaned_data
template:
{{ form }} # presents the empty form and not the data from that user
The version of django is 1.4
Can anyone tell me what is wrong and why I'm not able to see the form populated?
Thank you very much
You need to define a dictionary to be used for the initial data and change from TableForm(instance=user) to TableForm(initial=dict), for example something like:
user = User.objects.get(user_id=usr)
if request.method == 'POST':
form = TableForm(request.POST)
if form.is_valid():
#do something
else:
data = {'pres_clinic' : 'value', 'bcg_scar' : 'value', 'mantoux_register' : 'value'}
form = TableForm(initial=data)
return render_to_response('template.html',{'form':form})
I would also put the render to response out of the if statement so if the form isn't valid the page should reload and show any errors.
More information on the django docs here
I hope this helps!
You can try 'model_to_dict'
from django.forms.models import model_to_dict
user = User.objects.get(user_id=usr)
if request.method == 'POST':
form = TableForm(request.POST)
if form.is_valid():
#do something
else:
form = TableForm(initial=model_to_dict(user))
return render_to_response('template.html',{'form':form})

Django form is_valid() fails

I am a real beginner in web development. The following code is failing at the is_valid() check. But I do not understand why: The form should get its data filled from the POST-data or not?
Model:
class Statement(models.Model):
text = models.CharField(max_length=255)
user = models.ForeignKey(User)
time = models.DateField()
views = models.IntegerField()
ModelForm:
class StatementForm(ModelForm):
class Meta:
model = Statement
widgets = {
'time':forms.HiddenInput(),
'user':forms.HiddenInput(),
'views':forms.HiddenInput(),
}
View function:
def new(request):
if request.method == 'POST': # If the form has been submitted...
form = StatementForm(request.POST) # A form bound to the POST data
if form.is_valid():
stmt = form.save()
path = 'stmt/' + stmt.id
return render_to_response(path, {'stmt': stmt})
else:
c = {}
c.update(csrf(request))
loggedin_user = request.user
d = datetime.now()
form = StatementForm(request.POST, initial={'time': d.strftime("%Y-%m-%d %H:%M:%S"), 'user':loggedin_user, 'views':0})
return render_to_response('new_stmt.html', {'form': form, },context_instance=RequestContext(request))
I found similar topics and tried a lot. This is how i think it should work. I really need advice.
All fields of your model are required. So, form.is_valid() will be True, if all fields are filled with correct values and are not blanked.
You have declared fields time, user, views as hidden fields. Are you sure, that you have filled them in your template form?
Also, you may want to auto stamp field time = models.DateField(). Modify your model field like
time = models.DateField(auto_now=True)`.
After this you don't have to fill it by yourself in template form.
Your view must return HttpResponse object in all cases. If your form is not valid, i.e. if form.is_valid() will return False, then no HttpResponse object will be returned by your view. This can be the source of your fail. Add else statement for if form.is_valid():
from django.http import Http404
def new(request):
if request.method == 'POST': # If the form has been submitted...
form = StatementForm(request.POST) # A form bound to the POST data
if form.is_valid():
stmt = form.save()
path = 'stmt/' + stmt.id
return render_to_response(path, {'stmt': stmt})
else:
# Do something in case if form is not valid
raise Http404
else:
# Your code without changes
Change this line:
form = StatementForm(request.POST, initial={'time': d.strftime("%Y-%m-%d %H:%M:%S"), 'user':loggedin_user, 'views':0})
For this:
form = StatementForm(initial={'time': d.strftime("%Y-%m-%d %H:%M:%S"), 'user':loggedin_user, 'views':0})

Import csv data into database in Django Admin

I've tried to import a csv file into a database by tweaking the modelform inside the admin doing this:
models.py:
class Data(models.Model):
place = models.ForeignKey(Places)
time = models.DateTimeField()
data_1 = models.DecimalField(max_digits=3, decimal_places=1)
data_2 = models.DecimalField(max_digits=3, decimal_places=1)
data_3 = models.DecimalField(max_digits=4, decimal_places=1)
Forms.py:
import csv
class DataImport(ModelForm):
file_to_import = forms.FileField()
class Meta:
model = Data
fields = ("file_to_import", "place")
def save(self, commit=False, *args, **kwargs):
form_input = DataImport()
self.place = self.cleaned_data['place']
file_csv = request.FILES['file_to_import']
datafile = open(file_csv, 'rb')
records = csv.reader(datafile)
for line in records:
self.time = line[1]
self.data_1 = line[2]
self.data_2 = line[3]
self.data_3 = line[4]
form_input.save()
datafile.close()
Admin.py:
class DataAdmin(admin.ModelAdmin):
list_display = ("place", "time")
form = DataImport
admin.site.register(Data, DataAdmin)
But i'm stuck trying to import the file i put in "file_to_import" field. Getting AttributeError in forms.py : 'function' object has no attribute 'FILES'.
What i'm doing wrong?
After a long search i found an answer: Create a view inside the admin using a standard form
Form:
class DataInput(forms.Form):
file = forms.FileField()
place = forms.ModelChoiceField(queryset=Place.objects.all())
def save(self):
records = csv.reader(self.cleaned_data["file"])
for line in records:
input_data = Data()
input_data.place = self.cleaned_data["place"]
input_data.time = datetime.strptime(line[1], "%m/%d/%y %H:%M:%S")
input_data.data_1 = line[2]
input_data.data_2 = line[3]
input_data.data_3 = line[4]
input_data.save()
The view:
#staff_member_required
def import(request):
if request.method == "POST":
form = DataInput(request.POST, request.FILES)
if form.is_valid():
form.save()
success = True
context = {"form": form, "success": success}
return render_to_response("imported.html", context,
context_instance=RequestContext(request))
else:
form = DataInput()
context = {"form": form}
return render_to_response("imported.html", context,
context_instance=RequestContext(request))
The rest is part of this post:
http://web.archive.org/web/20100605043304/http://www.beardygeek.com/2010/03/adding-views-to-the-django-admin/
Take a look at django-admin-import, it does more or less exactly what you want -- you can upload a XLS (not a CSV, but that should not matter) and lets you assign columns to model fields. Default values are also supported.
https://pypi.org/project/django-admin-import/
Additionally, it does not take away the possibility to modify individual records by hand because you don't have to replace the default model form used in the administration.
In the save() method, you don't have any access to the request object - you can see that it's not passed in. Normally you would expect to have a NameError there, but I suspect that you've got a function elsewhere in the file called request().
At the point of saving, all the relevant data should be in cleaned_data: so you should be able to do
file_csv = self.cleaned_data['file_to_import']
At that point you'll have another problem, which is when you get to open - you can't do that, as file_to_import is not a file on the server filesystem, it's an in-memory file that has been streamed from the client. You should be able to pass file_csv directly to csv.reader.