I've coded some classes in pure python, but now I need to use that classes in a django view.
my_custom_classes.py
class RetryException(Exception):
...
...
class Trade():
def __init__(self):
...
...
def some_other(self, id):
...
...
For example I need to make a call to a django model inside the "some_other(self, id)".
What is the best way of organizing this custom classes for using in a Django view?
Best Regards,
There is no difference between using a python class in a django view and using a class inside a "normal" python function.
Instantiate your class, and call its methods.
Do you have a Trade model? If so, would it makes sense to put that functionality in the Trade model class?
If you need to call something inside of your Trade class, what you are calling has to be in scope. If you are querying a model you can import it in the module Trade is defined in, and you can access it as you expect.
from yourproject.yourapp.models import AModel
class Trade(object):
def some_other(self, id):
return AModel.objects.filter(pk=id)
Related
I had studied class methods in python but never really understood its application in Djnago. My coding life was going well without the use of it. But I came across a situation where class method will be useful.
My model:
class Example(models.Model):
post_count = models.IntegerField(default=0)
#classmethod
def total_counts(cls):
return cls.objects.values('post_views').annotate(sum logic)
In the above function, if I had used property decorator, i can only get a single object post_count because the object self is used. But if I use classmethod then I can count the post views of all the objects.
So my thought is that whenever we have to deal with all the objects instead of a self object we need class method. Is this correct?
Also, can we use this class method directly into our model serializer field just like we use property to serializer??
I can inherit from a class based generic view from generic.ListView as in
class BookListView(generic.ListView):
model = Book
Supposedly the .as_view() function gets called when the Django app starts up to create an instance of this view.
I find the definition of get_queryset in MultipleObjectMixin but what I dont find is, from where is this method called from?
I am trying to create a very simple CRUD application using REST API.
So I create a very simple model, serializer and viewset for all these.
And then I noticed that I don't fully understand some basic principals about right use-cases for calling (for example create method for my model instance)
As I understand, django providers several approaches:
I can define my CRUD methods inside model class:
class Foo(models.Model):
...
def create(...):
foo = Foo()
foo.save()
I also can create instances using model serializers (seems there is no big difference, because the same save method from model instance is calling):
class FooSerializer(seializer.ModelSerilizer):
...
class Meta:
model = Foo
....
def create():
fs = self.Meta.model()
fs.save()
2b. I can use simple serializers:
class FooSerializer(serializers.Serializer):
def create(**validated_data):
return Foo(**validated_data)
Finally I can use perform_create, update and so on from viewset:
class FooView(ModelViewSet):
serializer = FooSerializer
def perform_create():
serializer.save()
...
Is there some patterns when one or another solution should be implemented?
Could you please provide some explanation with use cases?
THanks!
Lets go step by step on your points of creating/using create method:
You don't need to write a create() method inside model.
You don't need to write a create() method in model serializer, unless you want to handle additional keywords or override the create() method to change the default behavior(Reference).
In serializer.Serializer you can write a create() method if you want save an instance with that serializer. Useful when you are using this serializer with GenericAPIViews or Viewsets. Reference can be found in documentation.
By writing perform_create() method in Viewset, you are basically overriding the default perform_create() from the Viewset. You can integrate additional tasks inside that function when overriding it(example).
This is maybe not a fundamental question, but as curious as I am, I'm asking this myself for a long time.
A part of Django code is functions and is not directly related to Django models.
Let's take for example this function :
def make_random_raw_password(length=8):
# Do some stuff and return a 8 char randomised string
Technically, this function is not related to the User class, but functionally, it is!
Where would you write this function?
From my beginner point of view, I can see at least 2 options:
I create a myutils.py file which contains all these kind of functions then I import myutils.py in files like models.py / view.py to use these functions.
I move this function as a classmethod in my UserProxy class (since I can not directly modify the User class methods in Django) which gives me something close to:
-
class UserProxy(User):
class Meta(object):
proxy = True
#classmethod
def make_random_raw_password(cls, length=8):
# Do some stuff...
Which one would you use? Could you explain why? Thank you in advance.
The main purpose of a model is to contain business logic, so I want most of my code inside Django model in the form of methods. For example I want to write a method named get_tasks_by_user() inside task model. So that I can access it as
Tasks.get_tasks_by_user(user_id)
Following is my model code:
class Tasks(models.Model):
slug=models.URLField()
user=models.ForeignKey(User)
title=models.CharField(max_length=100)
objects=SearchManager()
def __unicode__(self):
return self.title
days_passed = property(getDaysPassed)
def get_tasks_by_user(self,userid):
return self.filters(user_id=userid)
But this doesn't seems to work, I have used it in view as:
tasks = Tasks.objects.get_tasks_by_user(user_id)
But it gives following error:
'SearchManager' object has no attribute 'get_tasks_by_user'
If I remove objects=SearchManager, then just name of manager in error will change so I think that is not issue. Seems like I am doing some very basic level mistake, how can I do what I am trying to do? I know I can do same thing via :Tasks.objects.filters(user_id=userid) but I want to keep all such logic in model. What is the correct way to do so?
An easy way to do this is by using classmethod decorator to make it a class method. Inside class Tasks:
#classmethod
def get_tasks_by_user(cls, userid):
return cls.objects.filters(user_id=userid)
This way you can simply call:
tasks = Tasks.get_tasks_by_user(user_id)
Alternatively, you can use managers per Tom's answer.
To decided on which one to choose in your specific case, you can refer James Bennett's (the release manager of Django) blog post on when to use managers/classmethod.
Any methods on a model class will only be available to instances of that model, i.e. individual objects.
For your get_tasks_by_user function to be available as you want it (on the collection), it needs to be implemented on the model manager.
class TaskManager(models.Manager):
def get_tasks_by_user(self, user_id):
return super(TaskManager, self).get_query_set().filter(user=user_id)
class Task(models.Model):
# ...
objects = TaskManager()