Extending protorpc StringField - python

I would like to write custom validation for some fields in ProtoRPC messages.
The documentation says, that protorpc.messages.Field class cannot be extended by developers.
Does it mean I should not extend StringField?
E.g. StringField does not ensure that string is non-empty.
I've checked, and my custom string class with my validate_element method works as expected.
Is there any reason, I should not do that?

You can subclass protorpc.messages.MessageField to create a custom Field. See the DataTimeField source code for an example of this.

Related

MongoEngine validate choices within ListField

Is it possible to use the choices option of a field object (in my case StringField) which is being used as an argument to ListField?
I’m trying to define a property on a collection like this:
my_list_property = ListField(StringField(choices=CHOICES), required=True)
and I am wanting MongoEngine to validate that the elements of my_list_property are in CHOICES on save.
EDIT - from comments
Having looked at the MongoEngine code, ListField inherits from ComplexBaseField. The validate method on ComplexBaseField calls validate on self.field (in my case, this is StringField).
StringField inherits from BaseField. BaseField.validate just passes.
When a BaseField e.g. StringField is the parent field, BaseField._validate is called as opposed to BaseField.validate, and ._validate does validation on choices. I wonder if ComplexBaseField.validate should actually call self.field._validate instead?

Get Python type of Django's model field?

How can I get corresponding Python type of a Django model's field class ?
from django.db import models
class MyModel(models.Model):
value = models.DecimalField()
type(MyModel._meta.get_field('value')) # <class 'django.db.models.fields.DecimalField'>
I'm looking how can I get corresponding python type for field's value - decimal.Decimal in this case.
Any idea ?
p.s. I've attempted to work around this with field's default attribute, but it probably won't work in all cases where field has no default value defined.
I don't think you can decide the actual python type programmatically there. Part of this is due to python's dynamic type. If you look at the doc for converting values to python objects, there is no hard predefined type for a field: you can write a custom field that returns object in different types depending on the database value. The doc of model fields specifies what Python type corresponds to each field type, so you can do this "statically".
But why would you need to know the Python types in advance in order to serialize them? The serialize modules are supposed to do this for you, just throw them the objects you need to serialize. Python is a dynamically typed language.
An ugly alternative is to check the field's repr():
if 'DecimalField' in repr(model._meta.get_field(fieldname)):
return decimal.Decimal
else:
...
However, you have to this for all types seperatly.

Can django-tastypie display a different set of fields in the list and detail views of a single resource?

I would like for a particular django-tastypie model resource to have only a subset of fields when listing objects, and all fields when showing a detail. Is this possible?
You can also now use the use_in attribute on a field to specify the relevant resource to show the field in. This can either be list or detail, or a callback.
You would have to specify all fields in the actual ModelResource then override the get_list method to filter out only the fields you want to show. See the internal implementation of get_list on Resource to see how to override it.
However, note this will only apply on GET requests, you should still be able to POST/PUT/PATCH on the resource with all fields if you authorization limits allow you to do so.
In a nut shell, you want to hot patch the internal field list before full_dehydrate is called on all ORM objects returned by obj_get_list.
Alternatively, you can let the full dehydrate mechanism take place and just at the end of it remove the fields you don't want to show if you don't care about squeezing out as much as speed as possible. Of course you would need to do this only if the URL is invoked as a consequence of get_list call. There is a convenience method for this alter_list_data_to_serialize(request, to_be_serialized).
Just do:
class SomeResource(Resource):
class Meta(...):
...
field_list_to_remove = [ 'field1', 'field2' ]
...
def alter_list_data_to_serialize(request, to_be_serialized):
for obj in to_be_serialized['objects']:
for field_name in self._meta.field_list_to_remove:
del obj.data[field_name]
return to_be_serialized
There is an open issue for this on GitHub, with a number of workarounds suggested there.
Can also use the dehydrate(self, bundle) method.
def dehydrate(self, bundle):
del bundle.data['attr-to-del]
return bundle

Django ManyToMany field transformation on a ModelForm

I have this manytomany field in my model that I have overridden with a CharField that receives a csv list of the second models name attribute.
class PostForm(ModelForm):
tests = CharField(label="tests")
class Meta:
model = Post
fields = ('title','body')
def clean_tests(self):
# Here I clean, create or retrieve and return a list of Test objects.
Now, saving and validating is alright with this code, everything works, my problem comes when I create the PostForm with an existing instance, like PostForm(instance=current_post).
The CharField should contain a csv list but it contains nothing, obviously this happens because there is no conversion happening from Test object list to test name list, the problem is I do not know where to put that code, I see no method I could override to get this done, i've looked into initial data and default properties of fields.
I'm not sure if there's a method you could override to do this -- from a look at the BaseModelForm constructor though, it looks perfectly okay to specify both the instance and initial keyword arguments together -- the instance is converted into a dict (subject to the fields and exclude options in Meta), and that dict's update method is called with initial. Something like this should work:
# build your csv list somehow (just speculation here)
tests = ','.join(test.name for test in current_post.tests.all())
form = PostForm(instance=current_post, initial={'tests': tests})

Use of unicode in Django

Why is a unicode function required in models.py?
i.e,
def __unicode__(self)
return sumid;
It's not. If you define a __unicode__() method, Django will call it when it needs to render an object in a context where a string representation is needed (e.g. in the model's admin pages).
The documentation says:
The __unicode__() method is called
whenever you call unicode() on an
object. Since Django's database
backends will return Unicode strings
in your model's attributes, you would
normally want to write a __unicode__()
method for your model.
I'm a bit new to Django, but I think I can help you.
First, it isn't exactly required, but it's a really good idea. The field is used to create representations of your objects in the Django admin (otherwise they all have the same name :-P) and when you print out an object to your terminal window to see what's going on (otherwise you get a generic mostly useless message).
Second, from what you wrote, it looks like you're new to Python. I recommend reading some Python tutorials on class syntax. Also, semicolons aren't necessary in this language. The correct syntax for creating the unicode method is:
class Foo(models.Model):
# Model fields go here
def __unicode__(self):
return u"%i" % self.sumid
The __unicode__ method has double underscores because it is a special function, namely when the builtin function unicode( obj ) is called on it, it returns a unicode string representation of that object (sort of like java's ToString).
I hope this helps :-)
I think the others have given some detailed explanations that should be more than enough for you. But here's a straightforward answer: __unicode__() is equivalent to toString() in Java (and many other languages)

Categories