Auto fill a field in model via function django - python

I was searching to find a way to fill a field of a model via a function.
example:
def myfunction():
return a_file
class SomeModel(models.Model):
a_field_name=models.FileField(value=my_function())
I some how was thinking to rewrite the save().share with me your idea

Well as per my understanding your question you can try it like this:
def Function(self, parameter: int):
return Models.objects.update_or_create(
variable=parameter
)
Please reply to this message If the issue still persist.

Related

flask-smorest response and return type different

I am learning/working on a Rest Api suing flask-smorest and adding the schema using marshmallow.
Below is the code that I am confused with and have a question.
Schemas.py
class ChildAddressDetailsSchema(Schema):
class Meta:
unknown = EXCLUDE
address_id = fields.String(required=True)
address_type = fields.String(required=True)
is_primary = fields.Boolean(required=True)
class ChildAddressDetailsSchemaList(Schema):
class Meta:
unknown = EXCLUDE
person_list = fields.List(fields.Nested(ChildAddressDetailsSchema))
Endpoint Implementation
#address_blueprint.response(status_code=200, schema=ChildAddressDetailsSchema)
#address_blueprint.get('/child/address/<string:person_id>/list')
def get_child_address(person_id):
person_address_list = PersonAddressModel.query.filter_by(person_id=person_id).all()
person_address_dict = [{'address_id': person_address.address_id,
'address_type': person_address.address_type,
'is_primary': person_address.is_primary} for person_address in person_address_list]
return person_address_dict
The part where I have doubt is even though the schema defined in response of blueprint is
ChildAddressDetailsSchema which is not a list , still I get a valid response.Below is the screenshot of the Insomnia from where I am testing the api.
I was expecting an empty response or a error since the return of the get function get_child_address is a list of dictionary which is not as per the schema. Could someone please help me figuring out on to how to fix the issue and return type is strictly informed. Is this something that needs to be coded or does marshmallow handles this.
It's because you called Blueprint.response() before Blueprint.get(). So do like this.
#address_blueprint.get('/child/address/<string:person_id>/list')
#address_blueprint.response(status_code=200, schema=ChildAddressDetailsSchema)
def get_child_address(person_id):
...
A Python decorator returns a new function that calls the original function. So the order of decorators matters in general. In this case, the implementation of the ResponseMixin.response() of Flask Smorest does not work correctly if the Blueprint.route()(which is equivalent to the Scaffold.get()) is not called before.
You can see that on this and this. If the ResponseMixin.response() is called before the Blueprint.route(), the closure wrapper(created at the decorator() inside the ResponseMixin.response()) will be ignored, because the add_url_rule() will be called with the original endpoint function not the wrapper, at the decorator() inside the Blueprint.route().

How to access nested resources in Flask-Classy?

I've been using Flask-Classy for my server, and it works great. However, I've come across a use case that I haven't seen written about, but it's a pretty common use case, so I'd be shocked if it's not possible.
I have two APIs which I want to nest, and by that I mean I have:
class UsersView(FlaskView):
decorators = [jwt_required()]
route_prefix = '/api/v1/'
def index(self):
...
which is located at http://example.com/api/v1/users and I can access user 1 via http://example.com/api/v1/users/1
Now, how would I write the FlaskView which would let me do something like this?
http://example.com/api/v1/users/1/devices/3
When I try embedding the resource id in the route_prefix, I get a keyword argument error:
class DevicesView(FlaskView):
decorators = [jwt_required()]
route_prefix = '/api/v1/users/<user_id>/'
def index(self):
...
TypeError: index() got an unexpected keyword argument 'user_id'
One last point is that I can, naturally, use kwargs:
route_prefix = '/api/v1/users/<user_id>/'
def test(self, **kwargs):
print kwargs['user_id']
http://example.com/api/v1/users/103/devices will spit out '103', however, using kwargs feels kinda hokey. Is there a better way?
I put the top-level placeholder in the route_base in the register call.
For example:
class UsersView(FlaskView):
#route('/', methods=['GET'])
def index(self):
pass
class DevicesView(FlaskView):
#route('/', methods=['GET'])
def index(self, user_id):
pass
UsersView.register(app, route_base='/users', trailing_slash=False)
DevicesView.register(app, route_base='/users/<user_id>/devices', trailing_slash=False)
Now the user_id comes in as the first parameter on every method in DevicesView.
In case you haven't found a solution as yet...The answer is pretty simple here you need to have the index defined as:
def index(self, user_id):
you have to do this since you would want to know the base resource through which to access the required resource. In your example devices index would give me a list of all devices belonging to the user. In order to get this information you will first need to know which user's devices are being asked for

get_absolute_url() django docs example returns syntax error

I have this model:
class Invite(models.Model):
user = models.OneToOneField(User)
cookie = models.SlugField()
token = models.SlugField()
def __unicode__(self):
return u"%s's invite" % (self.user)
def get_absolute_url(self):
return (reverse('invite'), args=[self.token])
The final line, return (reverse('invite'), args=[self.token]), returns a syntax error. When I remove the args= part, it seems to work fine though.
I have three questions regarding this:
Why is arg= in this example returning a syntax error while the django docs uses a similiar example here.
How am I supposed to successfully key into this list/check the contents of the list without assigning it a name?
Does return require () to work with more than one variable? Since im using python 2.7.5 wouldn't a simple , suffice?
Thanks!
You have the closing parenthesis in the wrong place. args is an argument to reverse.
return (reverse('invite', args=[self.token]))

Django-import-export - import of advanced fields?

For a Django model I'm using django-import-export package.
If need to export more then just available model fields, like properties or custom fields, new can be added with import_export.fields.Field class and optionally dehydrate_<field> method.
from import_export import resources, fields, instance_loaders
class ProductResource(resources.ModelResource):
categories = fields.Field()
price = fields.Field(attribute='unit_price')
class Meta:
model = Product
def dehydrate_categories(self, product):
return ';'.join(
'/%s' % '/'.join([c.name for c in cat.parents()] + [cat.name])
for cat in product.category.iterator() )
It does work well, but only for exporting. What about import, the reverse process ? Is there some counterpart to dehydrate_ method ?
So far I've overridden get_or_init_instance method:
class ProductResource(resources.ModelResource):
def get_or_init_instance(self, instance_loader, row):
row['unit_price'] = row['price']; row.pop('price')
return super(ProductResource, self).get_or_init_instance(instance_loader, row)
but doubt this is the right way.
Would appreciate any hint how to handle imports of custom fields.
You can override import_obj instead. See Import workflow for more details.
Another approach is to subclass Field and override export and save methods and do all required data manipulation in a field.
I know this is very old but I came across the same problem and this is how I fixed it (based on the direction the original asker was heading).
First, you can add any custom/modified fields you need by overriding the 'before_import_row' function, like so:
def before_import_row(self, row, **kwargs):
row['extra_info'] = 'Some Info'
return super(RetailLocationResource, self).before_import_row(row, **kwargs)
Then you can pass this into your instance by overriding get_or_init_instance like so:
def get_or_init_instance(self, instance_loader, row):
instance, bool = super(RetailLocationResource, self).get_or_init_instance(instance_loader, row)
instance.extra_info = row['extra_info']
return instance, bool
Hope this helps anyone!

How can I use a Django F() expression in TastyPie's hydrate cycle?

I have a model with a version number in it. I want it to self-increment when new data is posted with an existing id via TastyPie. I'm currently doing this via the hydrate method, which works as long as two users don't try to update at once:
class MyResource(ModelResource):
...
def hydrate_version(self, bundle):
if 'id' in bundle.data:
target = self._meta.queryset.get(id=int(bundle.data['id']))
bundle.data['version'] = target.version+1
return bundle
I'd like to do this more robustly by using Django's F() expressions, e.g.:
def hydrate_version(self, bundle):
if 'id' in bundle.data:
from django.db.models import F
target = self._meta.queryset.get(id=int(bundle.data['id']))
bundle.data['version'] = F('version')+1
return bundle
However, this gives me an error:
TypeError: int() argument must be a string or a number, not 'ExpressionNode'
Is there a way to more robustly increment the version number with TastyPie?
thanks!
I would override the save() method for your Django Model instead, and perform the update there. That has the added advantage of ensuring the same behavior regardless of an update from tastypie or from the django/python shell.
def save(self, *args, **kwargs):
self.version = F('version') + 1
super(MyModel, self).save(*args, **kwargs)
This has been answered at github here, though I haven't tried this myself yet. To quote from that link:
You're setting bundle.data inside a hydrate method. Usually you modify bundle.obj in hydrate methods and bundle.data in dehydrate methods.
Also, those F objects are meant to be applied to Django model fields.
I think what you want is:
def hydrate_version(self, bundle):
if bundle.obj.id is not None:
from django.db.models import F
bundle.obj.version = F('version')+1
return bundle

Categories