Is it possible to call a property through another model? - django-models

I'm studying django and drf and I want to pass some information trough serializer.
I have two models:
class ModelA():
...
and
class ModelB():
...
#property
def anything(self)
return ...
Is it possible for ModelA to call the ModelB property? How could I do this?

Related

Add field to drf serializer dynamically

I have an API endpoint that return a list of objects of one of my models.
I have a very trivial serializer that currently returns all the model fields.
What I need now is to add to this serializer another field which is calculated by applying a logic on one of the model field and another data structure that is also calculated dynamicly - but should be calculated only once for each call to the API.
What is the way to supply this structure to the serializer for every API call but not for every object the serializer returns?
My ModelViewSet (without the extra field) is quite trivial:
class MyModelViewset(ModelViewSet):
queryset = SomeModel.objects.all()
serializer_class = SomeModelSerializer
Some suggestions on how you can achieve this:
To calculate something only once and use it in the serializer you should add it to the serializer context.
You can create #property in your SomeModel class and it can be exposed via serializer fields as read only. Django has also #cached_property so that value is only calculated once and persist as long as the instance does
You can use SerializerMethodField field if you want to calculate something (you have access the serializer context in there).
Just a quick example on how to use this.
class MyModelViewset(ModelViewSet):
queryset = SomeModel.objects.all()
serializer_class = SomeModelSerializer
def get_serializer_context(self):
context = super().get_serializer_context()
context['my_value'] = [] # calculate something here, you have access to self.request
return context
class SomeModelSerializer(serializers.ModelSerializer):
my_data = serializers.SerializerMethodField()
class Meta:
model = SomeModel
def get_my_data(self, obj):
# you have access to self.context['my_value']
# you have access to obj.some_property
return my_data

How to use hyperlinks to represent relationships instead of primary keys in Django REST framework

I want to get my object index as a "resource_uri" instead id
I take the usual way I make a model , views , serializers :
class User(BaseModel):
user = models.ForeignKey(settings.AUTH_USER_MODEL)
models.CharField()
class UserSerailizers(serializers.ModelSerializer):
class Meta:
model = User
fields = ('id','user','formatted_address')
classclass UserList(generics.ListCreateAPIView):
queryset = Image.objects.all()
serializer_class = UserSerializer
when i call < my_domain/user/ > I get this response
{
id:1,
name:'toto'
}
but I want to have an answer to this form:
{
'url': my_domain/user/1/
'name': 'toto'
}
Any thoughts?
If you want a hyperlink instead of a primary key in your model representations, you have to use either HyperlinkedModelSerializer or more generic Serializer along with HyperlinkedIdentityField and/or HyperlinkedRelatedField. The former is probably what you are looking for.
The HyperlinkedModelSerializer class is similar to the ModelSerializer class except that it uses hyperlinks to represent relationships, rather than primary keys.
See Django REST framework documentation for more details.
As already commented, you need to use the HyperlinkedModelSerializer as you've shown.
The lookup_field attribute should be inside the Meta class.
And the latest and this is a guess: You just have a ListView for your User model. In order to show the detail for the user, you need also the retrieve method. I would recommend you using the ModelViewset so it automatically implements all methods.

how to get model with backbone if i have it's URI?

I'm using django+tastypie+backbone.js with backbone-relational.
Let's say i have model(coffee script):
class Track extends Backbone.RelationalModel
And somehow i get the first object's URI:
api/track/1
Result in JSON have to be something like:
{
'title': 'Mytrack',
'length': '120'
}
How can i get full model JSON with all attributes using this URI?
You need to set the model's urlRoot (/api/track), then create a new model with the id you want (1), and call .fetch on the model. The fetch call will be asynchronous, so you need to wait for the success callback before you can access the full properties:
class Track extends Backbone.RelationalModel
urlRoot:"/api/track"
track = new Track id:1
track.fetch
success:(model) -> console.log model

what's the best way to set computed property of app engine model in appengine after fetch from datastore?

I have my own User model in app engine, which should have a property of his gravatar url. However, since this can be very quickly computed using his email address, it doesn't make sense to store it. Is there a way to just automatically initialize this property when it s loaded from the datastore?
I could just add a method called get_avatar_url(), but you can't call an object's methods (as far as I know), from within a jinja2 template, and I don't want to post all these values individually to the template.
You can define a method, as you describe, or you can define a property, like this:
class MyModel(db.Model):
email = db.StringProperty(required=True)
#property
def avatar_url(self):
return "http://gravatar.com/avatar/%s" % (hashlib.md5(self.email).hexdigest(),)
You can then refer to this as instance.avatar_url (or in a template, {{instance.avatar_url}}).
Either will work fine in a jinja2 template, but using a property is slightly neater if you need to request it elsewhere. Since only datastore property instances result in storing data in the datastore, your property will not be stored in the datastore.
It's ok to call them from a template. All you need to do is to declare this model's method as classmethod or property
Here's a quick example:
# sample model
class UserProfile(db.Model):
...
email = db.EmailProperty()
...
#property
def id(self):
return self.key().id()
#classmethod
def get_avatar_url(self):
# whatever you need to call gravatar url
return self.email
# sample view
def show_user(user_id):
user = User.all().filter("user = ", user_id).get()
flowers = Flower.all().filter("user = ", user)
return render_template('index.html', u=user, f=flowers)
# sample template
<div class="user">user id: {{ u.id }}, and gravatar: {{ u.get_gravatar_url() }}<div>
HTH.
You most certainly can call methods within a template. That is the best way to do it.

Naming conventions for MVVM?

I'm struggling a little over naming classes for my MVVM application.
I have a TrainingCourse, which is called a TrainingCourseViewModel, but I can have many of these, so I have created a TrainingCourseViewManager to hold the list of courses and allow them to be added/removed. I also have an EmployeeViewController which has a reference to other view models as well as the TrainingCourseViewManager.
The EmployeeViewController essentially wraps all of the other view models and view managers and when its instantiated it gets the employee and in turn instantiates each of the view models and view managers.
The question is... What naming conventions are people using?
Should my TrainingCourseViewManager be called TrainingCoursesViewModel and should my EmployeeViewManager be called EmployeeViewModel?
Thanks
There might be a confusion over the role of view model.
Classes in your example (and in Orion's answer to that matter) seem more like actual data model. For example, it doesn't make sense for a view model to "hold the list of courses and allow them to be added/removed" - that's what data model should do. Add and remove operations on a view model wouldn't operate on the collection itself - instead, they would access and modify underlying data model.
Do properties of TrainingCourseViewModel class store actual data values, or wrap properties of some TrainingCourseDataModel class (with additional processing)? Or if you need to serialize data, would you serialize TrainingCourseViewModel objects? If former is true, you are binding directly to the data model, and there should be no 'ViewModel' suffix in names.
On the topic of naming conventions, if names become too complex, namespaces can help. For example:
namespace TrainingCourseView.ViewModel
{
class TrainingCourse {}
class Manager {}
class Controller {}
}
...
Data.TrainingCourse course;
new ViewModel.TrainingCourse(course);
Should my TrainingCourseViewManager be called TrainingCoursesViewModel and should my EmployeeViewManager be called EmployeeViewModel?
What are your window classes called? (what is your .xaml file called?)
The naming convention goes, that you create one ViewModel class per View (a view is a .xaml/.xaml.cs pair)
If you have a single window which displays a list of Employees and Training Courses, then you'd have something like this:
namespace Models
{
public class Employee : INotifyPropertyChanged { ... }
public class TrainingCourse : INotifyPropertyChanged { ... }
}
namespace ViewModels
{
// assuming you have TrainingWindow.xaml
public class TrainingWindowViewModel : INotifyPropertyChanged
{
public ObservableCollection<TrainingCourse> TrainingCourses
{ get{ return m_trainingCourses; } }
{ set{ m_trainingCourses = value; RaisePropertyChanged("TrainingCourses"); } }
...
}
// so on and so forth
}

Resources