How to make a django model singleton - python-3.x

I have django model which stores file and uploded peron but i need my django model to be a singleton how can i acheive this?
models.py
class Mymodel(BaseModel):
title = models.FileField(
upload_to='',
validators=[],
)
person_uploaded = models.Foreignkey()

for the OP, please follow some tutorial about model relationships on official site just like the comments suggested.
for visitors who searched the title and tried to implement a table of constants.
I thought about this through architecture initially, and played around. then django taught me a tough lesson, you better not mess model structure, do with what you normally use, otherwise something may go wrong, so I ended up implementing this:
import math
from django.db import models
# Create your models here.
class Constants(models.Model):
pi = models.FloatField(default=math.pi)
e = models.FloatField(default=math.e)
#staticmethod
def setup():
try:
Constants.objects.get(pk=1)
except Constants.DoesNotExist:
instance = Constants()
instance.save()
#staticmethod
def instance():
return Constants.objects.get(pk=1)
# only create 1 and save 1 allowed, other abort
def save(self, *args, **kwargs):
if self._state.adding:
try:
Constants.objects.get(pk=1)
except Constants.DoesNotExist:
# create 1
super().save(*args, **kwargs)
else:
# save 1
super().save(*args, **kwargs)
which only allow pk=1 exist, and always use that instance, you can update it, and remember to run setup to initialise first instance and default values after deploy to server. this saves performance, and will causing any bug.

Related

Using Model.objects.filter in Form prevents me from updating Model

I have a form setup like this where I use the values from TestModel to create a select field in a form. However if I want to update the TestModel to add a new column, Django gives me a psycopg2.errors.UndefinedColumn saying the new column is not found on the table and the stack trace points back to this form ModelChoiceField. Its not until I comment out this select that I am able to make the migration to the database.
So my question is there a better way to setup this ModelChoiceField where I don't have to comment it out to update the underlying model on the database? I'm using Django 4.0 and python 3.8 for reference.
class TestModelChoiceField(forms.ModelChoiceField):
"""
Overwriting model choice field attribute to use
a different __str__ representation than the default
model
"""
def label_from_instance(self, obj):
return obj.test_field
class TestForm(forms.Form):
first_select = TestModelChoiceField(
queryset=TestModel.objects.filter(model_attribute__isnull=False),
initial=TestModel.objects.filter(model_attribute__isnull=False)
.filter(test_field="Yes")
.first()
.team_id,
label="Field One:",
)
When it comes to needing database access in a form like this, you're best waiting until the form is initialised rather than at runtime like you are doing here. With it setup like you have, when you start your app the form will get loaded and immediately try to query the database. If you wait until the app creates an instance of the form, you can be assured that the database will be ready/available.
So what you'd end up with is something like;
class TestForm(forms.Form):
first_select = TestModelChoiceField(
queryset=TestModel.objects.none(),
label="Field One:",
)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['first_select'].queryset = TestModel.objects.filter(model_attribute__isnull=False)
self.fields['first_select'].initial = TestModel.objects.filter(
model_attribute__isnull=False
).filter(test_field="Yes").first().team_id

How to implement "relationship" caching system in a similar query?

I noticed that when having a Model such as :
class User(Model):
id = ...
books = relationship('Book')
When calling user.books for the first time, SQLAlchemy query the database (when lazy='select' for instance, which is the default), but sub-sequent call to user.books don't call the database. The results seems to have been cached.
I'd like to have the same feature from SQLAlchemy when using a method that query, for instance:
class User:
def get_books(self):
return Book.query.filter(Book.user_id == self.id).all()
But when doing that, if I call 3 times get_books(), SQLAlchemy does call the database 3 times (when setting the ECHO property to True).
How can I change get_books() to use the caching system from SQLAlchemy ?
I insist to mention "from SQLAlchemy" because I believe they handle the refresh/expunge/flush system and changes are then re-queried to the DB if one of these happened. Opposed to if I were to simply create a caching property in the model with a simple:
def get_books(self):
if self._books is None:
self._books = Book.query.filter(Book.user_id == self.id).all()
return self._books
This does not work well with flush/refresh/expunge from SQLAlchemy.
So, How can I change get_books() to use the caching system from SQLAlchemy ?
Edit 1:
I realized that the solution provided under is not perfect, because it caches for the current object. If you have two instances of the same user, and call get_books on both, two queries will be made because the caching applies only on the instance, not globally, contrary to SQLAlchemy.
The reason is simple - I believe - but still unclear how to apply it in my case: The object is defined at the class level, not the instance (books = relationship()), and they build their own query internally, so they can cache it based on the query.
In the solution I gave, the memoize_getter is unaware of the query made, and as such, cannot cache it for the same value accros multiple instance, so any identical call made to another instance will query the database.
Original answer:
I've been trying to wrap my head around SQLAlchemy's code (wow that's dense!), and I think I figured it out!
A relationship, at least when being set as "lazy='select'" (default), is a InstrumentedAttribute, which contains a get function that does the following :
def __get__(self, instance, owner):
if instance is None:
return self
dict_ = instance_dict(instance)
if self._supports_population and self.key in dict_:
return dict_[self.key]
else:
try:
state = instance_state(instance)
except AttributeError as err:
util.raise_(
orm_exc.UnmappedInstanceError(instance),
replace_context=err,
)
return self.impl.get(state, dict_)
So, a basic caching system, respecting SQLAlchemy, would be something like:
from sqlalchemy.orm.base import instance_dict
def get_books(self):
dict_ = instance_dict(self)
if 'books' not in dict_:
dict_['books'] = Book.query.filter(Book.user_id == self.id).all()
return dict_['books']
Now, we can push the vice a bit further, and do ... a decorator (oh sweet):
def memoize_getter(f):
#functools.wraps(f)
def decorator(instance, *args, **kwargs):
property_name = f.__name__.replace('get_', '')
dict_ = instance_dict(instance)
if property_name not in dict_:
dict_[property_name] = f(instance, *args, **kwargs)
return dict_[property_name]
return decorator
Thus transforming the original method to :
class User:
#memoize_getter
def get_books(self):
return Book.query.filter(Book.user_id == self.id).all()
If someone has a better solution, I'm eagerly interested!

Django move models classmethod to another file

I have model
Order(models.Model):
name = models.Charfield()
#classmethod
do_something(cls):
print('do soemthing')
What I want to do is to move do_something method from my model to another file.I want to do it because I have several other big methods in this model and want to structure the code, don't like lengh of this file. It's getting big > 700 lines of code.
So I want to move my method to another file and import it, so it still can be used like modelmethod
like this:
Order.do_something()
Any ideas?
Use inheritance -- (wiki)
# some_package/some_module.py
class MyFooKlass:
#classmethod
def do_something(cls):
# do something
return 'foo'
# my_app/models.py
from some_package.some_module import MyFooKlass
class Order(models.Model, MyFooKlass):
name = models.CharField()

Singleton only containing a dict, statically accesible

I want to provide a class, that contains a dictionary, that should be accessible all over my package. This class should be initialized by another class, which is a database connector.
From the database I retrieve the mapping but I want to do this only once on initialization of the database connector. Furthermore this mapping than should be availabe to all other modules in my package without getting the instance of the database connector passed through all function calls.
I thought about using a Singleton pattern and tried some stuff from this SO post. But I can't find a working solution.
I tried it this way with metaclass:
The mapping class:
class Singleton(type):
_instances = {}
def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
return cls._instances[cls]
class CFMapping(metaclass=Singleton):
def __init__(self, cf_mapping: dict):
self._cf_mapping = cf_mapping
#classmethod
def get_cf_by_name(cls, name: str) -> str:
return cls._cf_mapping.get(name)
The database connector
class DBConnector:
def __init__(....):
# some init logic, connection to db etc...
self.cf_mapping = self.get_cf_mapping() # just returning a dict from a rest call
Now i expect the mapping to be accesible via the DBConnector instance.
But at other scripts where I don't have this instance I would like to access the mapping just over a static/class method like this:
CFMapping.get_cf_by_name("someName")
# leads to AttributeError as CFMapping has no attribute _cf_mapping
Is there a way to get this construct to work the way I want it to or is there some better approach for some problem like this?

Pyramid Hybrid application (traversal + url dispatch)

I've started using pyramid recently and I have some best-practice/general-concept questions about it's hybrid application approach. Let me try to mock a small but complex scenario for what I'm trying to do...
scenario
Say I'm building a website about movies, a place where users can go to add movies, like them and do other stuff with them. Here's a desired functionality:
/ renders templates/root.html
/movies renders templates/default.html, shows a list of movies
/movies/123456 shows details about a movie
/movies/123456/users shows list of users that edited this movie
/users renders templates/default.html, shows a list of users
/users/654321 shows details about a user
/users/654321/movies shows a list of favorite movies for this user
/reviews/movies renders templates/reviews.html, shows url_fetched movie reviews
/admin place where you can log in and change stuff
/admin/movies renders templates/admin.html, shows a list of editable movies
/admin/movies/123456 renders templates/form.html, edit this movie
extras:
ability to handle nested resources, for example movies/123/similar/234/similar/345, where similar is a property of movie class that lists ids of related movies. Or maybe more clear example would be: companies/123/partners/234/clients/345...
/movies/123456.json details about a movie in JSON format
/movies/123456.xml details about a movie in XML format
RESTFull methods (GET, PUT, DELETE..) with authorization headers for resource handling
approach
This is what I've done so far (my views are class based, for simplicity, I'll list just decorators...):
# resources.py
class Root(object):
__name__ = __parent__ = None
def __getitem__(self, name):
return None
def factory(request):
# pseudo code...
# checks for database model that's also a resource
if ModelResource:
return ModelResource()
return Root()
# main.py
def notfound(request):
return HTTPNotFound()
def wsgi_app():
config = Configurator()
config.add_translation_dirs('locale',)
config.add_renderer('.html', Jinja2Renderer)
# Static
config.add_static_view('static', 'static')
# Root
config.add_route('root', '/')
# Admin
config.add_route('admin', '/admin/*traverse', factory='factory')
config.add_route('default', '/{path}/*traverse', factory='factory')
config.add_notfound_view(notfound, append_slash=True)
config.scan('views')
return config.make_wsgi_app()
# views/root.py
#view_config(route_name='root', renderer="root.html")
def __call__():
# views/default.py
#view_defaults(route_name='default')
class DefaultView(BaseView):
#view_config(context=ModelResource, renderer="default.html")
def with_context():
#view_config()
def __call__():
# views/admin.py
#view_defaults(route_name='admin')
class AdminView(BaseView):
#view_config(context=ModelResource, renderer="admin.html")
def default(self):
#view_config(renderer="admin.html")
def __call__(self):
And following piece of code is from my real app. ModelResource is used as context for view lookup, and this is basically the reason for this post... Since all my models (I'm working with Google App Engine datastore) have same basic functionality they extend specific superclass. My first instinct was to add traversal functionality at this level, that's why I created ModelResource (additional explanation in code comments), but I'm begining to regret it :) So I'm looking for some insight and ideas how to handle this.
class ModelResource(ndb.Model):
def __getitem__(self, name):
module = next(module for module in application.modules if module.get('class') == self.__class__.__name__)
# this can be read as: if name == 'movies' or name == 'users' or .....
if name in module.get('nodes'):
# with this setup I can set application.modules[0]['nodes'] = [u'movies', u'films', u'фильми' ]
# and use any of the defined alternatives to find a resource
# return an empty instance of the resource which can be queried in view
return self
# my models use unique numerical IDs
elif re.match(r'\d+', name):
# return instance with supplied ID
cls = self.__class__
return cls.get_by_id(name)
# this is an attempt to solve nesting issue
# if this model has repeated property it should return the class
# of the child item(s)
# for now I'm just displaying the property's value...
elif hasattr(self, name):
# TODO: ndb.KeyProperty, ndb.StructuredProperty
return getattr(self, name)
# this is an option to find resource by slug instead of ID...
elif re.match(r'\w+', name):
cls = self.__class__
instance = cls.query(cls.slug == name).get()
if instance:
return instance
raise KeyError
questions
I have basically two big questions (widh some sub-questions):
How should I handle traversal in described scenario?
Should I extend some class, or implement an interface, or something else?
Should traversal be handled at model level (movie model, or it's superclass would have __getitem__ method)? Should resource be a model instance?
What's the best practice for __getitem__ that returns collection (list) of resources? In this scenario /movies/
My ModelResource in the code above is not location aware... I'm having trouble getting __public__ and __name__ to work, probably because this is the wrong way to do traversal :) I'm guessing once I find the right way, nested resources shouldn't be a problem.
How can I switch back from traversal to url dispatching?
For the extra stuff: How can I set a different renderer to handle JSON requests? Before I added traversal I configured config.add_route('json', '/{path:.*}.json') and it worked with appropriate view, but now this route is never matched...
Same problem as above - I added a view that handles HTTP methods #view_config(request_method='GET'), but it's never matched in this configuration.
Sorry for the long post, but it's fairly complex scenario. I should probably mention that real app has 10-15 models atm, so I'm looking for solution that would handle everything in one place - I want to avoid manually setting up Resource Tree...

Resources