On 20/06/2017 1:13 PM, Mike Dewhirst wrote:
> On 20/06/2017 2:22 AM, 'Victor Hooi' via Django users wrote:
>> If you go down the user-profiles route - how would you handle
>> managing each of those via the Django Admin?
>
> I use group permissions to reveal or hide models in the Admin main
> menu. I use admin, editor, author and for example authors cannot
> see/edit company, addresses or phone numbers . And so on.
>
>>
>> For example - say you have 3 user "types" - each just being User,
>> with a different profile linked to it. How would you manage each of
>> those via the admin interface?
>
> I do a similar thing. Any substance can have one or two of a few
> physical_state(s). Different physical forms have different data to be
> collected. However, all of them have a subset of the same data. So I
> use a core_fields model with abstract = True and all the solid,
> liquid, gas etc models inherit from core fields. All the attributes
> and methods in cvommon live on the core_fields abstract model.
>
> In the Admin I detect the substance physical_state and only present
> the appropriate models. One choice is solid and liquid. If that is
> selected the substance gets both "profiles"
>
> For a new substance, all those I select one of the choices and save to
> make the unwanted profiles disappear. Provided no data was entered in
> the unwanted models, they never get created.
>
> You need a bit of jiggery pokery in admin.py but it can be done. I'll
> try and get some time later to show you.
This is quite complex at first glance but very straightforward Python
code living in the SubstanceAdmin class (at the end) in substance
admin.py. The way I have arranged a substance is to have intrinsic
properties and other information in related models/tables. So each of
the inline classes below represents one of those related models. When
registering those inlines for a new substance, all inlines are used
because we don't yet know what physical state the substance will be.
The method below get_inline_instances()
(
https://docs.djangoproject.com/en/1.10/ref/contrib/admin/#django.contrib.admin.ModelAdmin.get_inline_instances)
simply assembles the appropriate lists of inlines for the physical state
of the substance. min_1_inlines and min_3_inlines are both always
included at the top and tail of the list but others vary depending on
physical state. And of course, the sequence in which they appear in the
final list is important because that is how they appear on the page.
Finally, physical_state is an IntegerField and I use constants to
represent SOLID, LIQUID etc. Here is the arrangement ...
SOLID = 1
LIQUID = 2
GAS = 4
AEROSOL = 8
... which lets me have any combinations like SOLID + LIQUID = 3 which
are all unique in choices. See solid_liquid_inlines below.
# excerpt from admin.py
min_1_inlines = [
LinkInline,
PapersInline,
SynonymsInline,
UsesInline,
IngredientsInline,
GroupsInline,
]
min_2_inlines = [
ExplosiveInline,
DesensitizedExpInline,
OrganicPeroxideInline,
SelfReactiveInline,
]
min_3_inlines = [
FirstaidInline,
FireInline,
SpillInline,
EngineeringInline,
LimitsInline,
PpeInline,
ExposureInline,
HealthInline,
OrganInline,
AquaticInline,
TerrestrialInline,
DisposalInline,
RegistryInline,
NotesInline,
]
solid_inlines = min_1_inlines + [
SolidInline,
] + min_2_inlines + min_3_inlines
liquid_inlines = min_1_inlines + [
LiquidInline,
] + min_2_inlines + min_3_inlines
solid_liquid_inlines = min_1_inlines + [
SolidInline,
LiquidInline,
] + min_2_inlines + min_3_inlines
gas_inlines = min_1_inlines + [
GasInline,
] + min_2_inlines + min_3_inlines
aerosol_inlines = min_1_inlines + [
AerosolInline,
] + min_3_inlines
all_inlines = min_1_inlines + [
SolidInline,
LiquidInline,
GasInline,
AerosolInline,
] + min_2_inlines + min_3_inlines
def get_inline_instances(
self,
request,
obj=None,
# now get each of the above inline lists into this scope
all_inlines=all_inlines,
aerosol_inlines=aerosol_inlines,
gas_inlines=gas_inlines,
liquid_inlines=liquid_inlines,
solid_inlines=solid_inlines,
solid_liquid_inlines=solid_liquid_inlines
):
physical_state = 0
if obj is not None and hasattr(obj, 'physical_state'):
physical_state = obj.physical_state
if physical_state == LIQUID:
return [inline(self.model, self.admin_site) for inline in
liquid_inlines]
elif physical_state == SOLID:
return [inline(self.model, self.admin_site) for inline in
solid_inlines]
elif physical_state == SOLID + LIQUID:
return [inline(self.model, self.admin_site) for inline in
solid_liquid_inlines]
elif physical_state == GAS:
return [inline(self.model, self.admin_site) for inline in
gas_inlines]
elif physical_state == AEROSOL:
return [inline(self.model, self.admin_site) for inline in
aerosol_inlines]
return [inline(self.model, self.admin_site) for inline in
all_inlines]