Wednesday, June 6, 2018

Re: Accessing the model attribute of UpdateView & friends

Ok! I think I see your problem.

It is a deeper understanding of python classes that may be the problem.
You see, "model" and "self" are class atributes of the python class that houses your class based view (as every class in django is first a python class).

So, if you try to access the attribute "model" of the class, or the attribute "self", a attribute that houses the instance of the class, on it's class attributes definitions you will have problems, as the python interpreter only load these modules lazyly, not actually going through on finding the value for the attribute you referenced.

One solution is to have that value (for the attribute "field" as a @property that is a function that then the python interpreter will go through and execute the reference lookup.

Another solution is to set that value to be initially None, and set the value for the fields on the dispatch method of the view, something like 
class ItemUpdateView(UpdateView):
  template_name="foo.html"
  fields = None
 
  def dispatch (self, request, *args, **kwargs):
    self.fields = self.model.fields
    return super(ItemUpdateView, self).dispatch(request, *args, **kwargs)



But as of my understanding of your problem, you are trying to just customize which form fields to display to the user based on which model the user is updating, so you could just specify the form_class attribute on the path (just as you did with the model).

Hope it helps!


On Wed, Jun 6, 2018, 10:36 Mikkel Kromann <mikkel@aabenhuskromann.dk> wrote:
Hello Daniel.

Thank you for your reply. Perhaps I was not explicit enough in describing my problem - it is far simpler than your solution indicates.
In my model definitions, I already have a list of the fields to be represented in the form of UpdateView - it is an attribute in the form of a simple array called "fields".
I don't want UpdateView to make a form for all columns of the model's data table, just the fields from my custom array in the Model objects.

My problem is simply: How to access my custom attribute "field" in the Model attribute passed to the Class Based View function.
As described, I get compilation errors, complaining that "model" and "self" are names not defined.
From the documentation (and my so far not too great Python understandign) it is not clear to me whether "Model" is simply the name of the model, or if it is the entire Model object instance.


thanks again, Mikkel


onsdag den 6. juni 2018 kl. 15.01.05 UTC+2 skrev Daniel Germano Travieso:
Hello!

As you see on the documentation (https://docs.djangoproject.com/en/2.0/topics/class-based-views/) for the class based views, any arguments you pass to the class based view .as_view() method will override attributes of the class based view, so if you set MyCView.as_view(model=Foo) is the same as setting class MyCView: model=Foo directly.

Now to access the field names of the Model, you used to be able to call a .get_field_names() or something like that but that is depreciated since 1.10. Now to do that you should use the Model._meta to get_fields(). Check the documentation for the Model._meta to check its full potential.

Hope it helps!

On Wed, Jun 6, 2018, 07:33 Mikkel Kromann <mik...@aabenhuskromann.dk> wrote:
Thanks for the advice, Andréas.
But the response is the same:

  File "C:\Users\ ... xxxxxxx   ... \items\views.py", line 7, in ItemUpdateView
    fields
= self.model.fields
NameError: name 'self' is not defined



As far as I understood, model is an attribute, not a method (though I'm new to Python and Django, so I'm unsure about this).
Does attribute/method make a difference in this case?

cheers, Mikkel
tirsdag den 5. juni 2018 kl. 22.10.31 UTC+2 skrev Andréas Kühne:
Hi,

Have you tried self.model? It should be present in all methods in the class?

Regards,

Andréas

2018-06-05 21:56 GMT+02:00 Mikkel Kromann <mik...@aabenhuskromann.dk>:
Dear Django-users.

I'm slowly working towards a Django "data-warehouse" framework, where I can easily add a lot of models (each containing a table with data), while sticking to only few reusable views.

I've realised that in urls.py, it is possible to specify the model on which the UpdateView is going to do its magic.
This allows me to use a generic UpdateView (which I called ItemUpdateView) and template for all my models, which will save me a ton of almost identical lines of code.

However, in the generic ItemUpdateView, I of course need to specify the fields of the specific model chosen in urls.py.
As I ideally only want a few generic views (i.e. ItemCreateView, ItemUpdateView, ItemDeleteView and ItemListView), I've chosen to place the field array in my model definition, hoping to be able to access it from my generic Class Based Views

But how do I access the model attribute in (Item)UpdateView


thanks, Mikkel

From views.py
from django.views.generic import CreateView, ListView, UpdateView, DeleteView

class ItemUpdateView(UpdateView):
    template_name = "item_form.html"
# How do I access the model attribute of ItemUpdateView as given in urls.py?
# This line below returns the error "NameError: name 'model' not defined"
    fields
= model.fields

From urls.py
from django.urls import path
from . views import ItemUpdate
from . models import Region, Location

# Awesome! I can specify the model to be used by ItemUpdateView
urlpatterns
= [
    path
('update/region/<pk>',    ItemUpdateView.as_view(model=Region),     name='region_update'),
    path
('update/location/<pk>',  ItemUpdateView.as_view(model=Location),   name='location_update'),
]



From models.py (Region and Location are only two of my tables, I'd like to have say 20 or 30 models
from django.db import models

# Abstract class for our items including common methods, data and definitions
class ItemModel(models.Model):

    fields
= [ 'label', 'short', 'descr' ]
    label  
= models.CharField(max_length=10)
   
short   = models.CharField(max_length=15)
    descr  
= models.CharField(max_length=40)

   
def __str__(self):
       
return self.short

   
class Meta:
       
abstract = True

class Region(ItemModel):
    fields  
= [ 'label', 'short', 'descr' ]

class Location(ItemModel):
    fields  
= [ 'label', 'short', 'descr', 'region' ]
    region  
= models.ForeignKey(Region, on_delete=models.CASCADE)

class Plant(ItemModel):
    fields  
= [ 'label', 'short', 'descr', 'location', 'capex', 'opex', 'capacity' ]
    location
= models.ForeignKey(Location, on_delete=models.CASCADE)
    capex   = models.DecimalField(decimal_places=3, max_digits=8)
    opex    = models.DecimalField(decimal_places=3, max_digits=8)
    capacity= models.DecimalField(decimal_places=3, max_digits=8)


--
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 django-users...@googlegroups.com.
To post to this group, send email to django...@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/ec4634e5-2279-49a7-9045-21712de87584%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

--
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 django-users...@googlegroups.com.
To post to this group, send email to django...@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/95db9cca-58ca-4460-ae39-9150bb199bff%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

--
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 django-users+unsubscribe@googlegroups.com.
To post to this group, send email to django-users@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/c857567f-dd71-46c1-a05b-787566bfa180%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

--
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 django-users+unsubscribe@googlegroups.com.
To post to this group, send email to django-users@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/CABF8kZPZSYqv49_7X_eF9nRhtdWWYOXHr-z6MdeMrd51GhoF2Q%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.

No comments:

Post a Comment