Upload directory path to database for multiple files - flask

I am using flask-admin, so I can add entries to the database without having to interact with it directly. I can currently save the name of one image file with my code. I would like to save the name of the directory instead so I can have multiple images under a folder.
base_path = op.join(op.dirname(__file__), 'static/pictures')
class listingsModelView(ModelView) :
# ModelView Functionality
page_size = 20
form_columns = ['Location', 'City', 'State', 'Zip',
'Price', 'Bedroom', 'Bathroom', 'SquareFeet',
'Description', 'Pictures']
column_labels = dict(Location="Street Address", City='City', State='State',
Zip='Zip Code', Price='Price', Bedroom='Bedroom', Bathroom='Bathroom',
SquareFeet='Square Feet', Description='Description', Pictures='Pictures')
form_overrides = dict(Pictures=FileUploadField)
form_args = {
'Pictures': {
'label': 'File',
'base_path': base_path,
'allow_overwrite': True
}
}
is there any way I can modify what I currently have to store a directory path instead of a single file name?

Related

How to add collation in indexes for mongodb?

I work with Mongoengine in Django, got task to sort by first_name, last_name fields ignoring case and leading whitespaces
that is why add collation in queryset:
collation = dict(
locale='en',
caseLevel=False,
caseFirst='off',
strength=3,
numericOrdering=True,
alternate='shifted',
maxVariable='space',
backwards=False,
)
return queryset.collation(collation).order_by('-is_stocked', 'brand', 'model')
Unfortunetly, my queryset takes too long time
I want to speed up it, so start to read about mongodb indexes, but don't understand how add it properly, I tried this:
models.py
class Car(UpdatedAtTimestampMixin, Document):
model = fields.StringField(null=True, db_field='model')
brand = fields.StringField(null=True, db_field='brand')
is_stocked = fields.BooleanField(db_field='isStocked')
meta = {
'collection': 'books',
'strict': False,
'indexes': [
['-is_stocked', 'brand', 'model'],
],
}
The main question is How to include collation in indexes? And will it work with null=True Field?
class Car(UpdatedAtTimestampMixin, Document):
model = fields.StringField(null=True, db_field='model')
brand = fields.StringField(null=True, db_field='brand')
is_stocked = fields.BooleanField(db_field='isStocked')
meta = {
'collection': 'books',
'strict': False,
'indexes': [
{'fields': ['-is_stocked', 'brand', 'model'], 'collation': collation},
],
}

Django (drf) add new parameters/fields only for output with existing queryset(used for output) from database

I am working on a project on drf, where I need to fetch data from database (in thousands), and display selective fields in response.
models.py
class TblDemo(models.Model):
tbl_id = models.IntegerField()
tbl_name = models.CharField(max_length=50)
tbl_size = models.CharField(max_length=50)
tbl_height = models.Charfield(max_length=50)
tbl_material = models.Charfield(max_length=50)
class Meta:
managed = True
db_table = 'tbl_demo'
views.py
class data_fetch(viewsets.ViewSet):
def tbl_list(self, request, format=None)
serializer = Tbl_Serializer_input(data=request.data)
if serializer.is_valid():
queryset1 = tbl_name.objects.all()
queryset2 = queryset1.filter(tbl_name=request.data.get("title"))
serializer = Tbl_Serializer_output(queryset2, many=True)
return Response(serializer.data)
serializers.py
class Tbl_Serializer_input(serializers.Serializer):
title = serializers.CharField(required=True, max_length=50)
refer_no = serializers.CharField(required=True, max_length=50)
class Tbl_Serializer_output(serializers.Serializer):
tbl_id = serializers.CharField(max_length=50)
tbl_name = serializers.CharField(max_length=50)
tbl_size = serializers.CharField(max_length=50)
tbl_height = serializers.Charfield(max_length=50)
output
[
{
"tbl_id":"1",
"tbl_name":"white table",
"tbl_size": "square",
"tbl_height": "2 feet"
},
{
"tbl_id":"2",
"tbl_name":"black table",
"tbl_size": "square",
"tbl_height": "3 feet"
},
.......and so on.
but now, requirement is that I can't change database/model, but need to add some more fields like ("refer_no", "material" and "density", which is overall same in every cases) and with every object in queryset, which will not be stored in database, but it is only for response/output.
so, after adding new parameters my output will be like :
where, "refer_no" is taken directly from input to show output fields.
and "material" and "density" can't be added in database, just need to be hardcoded in middle.
new_output
[
{
"tbl_id":"1",
"refer_no":"abadadf",
"tbl_name":"white table",
"tbl_size": "square",
"tbl_height": "2 feet",
"density": "350gm/in"
"material": "tek wood"
},
{
"tbl_id":"2",
"refer_no":"abadadf",
"tbl_name":"black table",
"tbl_size": "square",
"tbl_height": "3 feet",
"density": "350gm/in",
"material": "tek wood"
},
.......and so on.
I have actually added new fields with query set from database, but when it went for serialization, it is showing circular loop error.
Please help.
You could process the data inside the serializer using the to_representation method.
For instance:
class ModelSerializer(serializers.ModelSerializer):
...
def to_representation(self, instance):
to_repr = super().to_representation(instance)
# add here the "refer_no", "material" and "density" key-value per object
return to_repr

Django forms - is there a way to dynamically edit a FilePathField?

I have a django form which I am using to access a directory. However I would like to access two different directories based on a given input, but have one FilePathField.
As an example - I have two panels - 'panel1' and 'panel2'. The directory I would like to access is the analysis directory of each of these panels as such:
/path/destination/panel1/analysis/
/path/destination/panel2/analysis/
In each of these analysis directories are directories starting with "Experiment" which I would like a user to be able to choose to obtain some results.
I have my form:
class RunUploadForm(forms.Form):
directory_path = forms.FilePathField(
path='/path/destination/panel1/analysis',
required=True,
allow_folders=True,
allow_files=False,
recursive=True,
match="Experiment*",
label="Pick folder for results:"
)
class Meta:
fields = ('directory_path',)
This only allows the user to access panel1 directory as it is hardcoded into the path arg. Is there a way to dynamically change this path argument, maybe with a choicefield?
One way of doing so would be to pass the path as an argument to the __init__ method of the form, for example:
class RunUploadForm(forms.Form):
directory_path = forms.FilePathField(
path='/path/destination/panel1/analysis',
required=True,
allow_folders=True,
allow_files=False,
recursive=True,
match="Experiment*",
label="Pick folder for results:"
)
class Meta:
fields = ('directory_path',)
def __init__(self, *args, **kwargs):
path = kwargs.pop('path', 'somedefaultvalue')
super().__init__(*args, **kwargs)
self.fields['directory_path'] = forms.FilePathField(
path=path,
required=True,
allow_folders=True,
allow_files=False,
recursive=True,
match="Experiment*",
label="Pick folder for results:"
)
You need to crate a new instance of FilePathField because choices for this kind of field are generated on __init__

model field named url and django rest framework url

I started to use the great django-rest-framework days ago.
I'm not able to solve this simple issue.
My model contains a models.URLField named url.
My serializers.py file:
class ModelSerializer(serializers.HyperlinkedModelSerializer):
owner = serializers.Field(source='owner.username')
class Meta:
model = Model
fields = ('url', 'owner', 'title', 'abstract', 'category', 'position', 'param1')
Checking the API result the field 'url' is populated with model.URLField.
"results": [
{
"url": "http://www.web.com",
"owner": "me",
"title": "title of the stuff"
}
Instead I would like to have
"results": [
{
"url": "http://localhost:8000/en/apiv1/maps/4/",
"url_in_model": "http://www.web.com",
"owner": "me",
"title": "Forest fire"
}
How can I solve?
Thanks
It may be considered poor form (I am by no means a pro programmer or rest_framework expert), but I believe you can add extra context to the serialized output:
http://django-rest-framework.org/api-guide/serializers.html#specifying-fields-explicitly
class AccountSerializer(serializers.ModelSerializer):
url = serializers.CharField(source='get_absolute_url', read_only=True)
groups = serializers.PrimaryKeyRelatedField(many=True)
class Meta:
model = Account
Extra fields can correspond to any property or callable on the model.
So in the above the field 'get_absolute_url' must be in the 'Account' model.
In your case (I think) you could do this:
class ModelSerializer(serializers.HyperlinkedModelSerializer):
owner = serializers.Field(source='owner.username')
url_in_model = serializer.Field(source='url')
class Meta:
model = Model
fields = ('url', 'url_in_model', 'owner', 'title', 'abstract', 'category', 'position', 'param1')
Of course you would pick the field type that suits.
I haven't had the chance to test this, so there is the chance that using 'url' as your source causes an issue and you may want to name your model field something else - apologies if that is the case and I have wasted your time.
Hope I have helped.
The accepted answer didn't work for me in DRF 3. I got my model's url data for both url and url_in_model. To get the correct url value from DRF, it looked like:
class AccountSerializer(serializers.ModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='account-detail')
url_in_model = serializer.URLField(source='url')
class Meta:
model = Account
account-detail should be replaced with whatever view corresponds to a single Account.
I personally prefer to set the default hyperlinked field to another name altogether.
You can do this via the URL_FIELD_NAME setting.
Source: http://www.django-rest-framework.org/api-guide/serializers/#changing-the-url-field-name
e.g: URL_FIELD_NAME = 'key' (default is 'url')
The easiest way to avoid the conflict is to set URL_FIELD_NAME in settings.py like:
REST_FRAMEWORK = {
"DEFAULT_AUTHENTICATION_CLASSES": [
"rest_framework.authentication.SessionAuthentication",
"rest_framework.authentication.BasicAuthentication",
],
"DEFAULT_PERMISSION_CLASSES": ["rest_framework.permissions.IsAuthenticated"],
"URL_FIELD_NAME": "api_url", // <---- add this
}
the above answers are not precise.It is simply to control the name of url(default is 'url') by using the key "url_field_name".
class UserSerializer(serializers.ModelSerializer):
url_field_name='test-url'
class Meta:
model = UserInfo
extra_kwargs = {
'test-url': {
'view_name': '<your view name defined on urls.py>',
'lookup_field': '<lookup_field>',
'lookup_url_kwarg': '<lookup_url_kwarg>'
}
}
fields = ['test-url'] #remember include your defined url name
the source code of ModelSerializer in serializer.py
def get_fields(self):
"""
Return the dict of field names -> field instances that should be
used for `self.fields` when instantiating the serializer.
"""
if self.url_field_name is None:
self.url_field_name = api_settings.URL_FIELD_NAME
assert hasattr(self, 'Meta'), (
'Class {serializer_class} missing "Meta" attribute'.format(
serializer_class=self.__class__.__name__
)
)
assert hasattr(self.Meta, 'model'), (
'Class {serializer_class} missing "Meta.model" attribute'.format(
serializer_class=self.__class__.__name__
)
)
if model_meta.is_abstract_model(self.Meta.model):
raise ValueError(
'Cannot use ModelSerializer with Abstract Models.'
)
declared_fields = copy.deepcopy(self._declared_fields)
model = getattr(self.Meta, 'model')
depth = getattr(self.Meta, 'depth', 0)
Nginx needs to be configured correctly, put your ip in the PROXY_PASS
location / {
proxy_pass http://127.0.0.1:8003;
proxy_set_header X-Forwarded-Host $server_name;
proxy_set_header X-Real-IP $remote_addr;
}
Change http://127.0.0.1:8003 by http://this-is-my-ip-address.com/[port]

related-name : link objects instead of their url?

I'm using Django.
Here is my .json file :
{
title: "foo",
id: 4,
taskhistories: [
"http://localhost:8000/taskhistories/33/",
"http://localhost:8000/taskhistories/34/"
],
url: "http://localhost:8000/tasks/4/"
}
I have tasks that have one-to-many taskhistories. The thing is, I use related-name in the definition of my TaskHistory model to display it in the tasks directory of my API :
class TaskHistory(models.Model):
task = models.ForeignKey(Task, related_name='taskhistories')
But, in the API, it doesn't display the taskhistory itself but the url to the API page of the taskhistory. How can I directly display a list of my task histories in my task API page instead of just urls ?
Edit : Adding the serializer :
class TaskSerializer(serializers.HyperlinkedModelSerializer):
projectname = serializers.Field(source='project.name')
projectid = serializers.Field(source='project.id')
class Meta:
model = Task
fields = ('title', 'description', 'status', 'created_on', 'duration',
'id', 'projectid', 'projectname', 'taskhistories')
Add TaskSerializer:
taskhistories = serializers.RelatedField(many=True)
that will use your unicode method of TaskHistory Model for display. For further references see here
I think I answered your question.