Dynamic forms for end users in django - python

I'm creating a django project where any user can create forms with any number of fields. For example user A could create the follow form:
Name of field: Field_1 - Type: Text
Name of field: Field_2 - Type: Date
Name of field: Field_3 - Type: File
And user B could create:
Name of field: name - Type: Text
Name of field: phone - Type: Text
Look that the user need to say to the program the name of the field and type. Since is a dynamic way to create any number of forms and any number of field for each forms. What would be the most efficient way to create the database model?
Take into account that the program does not know the name of the field until the user send it. So in the views, I can't process it with exact name of fields.

If you create two tables in your database you can handle this pretty easily. Have one table that stores the serialized form as JSON, and another table that holds the form data (and links to the form definition).
How you serialize it is up to you but it would look something like this:
Serialized form
{
"fields": [
{
"name": "field_name"
"type": "text"
"attrs": []
}
]
}
Serialized data (ForeignKey's to above form)
{
"data": {
"field_name": "value"
}
}
The advantage to doing this is you aren't creating models on the fly, and your database stays a lot cleaner because you won't have tons of tables lying around.

Related

How to send JSON format data in postman to django models that have a foreign key to another model?

I have tried to send a POST request to django views.py file using postman.
It was working when I sent a POST and GET request to django models that haven't ForeignKey field. However, when I tried to send a POST request to a django model that have a ForeignKey field, it wasn't working. My question is how to send a JSON format data using postman to django models that have a Foregin Key field.
The models are as follows:
class Article(models.Model):
authorId=models.CharField(max_length=100)
authorResidence=models.CharField(max_length=100)
communtId=models.CharField(max_length=100)
content=models.TextField()
contentId=models.CharField(max_length=100)
source=models.CharField(max_length=100)
timestamp=models.IntegerField()
title=models.CharField(max_length=100)
class Interactions(models.Model):
userId=models.CharField(max_length=100,unique=True)
location=models.CharField(max_length=100)
eventType=models.IntegerField(unique=True)
articleId=models.ForeignKey(Article,on_delete=models.CASCADE)
communityId=models.CharField(max_length=100)
source=models.IntegerField()
timestamp=models.IntegerField()
I have tried in this way (in postman):
{
"userId":"153344",
"location":"Ethiopia",
"eventType":"1",
"articleId":"67353536",
"communityId":"1234567",
"source":"1",
"timestamp":"123456"
}
As you can see the articleId is a foreignKey field.
Here is the output:
{
"articleId": [
"Invalid pk \"67353536\" - object does not exist."
]
}
Django models have id field by default so the primary key of the models will be the id. if you use foreign key in Django model, it references the primary key of the referenced model.
Here what you face is, you are referencing non existing id - meaning wrong id, or, no instance of article exist with that id.
step 1: get all the articles with postman
step 2: copy one of the id's of the articles
step 3: paste that id to articleId like shown below, if id is 2 then you should right like this
{
"userId":"153344",
"location":"Ethiopia",
"eventType":"1",
"articleId":"2",
"communityId":"1234567",
"source":"1",
"timestamp":"123456"
}
You are getting this error because the articleId you submitted does not exist. If there is an article with an articleId value you sent, you will not get an error. Before the data you sent is saved, it is checked to see if there is an article with an articleId value. You cannot link to an object that does not exist.

Reset field in Django Admin page

Imagine, that I have model and in the Django admin form I can update my fields. I want to implement something like: update one field and the second one will be reset in admin form in real time (I'll hope it can help real admin in the future do not forget redefine this second field, because it's very important in my situation). Is that possible to implement something like that without custom admin form?
To achieve this without a custom template or form, you can just include a custom script, for example:
Assuming you have an app named people and it has a model called Person with two fields first_name and last_name:
Include javascript into the admin page
# people/admin.py
from django.contrib import admin
from people.models import Person
class PersonAdmin(admin.ModelAdmin):
class Media:
js = ('people/js/person.js',)
admin.site.register(Person, PersonAdmin)
Then create the person/js/person.js script:
'use strict';
//execute when everything is loaded
window.addEventListener('load', () => {
let first_field = document.querySelector('form input[name=first_name]'); //field name
let second_field = document.querySelector('form input[name=last_name]'); //field name
//just when the fields are found (add or update)
if(first_field && second_field) {
//here you can implement whatever logic you want
first_field.addEventListener('input', () => {
second_field.value = '';
});
}
});
Now every time the first_name changes last_name will be cleared. This idea can be extended to do more interesting things.

Django Model Table Input

I am trying to insert a data table in my current project. I was wondering if it is possible to insert one whole table inside one particular Django Model. If I let the user fill this table, like in the example below:
How could I send that data into my model after POST?
As you stated in the comment under the question, your table has got fixed fields which should correspond to your already prepared database model - each table column is a separate model attribute. So the only thing you need to do is send each row input by the user as a separate entry in the JSON POST request which your code will convert into a model class instance and save it to the database. The JSON sent in the POST request could look something like this:
{
"table_entries": [
{
"sku": "22A",
"name": "2B",
"description": "2C",
"price": "2D",
"size": "2E"
},
{
"sku": "3A",
"name": "3B",
"description": "3C",
"price": "3D",
"size": "3E"
},
...
]
}
The functionality you're asking for is quite well covered in the Django REST Framework (DRF), a toolkit to build Web APIs. The general pipeline will be:
Receive the POST request in views.py
Use a model serializer that you need to prepare to convert the request data to a Python object
Save this object in the database
So the views could look something like that (based on examples from the DRF views docs):
from myapp.models import Table
from myapp.serializers import TableSerializer
from rest_framework.views import APIView
from rest_framework.response import Response
class TableView(APIView):
"""
Create a new entry in the Table.
"""
def post(self, request, format=None):
table_entries = request.data["table_entries"]
for entry in table_entries:
# serialize each row
serializer = TableSerializer(data=entry)
if serializer.is_valid():
# you can store the objects in some list and if the're all fine
# use serializer.save() for each of them to save them into the db
else:
# At least one of the entries data is corrupted. You probably want
# to reject the whole request
# ...
This is to show you the general workflow, because the question is quite broad. To go further into details I strongly advise to have a look into the DRF tutorial, as it covers well the topic.

Return JSON field in GAE ProtoRPC

I want to construct an arbitrary json like this and return to the user dynamically
{
"items":[
{
"available":"2",
"capacity":"2",
"name":"name2",
"entityKey":"dkfhakshdfh"
},
{
"available":"1",
"capacity":"1",
"name":"name1",
"entityKey":"dkfhaksdfef"
}
],
"kind":"theatreManagement#show",
"etag":"\"asdfasdfasfasfahih\""w
}
But there seems to be no fields to pass in the json. The fields available are like StringField, BytesField, etc.,
How to return a json object?
OpenAPI services such as those created by the Google Cloud Endpoints Framework need to specify exactly what they return. You should define a message containing fields like 'items', 'kind', 'etag', and so on.

flask nested post data

I'm trying to build in a way to handle a large number of posted options, e.g.
my_posted_data = {"item": "value", "item_options":{"a":2, "b":2} }
This would be coming from somewhere else in an api situation where I'm not in control of the environment and it is simulated for now. I'll post that through the requests library; and moving server-side, I try to get this from the route/view in my application. request.form gets read into a variable(form) which is passed to a task_manager queue. In the task I'll try to do:
options = form.get("item_options", None)
options always ends up as NoneType. Why is this not selecting the dict(like) value of {"a": 2, "b": 2}? I guess I'm doing it wrong, but what at this point I am unable to pinpoint.
Based on this scant picture I've provided, how do I post and and retrieve nested values with Flask request in the most effective way?
EDIT: I had to go a different way, using JSON data because I realized for the situation that is best, the form is more for user input from an html page, and this is something that requires a different approach.
By using Flask-WTF with Field Enclosures in WTForms, you can easily handle nested post data.
class ListField(Field):
def process_formdata(self, valuelist):
self.data = valuelist
class ItemsForm(Form):
a = StringField()
b = StringField()
class TestForm(FlaskForm):
item = StringField()
product = ListField(FormField(ItemsForm))
Since FormField add default prefix, the JSON will looks like
{
"item": "value",
"product": {
"product-a": "string",
"product-b": "string",
}
}

Categories