Change form input from text value to model instance in django - django

I want to create Aviz entry using AJAX form.
In the form the input material has a jquery ui function autocomplete, that gets all the material names from the Material Model.
When I submit the form I get this error in the console : ValueError: Cannot assign "'ADEZIV LIPIRE VATA MINERALA, CT 180, 25 KG CERESIT'": "Aviz.material" must be a "Material" instance.
I know that I need to get the input from the form, and turn it in a Material instance...but do not know how/did not find any info about this.
models.py:
class Material(models.Model):
name = models.CharField(max_length=255,default=None,verbose_name='Nume material')
class Aviz(models.Model):
material = models.ForeignKey(Material, on_delete=models.CASCADE,related_name="aviz")
quantity = models.FloatField(default=0,verbose_name="Cantitate")
views.py:
class AvizCreate(LoginRequiredMixin, AjaxCreateView):
model = Aviz
form_class = AvizForm
def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
kwargs['pk'] = self.kwargs.get('centrudecost')
return kwargs
#login_required
def autocomplete(request):
if 'term' in request.GET:
qs = Material.objects.filter(name__icontains=request.GET.get('term'))
name = list()
id = list()
cod_nexus = list()
name = [prod.name for prod in qs]
id = [prod.pk for prod in qs]
cod_nexus = [prod.cod_nexus for prod in qs]
return JsonResponse({"name": name, "id":id, "cod_nexus":cod_nexus}, safe=False)
templates.html
$('#id_material').autocomplete({
source: function(request, response) {
$.ajax({
url: "{% url 'materiale:autocomplete' %}",
dataType: "json",
data: {
term: request.term
},
success: function(data) {
response($.map(data.name, function(value, key) {
return {
label: data.name[key],
value: data.name[key],
id:data.id[key],
cod_nexus:data.cod_nexus[key]
}
}));
}
});
},
select: async function(event, ui) {
let resp = await fetch("{% url 'materiale:get_um' 1 %}".replace('1',ui.item.id));
let json = await resp.json()
$('#id_um').val(json);
}
})
}
forms.py:
class AvizForm(BootstrapHelperForm, forms.ModelForm):
material = forms.CharField()
um = forms.CharField()
class Meta:
model = Aviz
fields = ('centrudecost','data','aviz', 'material','um','quantity',)
widgets = {
'data': DateInput(),
'centrudecost': forms.HiddenInput(),
# 'material': forms.Select(attrs={'class': 'form-control'})
}
def __init__(self, *args, **kwargs):
pk = kwargs.pop('pk', None)
super(AvizForm, self).__init__(*args, **kwargs)
self.fields['um'].widget.attrs['readonly'] = True
I know that by deleting this material = forms.CharField() from the forms.py, the form works, and a Aviz instance is created referencing the material model, but i need to use the autocomplete function in the form

Related

DJANGO REST FRAMEWORK IMAGE UPLOAD ["The submitted data was not a file. Check the encoding type on the form."]

I can't seem to upload an image to my project.
I always get this error when I try to submit the form from the frontend :
["The submitted data was not a file. Check the encoding type on the form."]
I've found some answers regarding the base64 encoding of the image but I can't seem to get it to work.
Any help would be much appreciated!!
thanks
here is the source code:
Models:
class Person(models.Model):
name = models.CharField(max_length=30)
age = models.IntegerField(default=0)
dob = models.CharField(max_length=10)
image = models.ImageField(upload_to='images/', null=True)
def __str__(self):
return self.name
class Details(models.Model):
party = models.ForeignKey(Person,on_delete=models.CASCADE,
related_name='party_details',null=True,blank=True)
adress = models.CharField(max_length=50)
date = models.CharField(max_length=20)
arrival= models.CharField(max_length=20)
def __str__(self):
return self.adress
Serializers:
class DetailsSerializer(serializers.ModelSerializer):
class Meta:
model = Details
# fields='__all__'
fields = ('id','party','adress','date','arrival')
class PersonSerializer(serializers.ModelSerializer):
party_details =DetailsSerializer(many=True)
class Meta:
model = Person
# fields='__all__'
fields = ('id','name','age','dob','image','party_details')
def create(self, validated_data):
named_details = validated_data.pop('party_details')
details = Person.objects.create(**validated_data)
for named_detail in named_details:
Details.objects.create(party=details, ** named_detail)
return details
def update(self,instance, validated_data):
named_details = validated_data.pop('party_details')
details = (instance.party_details).all()
details = list(details)
instance.name = validated_data.get('name', instance.name)
instance.age = validated_data.get('age', instance.age)
instance.dob = validated_data.get('dob', instance.dob)
instance.image = validated_data.get('image', instance.image)
instance.save()
for named_detail in named_details:
detail = details.pop(0)
detail.adress = named_detail.get('adress',detail.adress)
detail.date = named_detail.get('date',detail.date)
detail.arrival = named_detail.get('arrival', detail.arrival)
detail.save()
return instance
views:
class ListAllPerson (generics.ListCreateAPIView):
queryset=Person.objects.all()
serializer_class = PersonSerializer
class ListPerson (generics.RetrieveUpdateDestroyAPIView):
serializer_class = PersonSerializer
queryset= Person.objects.all()
class ListAllDetails(generics.ListCreateAPIView):
queryset=Details.objects.all()
serializer_class = DetailsSerializer
class ListDetail(generics.RetrieveUpdateDestroyAPIView):
serializer_class = DetailsSerializer
queryset=Details.objects.all()
class CreateDetail(generics.ListCreateAPIView):
queryset=Details.objects.all()
serializer_class = DetailsSerializer
HTML FORM and Axios:
const profileImage = async ()=>{
let formField = new FormData()
formField.append('image',addImages)
await axios({
method: 'patch',
url: url,
data: formField
}).then((response) => {
history.push('/')
}).catch((error) => {
console.log(error);
})
}
<div className="add-image-input">
<form action="" className="add-image-form">
<input className="image-input" value={addImages}
onChange={(e)=>{setAddImages(e.target.value)}} type="file"/>
<button className="" type="button" onClick={profileImage} >add</button>
</form>
</div>
Hopefully you are using React js, this should help. At the point of
saving and submitting your form data, your function should look like this:
const onSubmit = (data) => {
console.log(data)
let form_data = new FormData();
form_data.append('upload_image_photo', data.cover_image, data.cover_image.name);
form_data.append('title', data.title);
form_data.append('category', data.category);
form_data.append('price_per_night', data.price_per_night);
form_data.append('room_slug', data.room_slug);
form_data.append('capacity', data.capacity);
form_data.append('room_size', data.room_size);
let url = '/url to the end point you are saving with the expected image field / ';
const config = {
headers: {
"Content-Type": "multipart/form-data",
Authorization: `Bearer ${token}`,
},
};
axios.post(url, form_data, config)
.then(res => {
console.log(res.request.status);
console.log(res.data);
})
.catch(err => console.log(err))
};

Cannot resolve keyword 'name' into field. Choices are: categoria, categoria_id, detalle_compra,

I don't understand what I'm doing wrong. I am trying to do an autocomplete with the data from the Product table, I don't know what the reason is since I mention the name of the product but toa it as "name". I've done it but I keep getting this error:
Cannot resolve keyword 'name' into field. Choices are: categoria, categoria_id, detalle_compra, ...
Models
class Producto(models.Model):
id_producto = models.AutoField(primary_key=True)
categoria = models.ForeignKey(Categoria, on_delete=models.CASCADE)
def __str__(self):
return self.nombre
def toJSON(self):
item = model_to_dict(self)
return item
class Meta:
verbose_name = 'Producto'
Views
def post(self, request, *args, **kwargs):
data = {}
try:
action = request.POST['action']
if action == 'autocomplete':
productos = Producto.objects.filter(name__icontains=request.POST['term'])
for i in productos:
data = []
item = i.toJSON()
item['value'] = i.nombre
data.append(item)
else:
JS
$("#search").autocomplete({
source: function (request, response) {
$.ajax({
url: window.location.pathname,
type: 'POST',
data: {
'action': 'autocomplete',
'term': request.term
},
dataType: 'json',
}).done(function (data) {
response(data);
}).fail(function (data) {
alert("Error");
}).always(function (jqXHR, textStatus, errorThrown) {
})
},
I have verified that it is not "name" however in none of the files I have made that equivalent. I hope you can help me
You are trying to pass name_contains in views.py which is not in model Producto.
Try to use this :-
productos = Producto.objects.filter(id_producto__icontains=request.POST['term'])

django tables 2 - delete column and delete_item for inherited tables

I want to have one abstract function for all my tablelists (one for each model) and (one delete_item) function in view.
I don't know how to make the delete (column in this table) and pass the model to the delete_item function in the view
Tables.py
############ Abstract Table
class abs_Table(tables.Table):
SN = tables.Column(empty_values=(), orderable=False)
delete = tables.LinkColumn('delete_item', args=[A('pk'), ?????Model???], attrs={
'a': {'class': 'btn btn-small btn-dark'}
# })
def __init__(self, *args, **kwargs):
super(abs_Table, self).__init__(*args, **kwargs)
self.counter = itertools.count(1)
def render_SN(self, record):
pg = getattr(self, 'paginator', None)
if pg:
v = next(self.counter)
return v + self.paginator.per_page * (self.page.number-1)
else:
return next(self.counter)
class Meta:
model = None
fields = [ 'SN', 'id', 'delete', ]
attrs = {"class": "table-striped table-bordered", 'width': '100%'}
empty_text = "There are no Records matching the search criteria..."
Then for model Table
Tables.py
class ModelTable(abs_Table):
class Meta(abs_Table.Meta):
model = modelname
fields = abs_Table.Meta.fields+[selected_model_fields]
Views.py
def delete_item(request, pk, delmodel):
obj = get_object_or_404(delmodel, id=pk)
if request.method == "POST":
obj.delete()
return redirect("../")
else:
pass
context = {
'object': obj
}
return render(request, '/delete_confirmation.html', context)
For the Views part. It works for me after passing the model as string and then using apps.get_model to change it into a model.
views.py`
from django.apps import apps
def delete_item(request, pk, delmodel):
DeleteModel = apps.get_model("Myapp", delmodel)
obj = get_object_or_404(DeleteModel, id=pk)
if request.method == "POST":
obj.delete()
return redirect("../")
else:
pass
context = {
'object': obj
}
return render(request, '/delete_confirmation.html', context)
Still the confirmation is not handled correctly and the delete column in tables need to be improved.

Problems with the response in API REST django

I try to link django API-REST with a form that has an associated model. Everything works well until I do the:
return response.Response (serializer.data, status = status.HTTP_201_CREATED)
JavaScript
// To Save the Suggestion
let ajax_suggestion_save = function (type, url, data, context) {
let name_dm = $('#name-db-saved').val();
$.ajax({
type: type,
url: url,
data: data,
context: context,
beforeSend: function (xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
},
success: function (response) {
$.niftyNoty({
type: "success",
container: 'floating',
title: 'Your information was saved successfully.',
message: 'We much appreciate your interest of contact us, part of the growth of this platform it is base on your collaboration through your ideas.',
closeBtn: true,
timer: 4000
});
},
error: function (response) {
if (Object.keys(response.responseJSON).length >= 1) {
$.each(response.responseJSON, function (key, value) {
$.niftyNoty({
type: 'danger',
container: 'floating',
title: 'Ups, apparently we have problems saving your information.',
message: 'Please check the following ' +
'Error in <strong> ' + key + ' </strong>, with the following error <strong> ' + value + ' </strong>.',
closeBtn: true,
timer: 4000
});
});
} else {
$.niftyNoty({
type: 'danger',
container: 'floating',
title: 'Ups, apparently we have problems saving your information.',
message: 'Ups, apparently we have problems saving your suggestion. ' +
'If the problem persists, notify the system administrator in the help section.' +
'You suggestion <strong> ' + name_dm + ' </strong> not will be saved.',
closeBtn: true,
timer: 4000
});
}
}
});
};
$('#contactus').on('click', function (type, url, data, context) {
ajax_suggestion_save('POST', '/miscellaneous/api/contactus/create/', $("#contactus_form").serializeArray(), this);
});
Model
class DimContactUs(Model):
class Meta:
order_with_respect_to = 'email'
verbose_name = 'Contact'
verbose_name_plural = 'Contact'
id_contact_us = UUIDField(primary_key=True, default=uuid.uuid4, editable=False,
help_text='Universally unique identifier of a Contact')
name = CharField(max_length=100, help_text='Name of the Contact')
email = EmailField(max_length=70, help_text='Email of these Contact')
# id_user = ForeignKey(User, on_delete=CASCADE, help_text='Foreign Key of the User that made this Contact')
title = CharField(max_length=100, help_text='Title of the Contact')
message = TextField(
help_text='Short description of this Contact, e.g. : We want to include ...!')
url = URLField(null=True, blank=True,
help_text='Please copy the url associated to this Contact')
active = BooleanField(default=True, help_text='Do you want to make public this Contact?')
time_create = DateTimeField(auto_now=True, auto_now_add=False, editable=False, help_text='Time it was created')
time_stamp = DateField(auto_now=True, auto_now_add=False, help_text='Time of last modification')
def __str__(self):
return self.title
Serializers
class DimContactUsSer(serializers.ModelSerializer):
class Meta:
model = DimContactUs
fields = '__all__'
View
class ContactUsCreate(CreateAPIView):
queryset = DimContactUs.objects.all()
serializer_class = DimContactUsSer
#csrf_exempt
def post(self, request, *args, **kwargs):
try:
if request.method == 'POST':
form = DimContactUsForm(request.POST, request.FILES)
serializer = DimSuggestionSer(data=request.data)
if form.is_valid() and serializer.is_valid():
serializer.save()
return response.Response(serializer.data, status=status.HTTP_201_CREATED)
else:
return response.Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
except Exception as exception:
return response.Response(exception.args, status=status.HTTP_400_BAD_REQUEST)
Here, the response sends me to the REST API page instead of staying in the current one.
I would expect your missing the import statement for the module, I cannot see your import statements.
from rest_framework import status

Two model forms in one view/template in Django using CBV

Can someone show the example of usage of two model forms in one view/template? The task is to process more than one form in one CBV, where model of the second form has FK to first form model, so value from select widget from first form must be processed as value for object, created in second form.
My forms looks like this:
class CompanyEditForm(ModelForm):
name = CharField(label="Наименование", required=True)
type = ModelChoiceField(queryset=CompanyTypes.objects.all(), label="Тип компании", empty_label=None, initial=3)
description = CharField(label="Описание компании", required=False, widget=forms.Textarea(attrs={'cols': 40, 'rows':3}))
www = CharField(label="WEB сайт", required=False)
class Meta:
model = Companies
fields = ('type', 'name', 'description', 'www')
class BranchEditForm(ModelForm):
name = CharField(label="Наименование офиса", required=True)
type = ModelChoiceField(queryset=BranchTypes.objects.all(), label="Тип отделения", empty_label=None, initial=1)
class Meta:
model = Branches
exclude = ('company', 'address')
class AddressEditForm(ModelForm):
postalcode = IntegerField(label="Почтовый код", required=False)
city = CharField(label="Город", required=True)
street = CharField(label="Улица", required=True)
app = CharField(label="Дом", required=True)
app_extra = CharField(label="Корпус / Строение", required=False)
comment = CharField(label="Примечание к адресу", required=False)
exclude = ('company',)
class Meta:
model = Addresses
fields = ('postalcode', 'city', 'street', 'app', 'app_extra', 'comment')
UPDATE
I wrote this mixin:
class MultiFormCreate(FormMixin, TemplateResponseMixin, View):
formconf = None
def get_form_classes(self):
form_classes = {}
for key, params in self.formconf.items():
form_classes[key] = params.formclass
return self.form_classes
def get_initial(self, classname):
inicial = {}
if 'inicial' in self.formconf[classname]:
inicial = self.formconf[classname]['inicial'].copy()
return inicial
def get_form_kwargs(self, classname):
kwargs = {'initial': self.get_initial(classname), 'prefix': classname}
if self.request.method in ('POST', 'PUT'):
kwargs.update({
'data': self.request.POST,
'files': self.request.FILES,
})
return kwargs
def get_forms(self):
for classname, params in self.formconf.items():
log.info("Name: %s, Params: %s" % (classname, params))
return dict(
[(classname, params['formclass'](**self.get_form_kwargs(classname))) for classname, params in self.formconf.items()])
def get(self, request, *args, **kwargs):
forms = self.get_forms()
return self.render_to_response(self.get_context_data(forms=forms))
def get_success_url(self):
if self.success_url:
url = force_text(self.success_url)
else:
raise ImproperlyConfigured(
"No URL to redirect to. Provide a success_url.")
return url
then in a view i only need to write processing in post:
class CompanyCreate(MultiFormCreate):
template_name = 'company/edit.html'
success_url = '/forbidden/'
formconf = {
'company': {'formclass': CompanyEditForm, 'inicial': {'name': "TESTNAME"}},
'branch': {'formclass': BranchEditForm},
'address': {'formclass': AddressEditForm}
}
def post(self, request, *args, **kwargs):
forms = self.get_forms()
cform = forms['company']
aform = forms['address']
bform = forms['branch']
if cform.is_valid() and aform.is_valid() and bform.is_valid():
''' Creating main form form object (by saving tthe form) '''
company_object = cform.save()
''' Creating dependant object '''
address_object = aform.save(commit=False)
branch_object = bform.save(commit=False)
''' assigning dependent fields '''
address_object.company = company_object
''' saving dependent _object_ '''
address_object.save()
''' managing another dependent fields '''
branch_object.company = company_object
branch_object.address = address_object
''' saving last object '''
branch_object.save()
return HttpResponseRedirect(self.get_success_url())
else:
forms = self.get_forms()
return self.render_to_response(self.get_context_data(forms=forms))
Code for view file :
if request.method == "POST":
company_form = CompanyEditForm(request.POST)
if company_form.is_valid():
company_object = company_form.save()
post_data = request.POST.copy()
branch_form = BranchEditForm(post_data)
branch_form.data['company'] = company_object
if branch_form.is_valid():
branch_object.save()
rest implement your business logic ..