开发者

How do I add a temporary field to a model in Django?

I'm developing a web-app where the user can create multiple related elements and then save those elements to a database. The webapp has no idea of what the primary keys will be in the database so it assigns each element a UUID. These UUIDs are saved with each element in the database. When the webapp sends the data to the webserver to be placed in the database it encodes everything using JSON. The JSON is then deserialized by the webserver using serializers.deserialize('json', DATA). However, some of the models have foreign keys, which are sent in the JSON payload as references to the UUIDs of the associated elements rather than the database ids. For example, we may have a simple link object:

class Link(models.Model):
    uuid = models.CharField(max_length=32)
    source = models.ForeignKey(Node, related_name='source')
    target = models.ForeignKey(Node, related_name='target')

If the source had an id value of 2 and the target had an id value of 12, this would be serialized to JSON as this:

{"uuid": "[some long uuid]",
 "source": 2,
 "target": 12}

However, because in this case we don't know the database ids of source and target, probably because they haven't been set yet, the best I can do is pass in the UUID's like this:

{"uuid": "[some long uuid]", 
 "sourceuuid": "[uuid of source]", 
 "targetuuid": "[uuid of target]"}

Unfortunately, this raises an exception of FieldDoesNotExist: Link has no field named u'sourceuuid' when I call serializers.deserialize on the data.

I'd like to find a way that I can pass the UUID's in and then have the database fill in the id's once it's saved the appropriate parts or look them up where necessary. I don't want to save sourceuuid and targetuuid in the database as it's a lot less space to save an integer and the indicies should be faster too.

So, what I'm looking for is a temporary field. One that I can instantiate and reference, but that is never saved back to the database. Any ideas on how I would create such a thing?

UPDATE with more clarification

Thanks for the help so far, I'm aware that they're Python objects and I can assign arbitrary fields to the objects. However, the problem is that serializers.deserialize('json', INDATA) throws errors.

For reference here's a hunk of JSON that the deserializer likes, it has the foreign keys with their IDs:

ser='''[{"pk": 1, "model": "myapp.link", 
         "fields": {"uuid": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
                    "source": 2,
                    "target": 12}}]'''
serializer.deserialize('json',ser)

However, what 开发者_如何学编程I can provide is this:

ser='''[{"pk": 1, "model": "myapp.link",
         "fields": {"uuid": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
                    "sourceuuid": "11111111-2222-3333-4444-555555555555",
                    "targetuuid": "66666666-7777-8888-9999-000000000000"}}]'''
serializer.deserialize('json',ser)
FieldDoesNotExist: Link has no field named u'sourceuuid'

The reason I need to dummy field to be an actual field is because the deserialize requires actual fields.


I'm not sure exactly what you're trying to do. But remember that Django models are just Python objects - and Python objects are completely dynamic. So it is perfectly valid to do obj.uuid = whatever even if there is no uuid field defined on the model.


You can define a foreign key to non-materialized django model which stores the info you require.

To do so, in the new model to which foreign key (or a OnetoOne Key) is defined, just place

class _meta:
    managed = False


I don't know of such a temporary field. It would be nice :)

But my suggestion is this: In the view that receives the JSON and makes it into objects, you check the attributes. You create an object, with only the "real" attributes (not foreign keys or M2M). You can assign arbitrary attributes to them (instance.arbitrary_attribute = something) but you won't get the nice lookup mechanism (Model.objects.filter(...)). After you created all the objects, you loop over the objects again, and for each FK you look up the object that has the link's UUID, and link to it (using the instance.id).


You can try creating plain python attributes, they are not saved to db. Like:

class Link(models.Model):
    sourceuuid = None


Why not just use UIDS as primary keys ?

set primary_key to True

class Node(models.Model):
    uuid = models.CharField(max_length=32, primary_key=True)
    [...]


class Link(models.Model):
    uuid = models.CharField(max_length=32, primary_key=True)
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜