Are you trying to create something like a dynamic model, where the
model attributes are named on the fly? Do you have one central model
that needs to be able to have FK's to various other similar but
distinct models?

I think the better question is "what problem are you trying to solve?"


> I just had a look at proxy models. Nice stuff, but it's not what I am
> looking for.
>
> I need to be able to give each "instance" an individual value.

This is confusing, and may be a clash in typical Python nomenclature.
When you say 'instance', are you referring to the model class
definition itself, or an actual 'instance' of a model class that
already exists (ie, referring to kid when kid = KidType(**args) ).
Talking about values would imply the latter, but your example pseudo
code would indicate the former.

>>
>> Abstract Base Models come close but they don't allow me to combine
>> multiple instances of the BaseModel in the DataHolderModel.

Upon first reading this thread, this was the first response that came
to my mind. Your explanation of why it doesn't work suggests that
perhaps you are not implementing abstract models correctly. Can you
provide a brief example of what you tried (including all related model
definitions)?

>>
>> My goal is to store them all in one table without having to manually add
>> all the fields.

Store all of what? Confused again, as this sounds very close to what
abstract models are designed to do. It's also possible that you may
want to take advantage of Generic Relations within Django, which would
allow a single model to have relations with several other models with
little code.


>>>> now this is kind of hard for me to explain, I hope that somebody
>>>> understands what I actually want.

It doesn't seem like we've reached that point yet, unfortunately.

>>>>
>>>> I am a python newbie and wonder if there is an easy solution.
>>>>
>>>> They say: DRY!!

Yes, DRY is desirable, although breaking DRY to improve clarity is
certainly appreciated. Given the solution you originally posted, I
think you have a case for breaking DRY. They Python Zen also states
that explicit is better than implicit, meaning that if nobody here can
figure out the magic you are trying to perform, it may be better to be
more explicit with your code (which may mean multiple model
definitions with slight variances, which are much easier to follow).

>>>>
>>>> My question is:
>>>> How do a define an (abstract?) class including methods and fields
>>>> and then attach it to a real mode with variants instants?

Again, I think there's a vocabulary issue here. Everything you have
been describing (aside from your code examples) points back to using
an abstract model to define all of the common functionality between
several models (which includes both fields and methods). You can
define as little, or as much as you need within the abstract base
class. If you have fields that will be different between models that
inherit from the base class, you shouldn't define them in the base
class, and let the real models define them on their own (which doesn't
violate DRY, because it is different for every model).

You can be a bit more loose with custom methods because those can be
overridden by the real models as needed (have the base class define a
generic method that works for most child models, and override on the
models that need it).


>>>>
>>>> The data needs to be available as realy models.* types, so I can use it
>>>> in forms.

Of course. Once you define the abstract base model, you would create
the real models that inherit from your abstract base model with the
necessary overrides and additions specific to those models. You can
then reference the new models for any Django operation.


Let me see if I can work through this and you tell me (us) where I strayed:

>>>> # NOW THIS IS TOTALLY MADE UP
>>>> # Basically I would like to be able to define a definition of
>>>> model-fields and functions
>>>> # and then be able to "attach" it to a model as various instances

This is pretty much the definition of abstract base classes, but
myself and others have already covered that.

>>>> class KidType (models.Model):
>>>>     NAMEHOLDER = '' #nameholder
>>>>
>>>>     NAMEHOLDER_text = models.TextField()
>>>>     NAMEHOLDER_timestamp_updated =
>>>> models.DateTimeField(auto_now_add=False, auto_now=True)
>>>>
>>>>     def example_function_shared_among_types():
>>>>         return str(self.NAMEHOLDER_text +
>>>> self.NAMEHOLDER_timestamp_updated)
>>>>
>>>>     def set_NAMEHOLDER_text(value):
>>>>         self.set_NAMEHOLDER_text(value)


Ok, so here ^^ you have what looks like it should be an abstract model
per the Django definition. Not necessarily defined in the typical
fashion, but getting rid of the NAMEHOLDER references would go a long
way. You define a TextField (CharField?) and a time stamp field.
Typically this would look something like this:


class BaseKidType(models.Model):
    favorite_color = 'all of them'

    text = models.CharField(max_length=255)
    updated_at = models.DateTimeField(auto_now_add=False, auto_now=True)

    def reset_favorite_color(self):
        self.text = 'My favorite color is {}!'.format(self.favorite_color)

    class Meta:
        abstract = True

# Then you would define your actual models, inheriting from your base model
# I don't know what qualifies as a kid type, so I'll make some up

class BlueKid(BaseKidType):
    favorite_color = 'blue'

class GreenKid(BaseKidType):
    favorite_color = 'green'

#####

Now we have 3 model definitions, but only the last two models can be
used in other areas of the Django framework (and will generate DB
tables). The base class can't be used for anything like forms, etc.
(and has no DB table)

Both BlueKid and GreenKid have all of the properties of the base
class, which means I can do this:

my_blue_kid = BlueKid(text='My favorite color is blue!')
my_green_kid = GreenKidKid(text='My favorite color is not blue, but green!')

#You can also assign values to the attributes defined in the base class:

my_blue_kid.text = "My favorite color is now orange. I'm a rebel!"
# print my_blue_kid.text
# "My favorite color is now orange. I'm a rebel!"
my_blue_kid.reset_favorite_color()
# print my_blue_kid.text
# "My favorite color is blue!"
my_blue_kid.save()


And now the fun part:

>>>>
>>>> #
>>>> class DataHolderModel(models.Model):
>>>>     # Attach the above definition with different names
>>>>     # and make them accessable
>>>>     @attach (KidType, KidType.NAME = 'dataset1')
>>>>     @attach (KidType, KidType.NAME = 'dataset2')
>>>>     @attach (KidType, KidType.NAME = 'dataset3')

Quite honestly, I have no idea what this ^^ is supposed to be doing
(both the code and the intent for the model). My assumption is that
you are trying to substitute some custom behavior instead of using
ForeignKey() definitions back to real models like I defined above.
Trying to use the base class in this manner is going to bring pain on
most, if not all, levels.

If ForeignKeys are actually what you want (which I believe to be the
case), you have a couple of options. You can either specify a new FK
relation to any new *Kid models that you create, and create/run new
migrations, or you can invest some time into Generic Relations:
https://docs.djangoproject.com/en/dev/ref/contrib/contenttypes/#generic-relations

Using FK's would look something like this:

class DataHolderModel(models.Model):
    blue_kid = models.ForeignKey(BlueKid)
    green_kid = models.ForeignKey(GreenKid)



Without knowing a bit more about KidType, I would ask whether or not
multiple models would even be needed. Would it be more concise to have
a single concrete (non-abstract) model called Kid, with a field called
'kid_type' that is perhaps filtered down via the choices attribute to
a known list (ie choices=( ('green', 'Green Kid'), ('blue', 'Blue
Kid') ) ), then you can have a single table with multiple 'types' of
kids, that can be easily filtered on. This may or may not meet your
requirements, but I would consider it if possible (another Python Zen
saying, "simple beats complicated").



>>>>
>>>> # Access the instances within the HolderModel:
>>>> data_holder = DataHolderModel()
>>>> data_holder.dataset1_text = 'value1'
>>>> data_holder.set_dataset1_text('value1')
>>>> data_holder.dataset2_text = 'value2'
>>>> data_holder.dataset3_text = 'value3'

The updated version with the models I suggested above would be:

data_holder.blue_kid.text = 'value1'
data_holder.green_kid.text = 'value1'
data_holder.save()

And so on.

Hopefully I'm on track here. Put some thought into your model layout,
and avail of the options that Django provides such as FK relations and
generic relations. This might be a case where you are too focused on
making things DRY up front, and frustrating yourself. Make it DRY once
it is working. You'll have a better understanding of all of your code
as a whole, what it does, and what you need it to do, and at that
point, you'll likely come up with ways to take advantage of
inheritance and other techniques to start conforming to DRY.

If I'm off base here, providing real code examples of things you are
trying will be a big help, including related model definitions and
behavior in the Django shell interpreter (if you're using it).

Sorry for the lengthy reply, I didn't think I'd go this long.

HTH,

-James

-- 
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/django-users.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-users/CA%2Be%2BciV9_qobKNu9EW0VBhv%3DtWNUeqNBFr6%2BEMVk3oBd3CD7Qg%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to