I have this view that creates a form with groups and exercises.
How can I do to be able to create more groups and exercises in the template?
views.py
#login_required
def creaScheda(request):
if request.method == "POST":
form = CreaSchedaForm(request.POST)
if form.is_valid():
schedaName = form.cleaned_data['nome_scheda']
scheda = form.save(commit = False)
scheda.utente = request.user
scheda.save()
gruppi = DatiGruppi(
giorni_settimana = form.cleaned_data['giorni_settimana'],
dati_gruppo = form.cleaned_data['dati_gruppo'],
gruppi_scheda = Schede.objects.get(nome_scheda = schedaName)
)
gruppi.save()
esercizi = DatiEsercizi(
serie = form.cleaned_data['serie'],
ripetizione = form.cleaned_data['ripetizione'],
peso = form.cleaned_data['peso'],
gruppo_single = DatiGruppi.objects.get(gruppi_scheda = scheda.id),
dati_esercizio = form.cleaned_data['dati_esercizio']
)
esercizi.save()
return redirect('/backoffice')
else:
form = CreaSchedaForm()
context = {"form": form}
return render(request, "crea_scheda.html", context)
A solution to this would be using the bulk_create method on the object manager with an array/list of the objects to be created
example
ModelName.objects.bulk_create([
ModelName(title="Model1"),
ModelName(title="Model2"),
ModelName(title="Model3"),
])
where ModelName refers to the Name of Your Model, and ModelName within the list refers to the different instances/records of the ModelName class/database to be create in a bulk
I am trying to update an existing record in Django but whenever I PUT request with postman I get the following.
It says that it already exists. So i tried to assign
task_1 = Task.objects.get(pk=task_id)
task_1 = ser
But I get an error that i can't assign it
===============================
My current code:
class TaskView(APIView):
permission_classes = (IsAuthenticated,)
def put(self, request, task_id):
task_obj = find_task(request.auth, task_id)
if task_obj:
task = task_obj.data
my_data = json.loads(request.body)
keys = list(my_data.keys())
for key in keys:
task[key] = my_data[key]
ser = TaskSerializer(data=task)
ser.is_valid(raise_exception=True)
ser.save()
return Response(ser.data)
else:
return Response(status=status.HTTP_404_NOT_FOUND)
# Returns the task only if its assigned to current user
def find_task(token, task_id):
u_id = Token.objects.get(key=token).user_id
assign_to = AssignTo.objects.filter(task_id=task_id, user_id=u_id)
if len(assign_to) > 0:
task = Task.objects.get(pk=task_id)
serializer = TaskSerializer(task)
return serializer
else:
return False
I believe it has nothing to do with the method i use ( POST, PUT, PATCH) because it works perfect when I comment out this part of code:
# ser = TaskSerializer(data=task)
# print(ser)
# ser.is_valid(raise_exception=True)
# ser.save()
return Response(task)
So it's something with serialization and task Instances
===============================
SECOND VERSION OF MY CODE:
def put(self, request, task_id):
u_id = Token.objects.get(key=request.auth).user_id
assign_to = AssignTo.objects.filter(task_id=task_id, user_id=u_id)
if len(assign_to) > 0:
task = Task.objects.get(pk=task_id)
my_data = json.loads(request.body)
keys = list(my_data.keys())
for key in keys:
task[key] = my_data[key]
print(task)
return Response(task)
else:
return Response(status=status.HTTP_404_NOT_FOUND)
The error I get from my SECOND VERSION of code is :
TypeError: 'Task' object does not support item assignment
So how do I update JUST the given keys from the request body.
So the solution was pretty simple.
I just had to add some args inside the save function => task.save(update_fields=keys)
This is my working code:
def put(self, request, task_id):
# task = Task.objects.get(pk=task_id)
# Task is the returned Model value
task = find_task(request.auth, task_id)
if task:
my_data = json.loads(request.body)
keys = list(my_data.keys())
for key in keys:
setattr(task, key, my_data[key])
task.save(update_fields=keys)
ser = TaskSerializer(task)
return Response(ser.data)
else:
return Response(status=status.HTTP_404_NOT_FOUND)
Here are my lines dealing with the two forms :
user = request.user
user_liked = user_liked_form.save(commit = False)
user_liked.user = user
user_liked.save()
user_disliked = user_disliked_form.save(commit = False)
user_disliked.user = user
user_disliked.save()
The data submitted in second form is being saved in both liked and disliked.
I have used User foreignkey in both the liked and disliked models.
Here is the complete function :
def collect(request):
context = RequestContext(request)
submitted = False
if request.method == 'POST':
data = request.POST
user_liked_form = UserLikedForm(data = request.POST)
user_disliked_form = UserDislikedForm(data = request.POST)
# user_id = data["user_id"]
user = request.user
if user_liked_form.is_valid() and user_disliked_form.is_valid():
# user_liked_form.save(commit = True)
# user_disliked_form.save(commit = True)
user_liked = user_liked_form.save(commit = False)
user_liked.user = user
user_liked.save()
user_disliked = user_disliked_form.save(commit = False)
user_disliked.user = user
user_disliked.save()
submitted = True
else:
print user_liked_form.errors, user_disliked_form.errors
else:
user_liked_form = UserLikedForm()
user_disliked_form = UserDislikedForm()
return render_to_response(
'collect.html',
{'user_liked_form': user_liked_form, 'user_disliked_form': user_disliked_form, 'submitted': submitted},
context)
It sounds like your UserLikedForm and UserDislikedForm have the same field names and when the form is submitted, only the second value comes through in request.POST. To fix this, you will need to add a prefix to the forms:
user_liked_form = UserLikedForm(prefix='liked')
user_disliked_form = UserDislikedForm(prefix='disliked')
That way when the forms are rendered, each form will have unique field names.
I create several forms to edit some records. When I save the form, I can see in the database that the application update the record and insert one or two record more.
All the forms that I use to update record have this weird behavior. I don't know if the error is in the form definition or in the view definition.
Model
class DetalleRecepcion(models.Model):
id_proveedor = models.ForeignKey(Proveedor,db_column='id_proveedor',primary_key=True, verbose_name='Proveedor')
anio = models.IntegerField( null=False)
mes = models.IntegerField(verbose_name='Mes')
fecha_recepcion = models.DateField(verbose_name='Fecha Recepcion')
usuario = models.CharField(max_length=15, blank=True)
num_archivos = models.IntegerField(primary_key=True, verbose_name='No de archivos')
class Meta:
managed = False
db_table = 'mpc_detalle_recepcion'
View
#login_required(login_url='/login/')
def DetRecView(request):
idp = request.GET.get('i')
anio = request.GET.get('a')
mes = request.GET.get('m')
if request.method == 'POST':
r = DetalleRecepcion.objects.get(id_proveedor=idp,anio=anio,mes=mes)
form = DetRecForm(request.POST or None, instance =r)
if form.is_valid():
form.save()
return HttpResponse('<script type="text/javascript">window.close()</script>')
else:
r = DetalleRecepcion.objects.get(id_proveedor=idp,anio=anio,mes=mes)
r.usuario = request.user
form = DetRecForm(instance=r)
return render_to_response('detrec.html',
{'form':form},
context_instance=RequestContext(request))
Form
class DetRecForm(forms.ModelForm):
fecha_recepcion = forms.DateField(widget=DateInput(),)
def __init__(self,*args,**kwargs):
super(DetRecForm,self).__init__(*args,**kwargs)
self.helper = FormHelper(self)
self.helper.layout = Layout(
Field('id_proveedor',
'anio',
'mes',
'usuario',
readonly = True
),
Fieldset('',
'fecha_recepcion',
'num_archivos',
Submit('save','Grabar'),
HTML('<a class="btn btn-danger" id="cerrar">Cancelar</a>')
)
)
class Meta:
model = DetalleRecepcion
I am using a legacy database, I check the constrains, procedure, triggers of the database and everything look fine.
Beside the table don't use any procedure function etc.
And only when I update or insert from the application I can see this behavior.
UPDATE
urls.py
urlpatterns = patterns('',
url(r'^recepcion/$','prov.views.DetRecView',name='recepcion'),
url(r'^newdetrec/$','prov.views.NewDetRecView',name='newdetrec'),
url(r'^master/$','prov.views.NewMasterView',name='master'),
url(r'^conci/$', 'prov.views.ConciView',name='conci'),
url(r'^carga/$', 'prov.views.CargaView',name='carga'),
url(r'^gencert/$', 'prov.views.GenCertView',name='gencert'),
url(r'^entcert/$', 'prov.views.EntCertView',name='entcert'),
url(r'^aceptacert/$', 'prov.views.AceptaCertView',name='aceptacert'),
url(r'^envconci/$', 'prov.views.EnvConciView',name='envconci'),
)
My create view (for the same model)
#login_required(login_url='/login/')
#permission_required('prov.views.configView',login_url='/login/')
def NewDetRecView(request):
form = NewDetRecForm(request.POST or None)
if request.method == 'POST':
idp = request.POST['id_proveedor']
a = request.POST['anio']
m = request.POST['mes']
id = Proveedor.objects.get(id_proveedor=idp)
obj,created = DetalleRecepcion.objects.get_or_create(id_proveedor=id,anio=a,mes=m)
obj.save()
return HttpResponseRedirect('/monitor/')
if not created:
obj.id_proveedor = id
obj.anio = a
obj.mes = m
obj.save()
return HttpResponseRedirect('/monitor/')
return render_to_response('newdetrec.html',
{'form':form})
My form class to create new records:
class NewDetRecForm(forms.ModelForm):
def __init__(self,*args,**kwargs):
super(NewDetRecForm,self).__init__(*args,**kwargs)
self.helper = FormHelper(self)
self.helper.layout.append(Submit('save','Grabar'))
self.helper.layout = Layout(
Fieldset('',
'id_proveedor',
'anio',
'mes',
Submit('save','Grabar'),
)
)
def clean(self):
cleaned_data = super(NewDetRecForm, self).clean()
id_proveedor = self.cleaned_data['id_proveedor']
#num_archivos = self.cleaned_data['num_archivos']
anio = self.cleaned_data['anio']
mes = self.cleaned_data['mes']
qs = self.Meta.model.objects.filter(id_proveedor=id_proveedor, anio=anio, mes=mes)
if self.instance:
qs = qs.exclude(pk = self.instance.pk)
if qs.count() > 0:
raise forms.ValidationError(u'Registro ya existente')
return cleaned_data
class Meta:
model = DetalleRecepcion
DetRecForm is for update
DetRecView is for update
NewDetRecForm is for create
NewDetRecView is for create
UPDATE 2
javascript function to pass parameters
<script type="text/javascript">
$(document).ready ( function () {
$(document).on ("click", "#recepcion", function (event) {
event.preventDefault();
var tbl = document.getElementById("myTable");
var idpro = $(this).parents('tr:first').find('td:first').text();
var anio = $(this).closest('tr').children(":eq(1)").text();
var mes = $(this).closest('tr').children(":eq(2)").text();
var argu = "?i="+idpro+"&a="+anio+"&m="+mes;
//window.location = "/recepcion/"+argu;
var url = "/recepcion/"+argu;
window.open(url,'_blank')
});
});
</script>
I know this isn't the right way to pass parameters to the templates.
I am start learning AJAX to pass the data, but meanwhile I use this horrible function
url(r'^recepcion/add/$','prov.views.DetRecView',name='recepcion_add'), # create object
url(r'^recepcion/edit/(?P<pk>\d+)/$','prov.views.DetRecView',name='recepcion_edit'), # update object
Lets look at your condition in the view function: if request.method=='POST' better use if request.POST,
So when you have else - it means request.GET you get an instance of DetalleRecepcion (read instance as object of some class) and pass it to your ModelForm. It is update object approach (but you use this to create object), and provided query must give one object (unique).
If you want use this view to create and update you have to change your urls (smth like I did above) and you have to define condition: if request.kwargs.get('pk') you're going to update object else you're going to create object.
Main difference that if it is update case you have to provide instance to your form r = DetalleRecepcion.objects.get(pk=request.kwargs['pk']), so DetRecForm(instance=r) (whenrequest.GET) and form = DetRecForm(request.POST, instance =r) (whenrequest.POST).
If you want provide some initial data to your form (when request.GET) use DetRecForm(initial = {'id_proveedor': idp, 'anio': anio, 'mes': mes, 'usuario': request.user})
I have a basic search view. It currently queries the db for any objects from a particular client. The view code is as follows:
def search_page(request):
form = PrdSearchForm()
prdlinks = []
show_results = True
if request.GET.has_key('query'):
show_results = True
query = request.GET['query'].strip()
if query:
form = PrdSearchForm({'query' : query})
prdlinks = \
ProjectRecord.objects.filter(client__icontains=query)
if len(prdlinks) >= 1:
records = ProjectRecord.objects.filter(client__icontains=query)
t = get_template('org_list_client.html')
html = t.render(Context({'records': records}))
return HttpResponse(html)
else:
tpl = "prd_search.html"
variables = RequestContext(request, { 'form': form,
'prdlinks': prdlinks,
'show_results': show_results})
return render_to_response(tpl, variables)
I'd like for the search field to check both for objects by client AND account. This, I think, would involve altering this code:
if query:
form = PrdSearchForm({'query' : query})
prdlinks = \
ProjectRecord.objects.filter(client__icontains=query)
to include ProjectRecord.objects.filter(account__icontains=query). Can anyone help with the syntax, or is there more involved with what I'm trying to accomplish?
I think you're looking for the Q object (as refrenced by The MYYN)
from django.db.models import Q
records=ProjectRecord.objects.filter(
Q(client__icontains=query) |
Q(account__icontains=query)
)
complex-lookups-with-q-objects
You can try to chain filters, like:
>>> ProjectRecord.objects.filter(
... client__icontains=query).filter(account__icontains=query)
This will first filter the clients, which contain the query, then filter this result queryset where the account also contains query.
General form:
>>> Entry.objects.filter(
... headline__startswith='What'
... ).exclude(
... pub_date__gte=datetime.now()
... ).filter(
... pub_date__gte=datetime(2005, 1, 1)
... )
Further useful examples are included in the documentation:
Spanning Multi-Valued Relationships
Complex lookups with Q objects
Restructured the view code to separate the client records(prdlinks) from the account records(acclinks) and handled them separately. Wasn't sure if it would work (it does) and am still not sure if this is the most efficient way to write the code (probably isn't). In any event, here is the revised code:
def search_page(request):
form = PrdSearchForm()
prdlinks = []
**acclinks = []**
show_results = True
if request.GET.has_key('query'):
show_results = True
query = request.GET['query'].strip()
if query:
form = PrdSearchForm({'query' : query})
prdlinks = \
ProjectRecord.objects.filter(client__icontains=query)
**acclinks = \
ProjectRecord.objects.filter(account__icontains=query)**
if len(prdlinks) >= 1:
records = ProjectRecord.objects.filter(client__icontains=query)
t = get_template('org_list_client.html')
html = t.render(Context({'records': records}))
return HttpResponse(html)
**elif len(acclinks) >= 1:
records = ProjectRecord.objects.filter(account__icontains=query)
t = get_template('org_list_account.html')
html = t.render(Context({'records': records}))
return HttpResponse(html)**
else:
tpl = "prd_search.html"
variables = RequestContext(request, { 'form': form,
'prdlinks': prdlinks,
'show_results': show_results})
return render_to_response(tpl, variables)