Referencing objects by id

View: New views
8 Messages — Rating Filter:   Alert me  

Referencing objects by id

by Gerard Petersen-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi All,

1st, forgive my n00bishness. I'm on Grok for a net time of only a couple of days now. Anyway ..

Im trying to get my head around storing objects (Customers that is) based on customer id's. An url should look like this:

        http://localhost:8080/gpadmin/1

It was previously (working and) based on company name and used to look like this:

        http://localhost:8080/gpadmin/Customer

I use zope's interface and schema to work with the model and suppress the id field in forms with:

"form_fields = grok.AutoFields(Customer).omit('id')"

Because of this I have to calculate a new id before storing a new customer object. From a MVC perspective I think the 'get new id' code belongs in the model class but that's a different story.

The error I get wanting to set the value for id is this:

        TypeError: 'Customer' object does not support item assignment

The snippet I use it in is this:

def handle_voeg_toe(self, **data):
    customer = Customer()

    values = list(self.context.values())
    new_id = str(len(values) + 1)

    # It breaks here!!!!
    customer['id'] = new_id

    self.context['id'] = customer
    self.applyData(customer, **data)
    self.redirect(self.url('index'))


Changing/replacing the line in the snippet after the break point with this:

    self.context[new_id] = customer

Seemingly works because I can use this:

        http://localhost:8080/gpadmin/1

But then the actual 'id' attribute is not filled.

If more code or information is needed to clearify I'll gladly post it, but I consider this email long already ... :-)


Any pointers are very welcome.

Thanx a lot!

Kind regards,

Gerard.



_______________________________________________
Grok-dev mailing list
Grok-dev@...
http://mail.zope.org/mailman/listinfo/grok-dev

Re: Referencing objects by id

by Philipp von Weitershausen :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Gerard Petersen wrote:

> Hi All,
>
> 1st, forgive my n00bishness. I'm on Grok for a net time of only a couple
> of days now. Anyway ..
>
> Im trying to get my head around storing objects (Customers that is)
> based on customer id's. An url should look like this:
>
>     http://localhost:8080/gpadmin/1
>
> It was previously (working and) based on company name and used to look
> like this:
>
>     http://localhost:8080/gpadmin/Customer
>
> I use zope's interface and schema to work with the model and suppress
> the id field in forms with:
>
> "form_fields = grok.AutoFields(Customer).omit('id')"
>
> Because of this I have to calculate a new id before storing a new
> customer object. From a MVC perspective I think the 'get new id' code
> belongs in the model class but that's a different story.

Sure, you can do that. However, you probably want these IDs to be unique
throughout a particular range, so the model would have to know about
existing IDs somehow. That typically means it needs to know at creation
time which container it's being added to.

> The error I get wanting to set the value for id is this:
>
>     TypeError: 'Customer' object does not support item assignment
>
> The snippet I use it in is this:
>
> def handle_voeg_toe(self, **data):
>    customer = Customer()
>
>    values = list(self.context.values())
>    new_id = str(len(values) + 1)
>
>    # It breaks here!!!!
>    customer['id'] = new_id

You're doing item assignment here but that's typically only supported by
dict-like objects (e.g. containers). Hence the error message that it
doesn't support item assignment.

You want to assign a simple attribute:

      customer.id = new_id

>    self.context['id'] = customer
>    self.applyData(customer, **data)
>    self.redirect(self.url('index'))
>
>
> Changing/replacing the line in the snippet after the break point with this:
>
>    self.context[new_id] = customer
>
> Seemingly works because I can use this:
>
>     http://localhost:8080/gpadmin/1
>
> But then the actual 'id' attribute is not filled.
>
> If more code or information is needed to clearify I'll gladly post it,
> but I consider this email long already ... :-)

_______________________________________________
Grok-dev mailing list
Grok-dev@...
http://mail.zope.org/mailman/listinfo/grok-dev

Re: Referencing objects by id

by Martijn Faassen-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hey,

One thing you should realize is that in Zope 3 (and therefore Grok) what
is called 'id' in Zope 2 is actually called __name__. We call these the
name in the container.

So if you do:

   container[my_id] = s = Something()

you can later retrieve the __name__ of the object in that container like
this:

   s.__name__

I hope that helps!

It might also be worthwhile to investigate the NameChooser story in Zope
3, though that isn't strictly necessary.

Regards,

Martijn

_______________________________________________
Grok-dev mailing list
Grok-dev@...
http://mail.zope.org/mailman/listinfo/grok-dev

Re: Referencing objects by id

by Gerard Petersen-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Phillip,

Replies inline ...

> Sure, you can do that. However, you probably want these IDs to be unique
> throughout a particular range, so the model would have to know about
> existing IDs somehow. That typically means it needs to know at creation
> time which container it's being added to.
I indeed want to use them unique (e.g. for invoice references, etc.) but also keep them unchangeable by the application user (me :-).

Being aware of what a grok.container actually is since this afternoon, I'll dig in some more before getting back n this.

> You want to assign a simple attribute:
>
>      customer.id = new_id

Silly me. You're right. Thanx!

Kind regards,

Gerard.
_______________________________________________
Grok-dev mailing list
Grok-dev@...
http://mail.zope.org/mailman/listinfo/grok-dev

Re: Re: Referencing objects by id

by Gerard Petersen-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Dear Martijn,

I'll snoop around in de NameChooser story indeed. Thanx for that.

I do wonder about the 'id' though. I want the customer object to have a numeric value attribute for administering relations to email correspondence, invoices, tickets, etc.

By reading your explanation on the __name__ identifier (key?) I can choose any name to uniquely identify one customer object from many in a container. Right?

Personally I don't care about whether it's a name or a number behind the scenes, as long as it's the Customers name (and what not) that is showing on the webpage.

But since it can be anything I want, how would one then name an object's key to keep it understandable for humans (the coders that is)?

Any best practice tips on that are much appreciated.

Thanx again!

Kind regards,

Gerard.

Martijn Faassen wrote:

> Hey,
>
> One thing you should realize is that in Zope 3 (and therefore Grok) what
> is called 'id' in Zope 2 is actually called __name__. We call these the
> name in the container.
>
> So if you do:
>
>   container[my_id] = s = Something()
>
> you can later retrieve the __name__ of the object in that container like
> this:
>
>   s.__name__
>
> I hope that helps!
>
> It might also be worthwhile to investigate the NameChooser story in Zope
> 3, though that isn't strictly necessary.
>
> Regards,
>
> Martijn
>
> _______________________________________________
> Grok-dev mailing list
> Grok-dev@...
> http://mail.zope.org/mailman/listinfo/grok-dev
>
_______________________________________________
Grok-dev mailing list
Grok-dev@...
http://mail.zope.org/mailman/listinfo/grok-dev

Re: Re: Referencing objects by id

by Gerard Petersen-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi Martijn,

I found some interesting code snippets on the zope faq. In my previous I email was looking more for a semantical answer on naming objects.

Thanx again.

Gerard.

Martijn Faassen wrote:

> Hey,
>
> One thing you should realize is that in Zope 3 (and therefore Grok) what
> is called 'id' in Zope 2 is actually called __name__. We call these the
> name in the container.
>
> So if you do:
>
>   container[my_id] = s = Something()
>
> you can later retrieve the __name__ of the object in that container like
> this:
>
>   s.__name__
>
> I hope that helps!
>
> It might also be worthwhile to investigate the NameChooser story in Zope
> 3, though that isn't strictly necessary.
>
> Regards,
>
> Martijn
>
> _______________________________________________
> Grok-dev mailing list
> Grok-dev@...
> http://mail.zope.org/mailman/listinfo/grok-dev
>
_______________________________________________
Grok-dev mailing list
Grok-dev@...
http://mail.zope.org/mailman/listinfo/grok-dev

Re: Referencing objects by id

by Martijn Faassen-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hello,

Gerard Petersen wrote:
> I do wonder about the 'id' though. I want the customer object to have a
> numeric value attribute for administering relations to email
> correspondence, invoices, tickets, etc.

I have the suspicion we're talking about a number of topics at the same
time:

* naming in containers, i.e. names in URLs

* references from one object to another

If you have a single container which contains all the objects you may
want to reference to, of course you could use the container key (or some
id attribute) as the reference. There are other options however.

If your customer objects could occur throughout the ZODB in some form
hierarchy it might be worthwhile to investigate the use of the IIntIds
utility. This is a utility that can be used to give all objects a
globally unique id in the system, which you can then refer to, and resolve.

Another option would be to exploit the underlying nature of the object
database itself, and just put in a plain Python reference to the
customer object in whatever object that needs to refer to it. Of course
this might be too tight a coupling - what do you do when the customer
goes away for instance?

There are also more advanced solutions which perhaps require a bit too
much puzzling right now, but can help in more complicated scenarios
where you may want to ask questions about what relations exist in your
system. One library I wrote (but needs more polishing) is z3c.relationfield:

http://svn.zope.org/z3c.relationfield/trunk/

http://svn.zope.org/z3c.relationfield/trunk/src/z3c/relationfield/README.txt

> By reading your explanation on the __name__ identifier (key?) I can
> choose any name to uniquely identify one customer object from many in a
> container. Right?

You could use whatever strategy you like. A container is like a
dictionary in this; as long as your keys identify the values in a unique
way they could be any string.

> Personally I don't care about whether it's a name or a number behind the
> scenes, as long as it's the Customers name (and what not) that is
> showing on the webpage.
>
> But since it can be anything I want, how would one then name an object's
> key to keep it understandable for humans (the coders that is)?
> Any best practice tips on that are much appreciated.

It depends a bit on who is in control of these names. In some
applications, for some objects, you want to leave your users in control.
I could for instance imagine the customers would have to supply a unique
user name, and you could use this as the key. This makes for easy to
remember URLs, which is nice. A content management system that allows
you to create documents usually allows this.

If the user is not controlling the name in the URL, you could just make
up some number (the NameChooser bit might be useful here, though not
strictly necessary - it's a general abstraction for making up names in
containers) and make sure it's not in use yet.

You could also create a name based on data of the object itself, if
you're reasonably sure it's mostly unique and think it would provide for
prettier URLs. You could for instance use the name of the customer in
this case, perhaps lowercased, spaces replaced by underscores, with a
'unique-maker' number in the end if necessary, and replacing any
characters that wouldn't look nice in the URL. NameChooser could again
be something you fit this behavior into.

Regards,

Martijn

_______________________________________________
Grok-dev mailing list
Grok-dev@...
http://mail.zope.org/mailman/listinfo/grok-dev

Re: Re: Referencing objects by id

by Gerard Petersen-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi Martijn,

Let me first express my sincere thanks on your elaborate feedback. That really helped me a lot!

I have a clear view on where I go from here as far as the naming is concerned. And I'll definitely look into NameChooser for turning them into readable URL's.

I'm not replying on all the feedback, and will start on doing my homework first .. :-) , there's one part in your post however I would like to respond to.

> Another option would be to exploit the underlying nature of the object
> database itself, and just put in a plain Python reference to the
> customer object in whatever object that needs to refer to it.
Forgive my terminology, but by the 'plain python reference', do you mean just like you would pass on references to objects when instantiating other objects from classes?


I have no clue yet on how to do that in a grok/zope perspective, so I've decided to dig in on grok.container and get a better view on how a container relates to a model.

> this might be too tight a coupling - what do you do when the customer
> goes away for instance?
I thought of this, and customers that leave (and thus their projects as well) shall be moved to an archive-like container (or model?) for the customer as well as there projects. So there's still a (administrative) reference but there removed from the active applicatin scope.

Again. Thanx a lot for your much appreciated feedback!!

Regards,

Gerard.


>
> Regards,
>
> Martijn
>
> _______________________________________________
> Grok-dev mailing list
> Grok-dev@...
> http://mail.zope.org/mailman/listinfo/grok-dev
>
--
urls = { 'fun':  'www.zonderbroodje.nl',  'tech':  'www.gp-net.nl' }

_______________________________________________
Grok-dev mailing list
Grok-dev@...
http://mail.zope.org/mailman/listinfo/grok-dev
LightInTheBox - Buy quality products at wholesale price