I want to return only the clandpin fields. I have this model below:
model.py
class ButuanMaps(gismodel.Model):
class Meta:
verbose_name = u'Butuan Map'
verbose_name_plural = u'Butuan Maps'
clandpin = gismodel.CharField("Land PIN", max_length=50, null=True, blank=True)
ssectionid = gismodel.ForeignKey(Section)
#ssectionid_id = gismodel.IntegerField()
geom = gismodel.MultiPolygonField("Geom ID", srid=32651, null=True, blank=True)
objects = gismodel.GeoManager()
def __unicode__(self):
return self.clandpin
In my template, here's the code for AJAX:
<script type="text/javascript">
$(document).ready(function() {
$("#formsection").change(function() {
$.ajax({
url : "/sectionpins",
type : "GET",
dataType: "html",
data : {
'sectionid' : $('#formsection').val(),
'csrfmiddlewaretoken' : $("input[name=csrfmiddlewaretoken]").val()
},
success : searchSuccess,
error: errs
});
return false;
});
});
function searchSuccess(data){
alert("Success");
$('#forminput').append(
"<option value='"+data+"'>"+data+"</option>"
);
}
function errs(){
alert('Error!!!!');
}
</script>
In views.py:
def section_landpins(request):
if request.method == "GET":
m = ButuanMaps.objects.filter(ssectionid=request.GET['sectionid'])
landpins = serializers.serialize("json", m.values('clandpin'), fields=("clandpin"))
data = json.dumps({
'pins': landpins,
})
return HttpResponse(data, content_type='application/json')
It returned an error
AttributeError at /sectionpins'dict' object has no attribute '_meta'
When I changed the query with this:
m = ButuanMaps.objects.filter(ssectionid=request.GET['sectionid'])
It doesn't return an error but this:
{"pins": "[{\"pk\": 185625, \"model\": \"tbl.butuanmaps\", \"fields\": {\"clandpin\": \"162-12-0001-055-37\"}}
You can do this by requesting only the field you are interested in from the ORM, then evaluating the ValueQuerySet into a list of dictionaries:
section_id = request.GET.get('sectionid', 'defaultid')
m = ButuanMaps.objects.filter(ssectionid=section_id).values('landpins')
return HttpResponse(json.dumps({'pins': list(m)}),
content_type='application/json')
Related
I’m trying to build a web app using Django and I want to upload a file (a pdf or word document) using ajax (the ajax module in jquery).
I’m building my API using the django-rest-framework.
I’ve pretty much tried to do what every site says but can’t seem to get around it.
Has anyone done this?
My views:
def contract_post(request):
contract = Contract()
if request.method == 'POST':
serializer = ContractSerializer(contract, data=request.data)
data = {}
if serializer.is_valid():
serializer.create(validated_data=request.data)
handle_uploaded_file(request.FILES['atasament'])
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def handle_uploaded_file(f):
with open(f.name, 'wb+') as destination:
for chunk in f.chunks():
destination.write(chunk)
My serializer (it's a nested serializer):
class ContractSerializer(serializers.ModelSerializer):
client = ClientSerializer(read_only=False)
termen = serializers.DateField(format='%Y-%m-%d', default=datetime.date.today)
atasament = serializers.FileField(max_length=None, allow_empty_file=True)
class Meta:
model = Contract
fields = (
'pk',
'tip',
'nr_data',
'obiectul',
'termen',
'atasament',
'client',
)
def create(self, validated_data):
client = validated_data.pop('client')
client_instance, created = Client.objects.get_or_create(**client)
contract_instance = Contract.objects.create(**validated_data, client=client_instance)
return client_instance
My model:
class Contract(models.Model):
TIPURI = (
('P', 'Proiectare'),
('E', 'Executie'),
('D', 'Documentatie'),
)
tip = models.CharField(max_length=300, choices=TIPURI)
nr_data = models.CharField(max_length=50)
obiectul = models.TextField()
termen = models.DateField(default=datetime.date.today)
atasament = models.FileField(upload_to='main/documents/', blank=True, null=True)
client = models.ForeignKey(Client, on_delete=models.SET_NULL, null=True)
def __str__(self):
return self.nr_data
class Meta:
verbose_name_plural = "Contracte"
My JS:
$('#form_add').submit(function (event) {
event.preventDefault();
let input_atasament = document.getElementById('input_atasament');
let client_pk = $("#input_clienti").val();
let nr_data = "test";
let tip = $("#input_tip").val();
let obiectul = $("#input_obiectul").val();
let termen = $("#input_termen").val();
const url = \/api/contract-post/`;let client_url = `/api/client-get/${client_pk}`;let client = $.ajax({url: client_url,async: false,dataType: 'json'}).responseJSON;`
let data = new FormData();
data.append('nr_data', "test");
data.append('tip', tip);
data.append('obiectul', obiectul);
data.append('termen', termen);
data.append('atasament', input_atasament.files[0]);
data.append('client', JSON.stringify(client));
var action = function(d) {
console.log(d);
};
$.ajax({
url: url,
headers: {
'X-CSRF-TOKEN': csrftoken,
'Content-Type': 'multipart/form-data',
},
data: data,
type: "POST",
contentType: false,
processData: false,
success: action,
error: action
});
});
And what error I get now:
"Multipart form parse error - Invalid boundary in multipart: None"
Im using angular/typescript where I upload a form of data to my Django REST API. With the data all is correct, because I can log my whole form and I get back all my data. But when it comes to upload the data I get this error:
{src: ["No file was submitted."], tag: ["This field is required."]}
so somehow it does not recognize my data because Im actually submitting data.
frontend code
upload.service
const httpOptions = {
headers: new HttpHeaders({'Content-Type': 'multipart/form-data'})
};
...
uploadPost(src: File, tag: string) {
return this.http.post<any>(`{this.url}/posts/`, {src, tag}, httpOptions);
}
post.page
ngOnInit() {
this.storage.get('image_data').then((imageFile) => {
console.log(imageFile)
this.categoryForm.patchValue({
'image': this.storage.get('image_data')
});
});
this.categoryForm = new FormGroup({
'category': new FormControl('', Validators.compose([
Validators.maxLength(25),
Validators.minLength(1),
Validators.required
])),
'image': new FormControl(null),
});
apiSubmit() {
console.log('logged')
console.log(this.f.image);
this.submitted = true;
if (this.categoryForm.invalid) {
return;
}
this.isLoading = true;
this.loadingEl.present();
this.uploadService.uploadPost(
this.f.image,
this.f.category
)
.pipe(tap(x => this.loadingEl.dismiss())
)
.subscribe(
data => {
this.router.navigate(['one']);
},
error => {
this.error = error;
}
);
}
Django:
models.py
class Post(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='posts', on_delete=models.CASCADE)
src = models.ImageField(blank=False, null=False, editable=False, upload_to=utils.get_file_path,)
date_posted = models.DateTimeField(auto_now_add=True, editable=False)
last_modified = models.DateTimeField(auto_now=True)
when = models.FloatField(blank=True, null=True)
lock = models.BooleanField(default=False)
des = models.CharField(
max_length=100,
validators=[
RegexValidator(
regex='^[-_a-zA-Z0-9\.]+$',
message='only 1 to 20 characters and only letters, numbers, point, minus and underscore are allowed',
),
])
view.py
#swagger_auto_schema(request_body=doc_serializer.CreatePostDummy, responses={201: PostSerializer})
def create(self, request, *args, **kwargs):
"""permission required: authenticated. Note: the schema is not json it's multipart"""
return super().create(request, *args, **kwargs)
doc_serializers.py
class CreatePostDummy(serializers.HyperlinkedModelSerializer):
`enter code here`user = serializers.HyperlinkedRelatedField(required=False, read_only=True, view_name='user-detail')
src = serializers.CharField(required=True, help_text='Not Char but image upload field')
hey i tried this code but still have an error that is Not Null constraint failed i know this is because of my cheque_no that is unique type but how could i remove this error i did not remove my cheque_no is unique because its required.now am getting this problem i want to save these entries in my model.
views.py
#csrf_exempt
def jsdata(request):
table_data = json.loads(request.POST.get('MyData'))
# print(table_data)
r_data = {
'success': True,
}
for data in table_data:
# Since you are just creating objects you don't need to save created object in a variable.
Mvouchar.objects.create(bill_no = data['BillNo'], bill_details=data['BillDetails'],am=data['Amount'])
# r_data['success'] = False
# IMO Views responding to ajax requests should send JsonResponse
if r_data['success']:
r_data['msg'] = 'Data Saved'
else:
r_data['msg'] = 'Not all Data Saved'
return JsonResponse(r_data)
models.py
class Mvouchar(models.Model):
related = models.ForeignKey(Signs, on_delete=models.CASCADE, null=True, blank=True)
bill_no = models.CharField(max_length=8000, null=True, blank=True)
bill_details = models.CharField(max_length=10000, null=True, blank=True)
am = models.CharField(max_length=30000, null=True, blank=True)
cheque_no = models.PositiveIntegerField(validators=[MaxValueValidator(6)], unique=True, help_text='integers only')
def __str__(self):
if self.related:
return self.related.relation.username.title()
else:
return 'no related!'
class Meta:
verbose_name_plural = "Single Cheque Multiple Vouchar Of Users"
javascript
$("#btnjson").click(function () {
var array1 = [];
$("tbody tr").each(function () {
var firstTableData = {};
firstTableData.BillNo = $(this).find('td').eq(0).text();
firstTableData.BillDetails = $(this).find('td').eq(1).text();
firstTableData.Amount = $(this).find('td').eq(2).text();
array1.push(firstTableData);
//}
});
alert(JSON.stringify(array1));
$.ajax({
type: "POST",
url: "/jsondata/",
dataType: 'json',
data: {MyData: JSON.stringify(array1)},
success: function(msg){
alert(msg);
}
});
return false;
} );
});
from django.core.validators import RegexValidator
CHEQUE_REGEX = RegexValidator(
regex=r'^\d{6}$',
message="Cheque Number must be exactly 6 digits"
)
class Mvouchar(models.Model):
...
cheque_no = models.CharField(validators=[CHEQUE_REGEX, ], unique=True, max_length=6, help_text='integers only')
...
If you read the second traceback (The first traceback is from a different view views.mvoucha, and you didn't include that code in the question), you'll find that the problem is this line in your view function.
table_data = json.loads(request.POST.get('MyData'))
What's happening is that request.POST.get('MyData') returns None, which can't be represented as json. That's why the json encoder raises a TypeError.
The request.POST dictionary is used with form data. When you want to parse a json payload, you have to use request.body instead. For example like this:
table_data = json.loads(request.body).get('MyData')
https://docs.djangoproject.com/en/2.1/ref/request-response/#django.http.HttpRequest.POST
I want the queryset of my coin field to change when a user selects "Sell" in the "BuySell" dropdown option with jquery. Once the dropdown is changed I send a Get Request with AJAX, pick that request up in my view and then reload the form, which is where I override the default coin field queryset in my TransactionForm's init method.
This isn't working as expected, nothing happens to change the coin dropdown options and I get no errors (including in the Network tab when I inspect element).
I wonder if this is something to do with the way I'm calling my form here:
form = TransactionForm(user = request.user, coin_price = GetCoin("Bitcoin").price)
and the form init method:
def __init__(self, coin_price = None, user = None, *args, **kwargs):
super(TransactionForm, self).__init__(*args, **kwargs)
if user:
self.user = user
qs_coin = Portfolio.objects.filter(user = self.user).values('coin').distinct()
print("qs_coin test: {}".format(qs_coin))
self.fields['coin'].queryset = qs_coin
FULL CODE:
Forms
class TransactionForm(forms.ModelForm):
CHOICES = (('Buy', 'Buy'), ('Sell', 'Sell'),)
coin = forms.ModelChoiceField(queryset = Coin.objects.all())
buysell = forms.ChoiceField(choices = CHOICES)
field_order = ['buysell', 'coin', 'amount', 'trade_price']
class Meta:
model = Transaction
fields = {'buysell', 'coin', 'amount', 'trade_price'}
def __init__(self, coin_price = None, user = None, *args, **kwargs):
super(TransactionForm, self).__init__(*args, **kwargs)
print("Transaction form init: ", user, coin_price)
if user:
self.user = user
qs_coin = Portfolio.objects.filter(user = self.user).values('coin').distinct()
print("qs_coin test: {}".format(qs_coin))
self.fields['coin'].queryset = qs_coin
Views snippet
def add_transaction(request):
if request.method == "GET":
if request.is_ajax():
print("ajax test")
#print(request.GET.get)
print(request.GET.get('coin'))
print(request.GET.get('buysell'))
view_coin = None
if request.GET.get('coin'):
view_coin = GetCoin(request.GET.get('coin')).price
data = {
'view_buysell': request.GET.get('buysell'),
'view_coin': request.GET.get('coin'),
'view_amount': "test",
'view_price': view_coin
}
form = TransactionForm(user = request.user, coin_price = GetCoin("Bitcoin").price)
return JsonResponse(data)
jquery
$('#id_buysell').on('change', function(){
console.log("buysell");
var $id_buysell = $('#id_buysell').val();
console.log($id_buysell);
$.ajax({
method: "GET",
url: "/myportfolio/add_transaction",
dataType: 'json',
data: { buysell: $id_buysell },
success: function(data, status) {
console.log("SUCCESS:");
console.log(data);
console.log(data['view_buysell']);
},
error: function(response) {
}
});
});
$('#id_coin').on('change', function(){
console.log("test")
console.log("coin change")
var $id_coin = $('#id_coin').find("option:selected").text();
console.log($id_coin);
$.ajax({
method: "GET",
url: "/myportfolio/add_transaction",
dataType: 'json',
data: {coin: $id_coin},
success: function(data, status) {
console.log("SUCCESS:");
console.log(data);
console.log(data['view_buysell']);
$("#id_trade_price").val(data['view_price']);
},
error: function(response) {
}
});
What I was trying to do was unnecessary.
The correct way to achieve this was to convert all of my querysets into lists and then pass them to jquery in JsonResponse. Then I can clear and load these lists as select options in my jquery as and when I need.
updated code:
views
if request.method == "GET":
if request.is_ajax():
print("ajax test")
#print(request.GET.get)
print(request.GET.get('coin'))
print(request.GET.get('buysell'))
view_coin = None
if request.GET.get('coin'):
view_coin = GetCoin(request.GET.get('coin')).price
coin_sell_options = Portfolio.objects.filter(user = request.user).values('coin').distinct()
coin_buy_options = Coin.objects.all()
coin_buy_options = [x.coin for x in coin_buy_options]
coins = [key['coin'] for key in coin_sell_options]
coin_amount = list(Portfolio.objects.filter(user = request.user, coin__in = coins).values_list('amount', flat = True))
coin_amount = [str(x) for x in coin_amount]
print(coin_amount)
data = {
'view_buysell': request.GET.get('buysell'),
'view_coin': request.GET.get('coin'),
'view_amount': "test",
'view_price': view_coin,
'coin_sell_options': list(coin_sell_options),
'coin_buy_options': list(coin_buy_options),
'coin_amounts': coin_amount
}
form = TransactionForm(user = request.user, coin_price = GetCoin("Bitcoin").price)
return JsonResponse(data)
jquery
$('#id_buysell').on('change', function(){
console.log("buysell");
var $id_buysell = $('#id_buysell').val();
console.log($id_buysell);
$.ajax({
method: "GET",
url: "/myportfolio/add_transaction",
dataType: 'json',
data: { buysell: $id_buysell },
success: function(data, status) {
console.log("SUCCESS:");
console.log(data);
console.log(data['view_buysell']);
$("#id_coin").empty();
var items = data['coin_options'];
console.log(items);
$.each(items, function(key, value) {
console.log(value.coin);
$("#id_coin").append(new Option(value.coin));
});
},
error: function(response) {
}
});
});
I am getting NOT NULL constraint error even after passing the data from the form. I am using ajax for posting the data. I checked both the request.POST and network request tab. Both shows the store_contact_number has data in it.
Here is my code
class ListStore(FormView):
form_class = StoreForm
template_name = 'Store/list-store.html'
def form_invalid(self, form):
if self.request.is_ajax():
print('ajax form error', form.errors)
response = {
'error': form.errors
}
return JsonResponse(response, status=400)
else:
return super(ListStore, self).form_invalid(form.errors)
def form_valid(self, form):
success_message = "Thank you for listing your store. We Welcome you."
store, created = Store.objects.get_or_create(merchant=self.request.user)
if self.request.is_ajax():
response = {
'result': success_message
}
return JsonResponse(response)
else:
message.success(self.request, success_message)
return self.render_to_response(self.get_context_data())
class Store(models.Model):
merchant = models.ForeignKey(User, blank=False, null=False)
token = models.CharField(default=token_generator, max_length=20, unique=True, editable=False)
name_of_legal_entity = models.CharField(max_length=250, blank=False, null=False)
pan_number = models.CharField(max_length=20, blank=False, null=False)
registered_office_address = models.CharField(max_length=200)
name_of_store = models.CharField(max_length=100)
email = models.EmailField(blank=False, null=False)
store_contact_number = models.PositiveIntegerField(blank=False, null=False)
$('.list-store-form').on('submit', function(event) {
event.preventDefault(); // preventing from the brwoser default behavior for form submission
var form = $(this);
console.log(form);
$.ajax({
async: true,
url: form.attr('action'),
data: form.serialize(),
type: 'POST',
dataType: 'json',
headers: {
'X-CSRFToken': window.csrf_token
},
success: function(data) {
if (data.form_is_valid) {
alert('Store Listed');
}
// $('.display').html(
// "<div class='ui floating message'> <i class='close icon'></i>" + data.result + '</div>'
// );
},
The error is shown in the store_contact_number as
IntegrityError at /list/store NOT NULL constraint failed:
Store_store.store_contact_number
<QueryDict: {'store_contact_number': ['98489678'], 'email': ['admin#gmail.com'], 'registered_office_address': ['Delhi'], 'csrfmiddlewaretoken': ['kSaPMgNt'], 'name_of_store': ['BigMart'], 'pan_number': ['98713962'], 'name_of_legal_entity': ['BigMart Pvt Ltd']}>
Form
class StoreForm(forms.ModelForm):
class Meta:
model = Store
exclude = ('is_active', 'token', 'merchant',)
You need to add store = form.save() at the start of your form_valid method and get rid of the line store, created = Store.objects.get_or_create(merchant=self.request.user).
EDIT: Actually it's not that simple because the form.save() will also fail due to not having the merchant field specified. You'll need to either need to override either the __init__ or save method of your form so you can pass in the merchant.
Something like:
def save(self, merchant, *args, **kwargs):
commit = kwargs.pop('commit', True)
kwargs['commit'] = False
store = super().save(*args, **kwargs)
store.merchant = merchant
if commit:
store.save()
return store
then call it using:
def form_valid(self, form):
store = form.save(merchant=self.request.user)
success_message = "Thank you for listing your store. We Welcome you."
if self.request.is_ajax():
response = {
'result': success_message
}
return JsonResponse(response)
else:
message.success(self.request, success_message)
return self.render_to_response(self.get_context_data())